Release 950901
Thu Aug 31 17:19:57 1995 Alexandre Julliard <julliard@sunsite.unc.edu> * [Configure] Added compile-time option for IPC. * [configure.in] Added command-line options for language, IPC and malloc debugging. * [controls/menu.c] WM_MENUSELECT was sometimes sent to the wrong window. * [debugger/break.c] For the 'next' command, only step over instruction that require it. This allows 'next' to do the right thing with jmp and ret instructions. * [ipc/*.c] [memory/atom.c] [memory/global.c] IPC can now be configured out at compile-time. * [loader/task.c] Bug fix in TASK_Reschedule() that could cause a task to be deleted twice. * [miscemu/dosmem.c] (New file) Partial emulation of the BIOS data segment. * [miscemu/instr.c] Trap attempts to access selector 0x40 and remap the access to segment __0040H. * [tools/build.c] Fixed bug in CallTo32_LargeStack() that caused problems when compiling Wine with the -fomit-frame-pointer option. * [windows/message.c] Fixed bug in hardware event handling that could cause some events to get ignored. Sat Aug 26 13:12:59 IST 1995 Michael Veksler <mveksler@vnet.ibm.com> * [ipc/README] [ipc/dde.tex] LaTeX documentation for the ipc and DDE stuff. Wed Aug 23 22:01:23 GMT 1995 Michael Veksler <mveksler@vnet.ibm.com> * [ipc/Imakefile] [ipc/wine_test_stub.c] Fixed IPC testing. Now it can be compiled with "make tests" Wed Aug 23 21:04:14 1995 Fons Botman <botman@wab-tis.rabobank.nl> * [if1632/kernel.spec] [include/windows.h] [misc/main.c] Added GetWinDebugInfo/SetWinDebugInfo stub for player.exe Sun Aug 20 13:49:42 1995 Marcus Meissner <msmeissn@faui01.informatik.uni-erlangen.de> * [miscemu/int21.c] Misc fix to int21,ah=40 (write) to match _lwrite(). AX=0x440A (check if handle is remote) added. * [multimedia/mmsystem.c] Moved mciSendString to mcistring.c. * [multimedia/mcistring.c] New file, string interface for MCI (not complete, not thoroughly tested). * [multimedia/audio.c] IOCTL prints errors; one paranoid check disabled. * [misc/file.c] Misc operator precedence fixes. * [if1632/gdi.spec] [objects/bitblt.c] Stub for FastWindowFrame (parameters not correct). Sat Aug 19 01:31:23 1995 Graham Menhennitt <gfm@werple.mira.net.au> * [loader/ne_image.c] Preliminary support for iterated segments. Sat Aug 19 00:43:04 1995 Andrew Taylor (andrew@riscan.com) * [windows/mapping.c] In function MAPPING_FixIsotropic(), VportExt[XY] is multiplied by the absolute value of (ydim / xdim) or (xdim / ydim). Thu Aug 15 23:00:16 Gregory Trubetskoy <grisha@mira.com> * [objects/oembitmap.c] Added some includes for Windows 95. * [include/sysmetrics.h] Added some sysmetrics for Windows 95. * [include/bitmaps/*95] New files: obm_close_95, obm_closed_95, obm_reduce_95, obm_reduced_95 obm_zoom_95, obm_zoomd_95 - these are some pixmaps for Windows 95. Thu Aug 10 12:00:00 1995 Jan Willamowius (jan@janhh.shnet.org) * [misc/shell.c] [rc/sysres*.rc] The caption of the ShellAbout dialog box is language specific and should be defined in the resources.
This commit is contained in:
parent
808cb0436d
commit
b7258befe0
100 changed files with 4852 additions and 2801 deletions
23
ANNOUNCE
23
ANNOUNCE
|
@ -1,14 +1,15 @@
|
|||
This is release 950817 of Wine the MS Windows emulator. This is still a
|
||||
This is release 950901 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.
|
||||
|
||||
Patches should be submitted to "wine-new@amscons.com". Please don't forget
|
||||
to include a ChangeLog entry. I'll make a new release every other Sunday.
|
||||
to include a ChangeLog entry. I'll make a new release every other week.
|
||||
|
||||
WHAT'S NEW with Wine-950817: (see ChangeLog for details)
|
||||
- Built-in debugger improvements.
|
||||
- Multimedia fixes.
|
||||
- IPC can be disabled at run-time.
|
||||
WHAT'S NEW with Wine-950901: (see ChangeLog for details)
|
||||
- Accesses to BIOS segment 0x40 are trapped and emulated.
|
||||
- Multimedia improvements.
|
||||
- IPC can now be disabled at compile-time.
|
||||
- Documentation for the IPC code.
|
||||
- Lots of bug fixes.
|
||||
|
||||
See the README file in the distribution for installation instructions.
|
||||
|
@ -17,11 +18,11 @@ 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:
|
||||
|
||||
sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950817.tar.gz
|
||||
tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950817.tar.gz
|
||||
ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950817.tar.gz
|
||||
ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950817.tar.gz
|
||||
aris.com:/pub/linux/ALPHA/Wine/development/Wine-950817.tar.gz
|
||||
sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950901.tar.gz
|
||||
tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950901.tar.gz
|
||||
ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950901.tar.gz
|
||||
ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950901.tar.gz
|
||||
aris.com:/pub/linux/ALPHA/Wine/development/Wine-950901.tar.gz
|
||||
|
||||
It should also be available from any site that mirrors tsx-11 or sunsite.
|
||||
|
||||
|
|
105
ChangeLog
105
ChangeLog
|
@ -1,3 +1,108 @@
|
|||
Thu Aug 31 17:19:57 1995 Alexandre Julliard <julliard@sunsite.unc.edu>
|
||||
|
||||
* [Configure]
|
||||
Added compile-time option for IPC.
|
||||
|
||||
* [configure.in]
|
||||
Added command-line options for language, IPC and malloc
|
||||
debugging.
|
||||
|
||||
* [controls/menu.c]
|
||||
WM_MENUSELECT was sometimes sent to the wrong window.
|
||||
|
||||
* [debugger/break.c]
|
||||
For the 'next' command, only step over instruction that require
|
||||
it. This allows 'next' to do the right thing with jmp and ret
|
||||
instructions.
|
||||
|
||||
* [ipc/*.c] [memory/atom.c] [memory/global.c]
|
||||
IPC can now be configured out at compile-time.
|
||||
|
||||
* [loader/task.c]
|
||||
Bug fix in TASK_Reschedule() that could cause a task to be deleted
|
||||
twice.
|
||||
|
||||
* [miscemu/dosmem.c] (New file)
|
||||
Partial emulation of the BIOS data segment.
|
||||
|
||||
* [miscemu/instr.c]
|
||||
Trap attempts to access selector 0x40 and remap the access to
|
||||
segment __0040H.
|
||||
|
||||
* [tools/build.c]
|
||||
Fixed bug in CallTo32_LargeStack() that caused problems when
|
||||
compiling Wine with the -fomit-frame-pointer option.
|
||||
|
||||
* [windows/message.c]
|
||||
Fixed bug in hardware event handling that could cause some events
|
||||
to get ignored.
|
||||
|
||||
Sat Aug 26 13:12:59 IST 1995 Michael Veksler <mveksler@vnet.ibm.com>
|
||||
|
||||
* [ipc/README] [ipc/dde.tex]
|
||||
LaTeX documentation for the ipc and DDE stuff.
|
||||
|
||||
Wed Aug 23 22:01:23 GMT 1995 Michael Veksler <mveksler@vnet.ibm.com>
|
||||
|
||||
* [ipc/Imakefile] [ipc/wine_test_stub.c]
|
||||
Fixed IPC testing. Now it can be compiled with "make tests"
|
||||
|
||||
Wed Aug 23 21:04:14 1995 Fons Botman <botman@wab-tis.rabobank.nl>
|
||||
|
||||
* [if1632/kernel.spec] [include/windows.h] [misc/main.c]
|
||||
Added GetWinDebugInfo/SetWinDebugInfo stub for player.exe
|
||||
|
||||
Sun Aug 20 13:49:42 1995 Marcus Meissner <msmeissn@faui01.informatik.uni-erlangen.de>
|
||||
|
||||
* [miscemu/int21.c]
|
||||
Misc fix to int21,ah=40 (write) to match _lwrite().
|
||||
AX=0x440A (check if handle is remote) added.
|
||||
|
||||
* [multimedia/mmsystem.c]
|
||||
Moved mciSendString to mcistring.c.
|
||||
|
||||
* [multimedia/mcistring.c]
|
||||
New file, string interface for MCI (not complete, not thoroughly
|
||||
tested).
|
||||
|
||||
* [multimedia/audio.c]
|
||||
IOCTL prints errors; one paranoid check disabled.
|
||||
|
||||
* [misc/file.c]
|
||||
Misc operator precedence fixes.
|
||||
|
||||
* [if1632/gdi.spec] [objects/bitblt.c]
|
||||
Stub for FastWindowFrame (parameters not correct).
|
||||
|
||||
Sat Aug 19 01:31:23 1995 Graham Menhennitt <gfm@werple.mira.net.au>
|
||||
|
||||
* [loader/ne_image.c]
|
||||
Preliminary support for iterated segments.
|
||||
|
||||
Sat Aug 19 00:43:04 1995 Andrew Taylor (andrew@riscan.com)
|
||||
|
||||
* [windows/mapping.c]
|
||||
In function MAPPING_FixIsotropic(), VportExt[XY] is multiplied by
|
||||
the absolute value of (ydim / xdim) or (xdim / ydim).
|
||||
|
||||
Thu Aug 15 23:00:16 Gregory Trubetskoy <grisha@mira.com>
|
||||
|
||||
* [objects/oembitmap.c]
|
||||
Added some includes for Windows 95.
|
||||
|
||||
* [include/sysmetrics.h]
|
||||
Added some sysmetrics for Windows 95.
|
||||
|
||||
* [include/bitmaps/*95]
|
||||
New files: obm_close_95, obm_closed_95, obm_reduce_95, obm_reduced_95
|
||||
obm_zoom_95, obm_zoomd_95 - these are some pixmaps for Windows 95.
|
||||
|
||||
Thu Aug 10 12:00:00 1995 Jan Willamowius (jan@janhh.shnet.org)
|
||||
|
||||
* [misc/shell.c] [rc/sysres*.rc]
|
||||
The caption of the ShellAbout dialog box is language specific and
|
||||
should be defined in the resources.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Thu Aug 17 19:30:14 1995 Alexandre Julliard <julliard@sunsite.unc.edu>
|
||||
|
||||
|
|
|
@ -49,6 +49,12 @@ do
|
|||
done
|
||||
ALLDEFINES="$ALLDEFINES -ALANG\($LANGUAGE\)"
|
||||
|
||||
prompt "Inter-process communication" CONFIG_IPC N
|
||||
if [ CONFIG_IPC = 'Y' -o $CONFIG_IPC = 'y' ]
|
||||
then
|
||||
ALLDEFINES="$ALLDEFINES -DCONFIG_IPC"
|
||||
fi
|
||||
|
||||
prompt "Malloc debugging" MALLOC_DEBUGGING N
|
||||
if [ MALLOC_DEBUGGING = 'Y' -o $MALLOC_DEBUGGING = 'y' ]
|
||||
then
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#if defined(i386FreeBsd) || defined(FreeBSDArchitecture)
|
||||
MAKE = gmake
|
||||
CC = gcc -D__FreeBSD__
|
||||
#endif
|
||||
|
||||
DEFINES = AutoDefines -DUSE_READLINE
|
||||
|
|
11
Makefile.in
11
Makefile.in
|
@ -12,6 +12,7 @@
|
|||
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
DEFS = @DEFS@
|
||||
XINCL = @x_includes@
|
||||
TOPSRC = @top_srcdir@
|
||||
DIVINCL = -I$(TOPSRC)/include
|
||||
|
@ -22,7 +23,7 @@ LDLIBS = -lm
|
|||
LD = @LD@
|
||||
LANG = @LANG@
|
||||
LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
COMMONSUBDIRS = controls rc ipc loader misc multimedia objects windows
|
||||
|
||||
|
@ -53,7 +54,7 @@ wine: $(SUBDIRS) dummy
|
|||
$(CC) -o wine $(OBJS) $(LDOPTIONS) $(XDIR) $(XPM_LIB) $(XLIB) $(LDLIBS)
|
||||
|
||||
$(SUBDIRS): dummy
|
||||
@cd $@; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)' 'LANG=$(LANG)'
|
||||
@cd $@; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'DEFS=$(DEFS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)' 'LANG=$(LANG)'
|
||||
|
||||
depend:
|
||||
for i in $(SUBDIRS); do (cd $$i; $(MAKE) depend); done
|
||||
|
@ -63,14 +64,14 @@ etags:
|
|||
|
||||
clean:
|
||||
for i in $(SUBDIRS); do (cd $$i; $(MAKE) clean); done
|
||||
rm -f *.o \#*\# *~ wine wine.sym TAGS
|
||||
rm -f *.o \#*\# *~ *.bak wine wine.sym TAGS
|
||||
|
||||
distclean:
|
||||
for i in $(SUBDIRS); do (cd $$i; $(MAKE) distclean); done
|
||||
echo "/* autoconf.h generated automatically. Run Configure */" >autoconf.h
|
||||
echo "#error You must run Configure before you can build the makefiles." >>autoconf.h
|
||||
rm -f *.o \#*\# *~ wine wine.sym
|
||||
rm -f stamp-config config.* include/config.h Makefile
|
||||
rm -f *.o \#*\# *~ *.bak wine wine.sym TAGS
|
||||
rm -f config.* include/config.h Makefile
|
||||
|
||||
countryclean:
|
||||
for i in $(SUBDIRS); do (cd $$i; $(MAKE) countryclean); done
|
||||
|
|
|
@ -12,16 +12,19 @@ realises the problem later on. 'make' again and watch the output. Be
|
|||
sure to analyze the problem before you report it to the newsgroup.
|
||||
|
||||
2. What are these questions in Configure?
|
||||
Emulator/Library: You need an emulator when you want to run MS-Win
|
||||
binaries. You need a library when you want to compile the source code
|
||||
of a Windows program.
|
||||
Language: Wine can present the system menu in multiple languages. Select
|
||||
one of English, German, or Norwegian here.
|
||||
Malloc debugging: When enabled, the mtrace and mcheck GNU libc functions
|
||||
are called. You might want to set the MALLOC_TRACE environment variable
|
||||
to a trace file name. If your system supports another way of malloc
|
||||
debugging, feel free to add it.
|
||||
Config file: Sets the Wine environment. See README for details.
|
||||
- Emulator/Library: You need an emulator when you want to run MS-Win
|
||||
binaries. You need a library when you want to compile the source code
|
||||
of a Windows program.
|
||||
- Language: Wine can present the system menu in multiple languages. Select
|
||||
one of English, German, or Norwegian here.
|
||||
- Inter-process communication: Allows setting up a DDE conversation
|
||||
between different instances of Wine. Only really useful when
|
||||
building Wine as a library.
|
||||
- Malloc debugging: When enabled, the mtrace and mcheck GNU libc functions
|
||||
are called. You might want to set the MALLOC_TRACE environment variable
|
||||
to a trace file name. If your system supports another way of malloc
|
||||
debugging, feel free to add it.
|
||||
- Config file: Sets the Wine environment. See README for details.
|
||||
|
||||
3. BAR.EXE used to work, but does not work anymore
|
||||
Look at the ChangeLog to see what files have been changed. Try to undo
|
||||
|
|
365
configure
vendored
365
configure
vendored
|
@ -12,6 +12,12 @@
|
|||
ac_help=
|
||||
ac_default_prefix=/usr/local
|
||||
# Any additions from configure.in:
|
||||
ac_help="$ac_help
|
||||
--with-language=LANG change the default language (LANG=En/De/No)"
|
||||
ac_help="$ac_help
|
||||
--with-ipc use inter-process communication for DDE"
|
||||
ac_help="$ac_help
|
||||
--with-malloc-debug enable malloc() debugging"
|
||||
ac_help="$ac_help
|
||||
--with-x use the X Window System"
|
||||
|
||||
|
@ -402,11 +408,38 @@ fi
|
|||
|
||||
|
||||
|
||||
|
||||
# We want these before the checks, so the checks can modify their values.
|
||||
test -z "$CFLAGS" && CFLAGS="-g -O2 -Wall"
|
||||
test -z "$LDFLAGS" && LDFLAGS=-g
|
||||
|
||||
# Check whether --with-language or --without-language was given.
|
||||
withval="$with_language"
|
||||
if test -n "$withval"; then
|
||||
LANG="-ALANG\($withval\)"
|
||||
else
|
||||
LANG="-ALANG\(En\)"
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-ipc or --without-ipc was given.
|
||||
withval="$with_ipc"
|
||||
if test -n "$withval"; then
|
||||
cat >> confdefs.h <<\EOF
|
||||
#define CONFIG_IPC 1
|
||||
EOF
|
||||
|
||||
fi
|
||||
|
||||
# Check whether --with-malloc-debug or --without-malloc-debug was given.
|
||||
withval="$with_malloc_debug"
|
||||
if test -n "$withval"; then
|
||||
cat >> confdefs.h <<\EOF
|
||||
#define MALLOC_DEBUGGING 1
|
||||
EOF
|
||||
|
||||
fi
|
||||
|
||||
|
||||
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
|
||||
set dummy ${MAKE-make}; ac_make=$2
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
|
||||
|
@ -521,7 +554,7 @@ else
|
|||
# On the NeXT, cc -E runs the code through the compiler's parser,
|
||||
# not just through cpp.
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 525 "configure"
|
||||
#line 558 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <assert.h>
|
||||
Syntax Error
|
||||
|
@ -535,7 +568,7 @@ else
|
|||
rm -rf conftest*
|
||||
CPP="${CC-cc} -E -traditional-cpp"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 539 "configure"
|
||||
#line 572 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <assert.h>
|
||||
Syntax Error
|
||||
|
@ -621,7 +654,7 @@ test -z "$x_direct_test_library" && x_direct_test_library=Xt
|
|||
test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc
|
||||
test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 625 "configure"
|
||||
#line 658 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$x_direct_test_include>
|
||||
EOF
|
||||
|
@ -684,7 +717,7 @@ rm -f conftest*
|
|||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-l$x_direct_test_library $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 688 "configure"
|
||||
#line 721 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() { return 0; }
|
||||
|
@ -840,7 +873,7 @@ else
|
|||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-l$ac_lib $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 844 "configure"
|
||||
#line 877 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() { return 0; }
|
||||
|
@ -891,7 +924,7 @@ 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 <<EOF
|
||||
#line 895 "configure"
|
||||
#line 928 "configure"
|
||||
#include "confdefs.h"
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $ac_func(); below. */
|
||||
|
@ -943,7 +976,7 @@ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
|||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 947 "configure"
|
||||
#line 980 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
|
@ -971,122 +1004,12 @@ else
|
|||
fi
|
||||
done
|
||||
|
||||
ac_header_dirent=no
|
||||
for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
|
||||
echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 984 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <sys/types.h>
|
||||
#include <$ac_hdr>
|
||||
int main() { return 0; }
|
||||
int t() {
|
||||
DIR *dirp = 0;
|
||||
; return 0; }
|
||||
EOF
|
||||
if eval $ac_compile; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_header_dirent_$ac_safe=yes"
|
||||
else
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_header_dirent_$ac_safe=no"
|
||||
fi
|
||||
rm -f conftest*
|
||||
|
||||
fi
|
||||
if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
|
||||
echo "$ac_t""yes" 1>&6
|
||||
ac_tr_hdr=HAVE_`echo $ac_hdr | tr '[a-z]./\055' '[A-Z]___'`
|
||||
cat >> confdefs.h <<EOF
|
||||
#define $ac_tr_hdr 1
|
||||
EOF
|
||||
ac_header_dirent=$ac_hdr; break
|
||||
else
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
done
|
||||
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
|
||||
if test $ac_header_dirent = dirent.h; then
|
||||
echo $ac_n "checking for -ldir""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_dir'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-ldir $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1023 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() { return 0; }
|
||||
int t() {
|
||||
opendir()
|
||||
; return 0; }
|
||||
EOF
|
||||
if eval $ac_link; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_dir=yes"
|
||||
else
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_dir=no"
|
||||
fi
|
||||
rm -f conftest*
|
||||
LIBS="$ac_save_LIBS"
|
||||
|
||||
fi
|
||||
if eval "test \"`echo '$ac_cv_lib_'dir`\" = yes"; then
|
||||
echo "$ac_t""yes" 1>&6
|
||||
LIBS="$LIBS -ldir"
|
||||
else
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
|
||||
else
|
||||
echo $ac_n "checking for -lx""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_x'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-lx $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1057 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() { return 0; }
|
||||
int t() {
|
||||
opendir()
|
||||
; return 0; }
|
||||
EOF
|
||||
if eval $ac_link; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_x=yes"
|
||||
else
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_x=no"
|
||||
fi
|
||||
rm -f conftest*
|
||||
LIBS="$ac_save_LIBS"
|
||||
|
||||
fi
|
||||
if eval "test \"`echo '$ac_cv_lib_'x`\" = yes"; then
|
||||
echo "$ac_t""yes" 1>&6
|
||||
LIBS="$LIBS -lx"
|
||||
else
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
|
||||
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 <<EOF
|
||||
#line 1090 "configure"
|
||||
#line 1013 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -1140,7 +1063,7 @@ if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
|
|||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1144 "configure"
|
||||
#line 1067 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() { return 0; }
|
||||
|
@ -1217,7 +1140,7 @@ else
|
|||
ac_cv_c_cross=yes
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1221 "configure"
|
||||
#line 1144 "configure"
|
||||
#include "confdefs.h"
|
||||
main(){return(0);}
|
||||
EOF
|
||||
|
@ -1238,7 +1161,7 @@ if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
|
|||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1242 "configure"
|
||||
#line 1165 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -1260,7 +1183,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
|
||||
#line 1264 "configure"
|
||||
#line 1187 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <string.h>
|
||||
EOF
|
||||
|
@ -1278,7 +1201,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
|
||||
#line 1282 "configure"
|
||||
#line 1205 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <stdlib.h>
|
||||
EOF
|
||||
|
@ -1299,7 +1222,7 @@ if test "$cross_compiling" = yes; then
|
|||
ac_cv_header_stdc=no
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1303 "configure"
|
||||
#line 1226 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <ctype.h>
|
||||
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
|
||||
|
@ -1333,7 +1256,7 @@ 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 <<EOF
|
||||
#line 1337 "configure"
|
||||
#line 1260 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <sys/types.h>
|
||||
#if STDC_HEADERS
|
||||
|
@ -1364,82 +1287,6 @@ if test -z "${top_srcdir}"; then
|
|||
TOP_SRCDIR="."
|
||||
else
|
||||
TOP_SRCDIR="${top_srcdir}"
|
||||
fi
|
||||
echo $ac_n "checking for language in autoconf.h""... $ac_c" 1>&6
|
||||
if test -f ${TOP_SRCDIR}/autoconf.h; then
|
||||
LANG=`tr ' ' '\n' < ${TOP_SRCDIR}/autoconf.h | grep '\-ALANG' | head -1`
|
||||
if test -n "${LANG}"; then
|
||||
echo "$ac_t""`echo "${LANG}" | cut -b9-10`" 1>&6
|
||||
fi
|
||||
fi
|
||||
if test -z "${LANG}"; then
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
|
||||
|
||||
if test -z "${LANG}"; then
|
||||
echo $ac_n "checking for language through domainname""... $ac_c" 1>&6
|
||||
DNAME=`domainname`
|
||||
if test `echo "${DNAME}" | grep -c "\.no"` -ne 0; then
|
||||
LANG="-ALANG\(No\)"
|
||||
echo "$ac_t""No" 1>&6
|
||||
fi
|
||||
if test `echo "${DNAME}" | grep -c "\.de"` -ne 0; then
|
||||
LANG="-ALANG\(De\)"
|
||||
echo "$ac_t""De" 1>&6
|
||||
fi
|
||||
if test `echo "${DNAME}" | grep -c "\.uk"` -ne 0; then
|
||||
LANG="-ALANG\(En\)"
|
||||
echo "$ac_t""En" 1>&6
|
||||
fi
|
||||
if test `echo "${DNAME}" | grep -c "\.com"` -ne 0; then
|
||||
LANG="-ALANG\(En\)"
|
||||
echo "$ac_t""En" 1>&6
|
||||
fi
|
||||
if test `echo "${DNAME}" | grep -c "\.edu"` -ne 0; then
|
||||
LANG="-ALANG\(En\)"
|
||||
echo "$ac_t""En" 1>&6
|
||||
fi
|
||||
if test `echo "${DNAME}" | grep -c "\.gov"` -ne 0; then
|
||||
LANG="-ALANG\(En\)"
|
||||
echo "$ac_t""En" 1>&6
|
||||
fi
|
||||
if test -z "${LANG}"; then
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "${LANG}"; then
|
||||
echo $ac_n "checking for linux""... $ac_c" 1>&6
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1416 "configure"
|
||||
#include "confdefs.h"
|
||||
#ifdef linux
|
||||
yes
|
||||
#endif
|
||||
|
||||
EOF
|
||||
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||
egrep "yes" >/dev/null 2>&1; then
|
||||
rm -rf conftest*
|
||||
echo "$ac_t""yes" 1>&6
|
||||
echo $ac_n "checking for language by examining keymap""... $ac_c" 1>&6
|
||||
if test `dumpkeys | grep "keycode *26" | tr ' ' '\n' | grep -c udiaeresis` -ne 0; then
|
||||
echo "$ac_t""De" 1>&6
|
||||
LANG='-ALANG\(De\)'
|
||||
else
|
||||
echo "$ac_t""no" 1>&6
|
||||
LANG='-ALANG\(En\)'
|
||||
fi
|
||||
|
||||
else
|
||||
rm -rf conftest*
|
||||
echo "$ac_t""no" 1>&6
|
||||
LANG='-ALANG\(En\)'
|
||||
|
||||
fi
|
||||
rm -f conftest*
|
||||
|
||||
fi
|
||||
|
||||
echo $ac_n "checking for wine.ini in autoconf.h""... $ac_c" 1>&6
|
||||
|
@ -1518,7 +1365,19 @@ fi
|
|||
|
||||
trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
|
||||
|
||||
DEFS=-DHAVE_CONFIG_H
|
||||
# Transform confdefs.h into DEFS.
|
||||
# Protect against shell expansion while executing Makefile rules.
|
||||
# Protect against Makefile macro expansion.
|
||||
cat > conftest.defs <<\EOF
|
||||
s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%-D\1=\2%g
|
||||
s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
|
||||
s%\[%\\&%g
|
||||
s%\]%\\&%g
|
||||
s%\$%$$%g
|
||||
EOF
|
||||
DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
|
||||
rm -f conftest.defs
|
||||
|
||||
|
||||
# Without the "./", some shells look in PATH for config.status.
|
||||
: ${CONFIG_STATUS=./config.status}
|
||||
|
@ -1555,7 +1414,7 @@ done
|
|||
|
||||
ac_given_srcdir=$srcdir
|
||||
|
||||
trap 'rm -fr `echo "controls/Makefile ipc/Makefile loader/Makefile memory/Makefile misc/Makefile miscemu/Makefile multimedia/Makefile objects/Makefile windows/Makefile rc/Makefile debugger/Makefile debugger/readline/Makefile tools/Makefile if1632/Makefile Makefile autoconf.h include/config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
|
||||
trap 'rm -fr `echo "controls/Makefile ipc/Makefile loader/Makefile memory/Makefile misc/Makefile miscemu/Makefile multimedia/Makefile objects/Makefile windows/Makefile rc/Makefile debugger/Makefile debugger/readline/Makefile tools/Makefile if1632/Makefile Makefile autoconf.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
|
||||
|
||||
# Protect against being on the right side of a sed subst in config.status.
|
||||
sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\\\&%]/\\\\&/g;
|
||||
|
@ -1571,6 +1430,7 @@ s%@LIBS@%$LIBS%g
|
|||
s%@exec_prefix@%$exec_prefix%g
|
||||
s%@prefix@%$prefix%g
|
||||
s%@program_transform_name@%$program_transform_name%g
|
||||
s%@LANG@%$LANG%g
|
||||
s%@SET_MAKE@%$SET_MAKE%g
|
||||
s%@CC@%$CC%g
|
||||
s%@CPP@%$CPP%g
|
||||
|
@ -1583,7 +1443,6 @@ s%@x_libraries@%$x_libraries%g
|
|||
s%@LIBOBJS@%$LIBOBJS%g
|
||||
s%@LD@%$LD%g
|
||||
s%@LDCOMBINEFLAGS@%$LDCOMBINEFLAGS%g
|
||||
s%@LANG@%$LANG%g
|
||||
s%@WINE_INI_GLOBAL@%$WINE_INI_GLOBAL%g
|
||||
|
||||
CEOF
|
||||
|
@ -1641,104 +1500,8 @@ s%@top_srcdir@%$top_srcdir%g
|
|||
fi; done
|
||||
rm -f conftest.subs
|
||||
|
||||
# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
|
||||
# NAME is the cpp macro being defined and VALUE is the value it is being given.
|
||||
#
|
||||
# ac_d sets the value in "#define NAME VALUE" lines.
|
||||
ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
|
||||
ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
|
||||
ac_dC='\3'
|
||||
ac_dD='%g'
|
||||
# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
|
||||
ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
|
||||
ac_uB='\([ ]\)%\1#\2define\3'
|
||||
ac_uC=' '
|
||||
ac_uD='\4%g'
|
||||
# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
|
||||
ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
|
||||
ac_eB='$%\1#\2define\3'
|
||||
ac_eC=' '
|
||||
ac_eD='%g'
|
||||
|
||||
CONFIG_HEADERS=${CONFIG_HEADERS-"include/config.h"}
|
||||
for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
|
||||
# Support "outfile[:infile]", defaulting infile="outfile.in".
|
||||
case "$ac_file" in
|
||||
*:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
|
||||
ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
|
||||
*) ac_file_in="${ac_file}.in" ;;
|
||||
esac
|
||||
|
||||
echo creating $ac_file
|
||||
|
||||
rm -f conftest.frag conftest.in conftest.out
|
||||
cp $ac_given_srcdir/$ac_file_in conftest.in
|
||||
|
||||
EOF
|
||||
|
||||
# Transform confdefs.h into a sed script conftest.vals that substitutes
|
||||
# the proper values into config.h.in to produce config.h. And first:
|
||||
# Protect against being on the right side of a sed subst in config.status.
|
||||
# Protect against being in an unquoted here document in config.status.
|
||||
rm -f conftest.vals
|
||||
cat > conftest.hdr <<\EOF
|
||||
s/[\\&%]/\\&/g
|
||||
s%[\\$`]%\\&%g
|
||||
s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
|
||||
s%ac_d%ac_u%gp
|
||||
s%ac_u%ac_e%gp
|
||||
EOF
|
||||
sed -n -f conftest.hdr confdefs.h > conftest.vals
|
||||
rm -f conftest.hdr
|
||||
|
||||
# This sed command replaces #undef with comments. This is necessary, for
|
||||
# example, in the case of _POSIX_SOURCE, which is predefined and required
|
||||
# on some systems where configure will not decide to define it.
|
||||
cat >> conftest.vals <<\EOF
|
||||
s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
|
||||
EOF
|
||||
|
||||
# Break up conftest.vals because some shells have a limit on
|
||||
# the size of here documents, and old seds have small limits too.
|
||||
# Maximum number of lines to put in a single here document.
|
||||
ac_max_here_lines=12
|
||||
|
||||
rm -f conftest.tail
|
||||
while :
|
||||
do
|
||||
ac_lines=`grep -c . conftest.vals`
|
||||
# grep -c gives empty output for an empty file on some AIX systems.
|
||||
if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
|
||||
# Write a limited-size here document to conftest.frag.
|
||||
echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
|
||||
sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
|
||||
echo 'CEOF
|
||||
sed -f conftest.frag conftest.in > conftest.out
|
||||
rm -f conftest.in
|
||||
mv conftest.out conftest.in
|
||||
' >> $CONFIG_STATUS
|
||||
sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
|
||||
rm -f conftest.vals
|
||||
mv conftest.tail conftest.vals
|
||||
done
|
||||
rm -f conftest.vals
|
||||
|
||||
cat >> $CONFIG_STATUS <<\EOF
|
||||
rm -f conftest.frag conftest.h
|
||||
echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
|
||||
cat conftest.in >> conftest.h
|
||||
rm -f conftest.in
|
||||
if cmp -s $ac_file conftest.h 2>/dev/null; then
|
||||
echo "$ac_file is unchanged"
|
||||
rm -f conftest.h
|
||||
else
|
||||
rm -f $ac_file
|
||||
mv conftest.h $ac_file
|
||||
fi
|
||||
fi; done
|
||||
|
||||
|
||||
touch stamp-config
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x $CONFIG_STATUS
|
||||
|
|
83
configure.in
83
configure.in
|
@ -3,12 +3,23 @@ dnl Author: Michael Patra <micky@marie.physik.tu-berlin.de>
|
|||
dnl <patra@itp1.physik.tu-berlin.de>
|
||||
AC_REVISION([configure.in 1.00])
|
||||
AC_INIT(controls/edit.c)
|
||||
AC_CONFIG_HEADER(include/config.h)
|
||||
|
||||
# We want these before the checks, so the checks can modify their values.
|
||||
test -z "$CFLAGS" && CFLAGS="-g -O2 -Wall" AC_SUBST(CFLAGS)
|
||||
test -z "$LDFLAGS" && LDFLAGS=-g AC_SUBST(LDFLAGS)
|
||||
|
||||
AC_ARG_WITH(language,
|
||||
[ --with-language=LANG change the default language (LANG=En/De/No)],
|
||||
[LANG="-ALANG\($withval\)"],
|
||||
[LANG="-ALANG\(En\)"],)
|
||||
AC_SUBST(LANG)
|
||||
AC_ARG_WITH(ipc,
|
||||
[ --with-ipc use inter-process communication for DDE],
|
||||
[AC_DEFINE(CONFIG_IPC)])
|
||||
AC_ARG_WITH(malloc-debug,
|
||||
[ --with-malloc-debug enable malloc() debugging],
|
||||
[AC_DEFINE(MALLOC_DEBUGGING)])
|
||||
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_CC
|
||||
AC_PATH_X
|
||||
|
@ -41,70 +52,6 @@ TOP_SRCDIR="."
|
|||
else
|
||||
TOP_SRCDIR="${top_srcdir}"
|
||||
fi
|
||||
AC_MSG_CHECKING(for language in autoconf.h)
|
||||
if test -f ${TOP_SRCDIR}/autoconf.h; then
|
||||
LANG=`tr ' ' '\n' < ${TOP_SRCDIR}/autoconf.h | grep '\-ALANG' | head -1`
|
||||
if test -n "${LANG}"; then
|
||||
AC_MSG_RESULT(`echo "${LANG}" | cut -b9-10`)
|
||||
fi
|
||||
fi
|
||||
if test -z "${LANG}"; then
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_SUBST(LANG)
|
||||
|
||||
if test -z "${LANG}"; then
|
||||
AC_MSG_CHECKING(for language through domainname)
|
||||
DNAME=`domainname`
|
||||
if test `echo "${DNAME}" | grep -c "\.no"` -ne 0; then
|
||||
LANG="-ALANG\(No\)"
|
||||
AC_MSG_RESULT(No)
|
||||
fi
|
||||
if test `echo "${DNAME}" | grep -c "\.de"` -ne 0; then
|
||||
LANG="-ALANG\(De\)"
|
||||
AC_MSG_RESULT(De)
|
||||
fi
|
||||
if test `echo "${DNAME}" | grep -c "\.uk"` -ne 0; then
|
||||
LANG="-ALANG\(En\)"
|
||||
AC_MSG_RESULT(En)
|
||||
fi
|
||||
if test `echo "${DNAME}" | grep -c "\.com"` -ne 0; then
|
||||
LANG="-ALANG\(En\)"
|
||||
AC_MSG_RESULT(En)
|
||||
fi
|
||||
if test `echo "${DNAME}" | grep -c "\.edu"` -ne 0; then
|
||||
LANG="-ALANG\(En\)"
|
||||
AC_MSG_RESULT(En)
|
||||
fi
|
||||
if test `echo "${DNAME}" | grep -c "\.gov"` -ne 0; then
|
||||
LANG="-ALANG\(En\)"
|
||||
AC_MSG_RESULT(En)
|
||||
fi
|
||||
if test -z "${LANG}"; then
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "${LANG}"; then
|
||||
AC_MSG_CHECKING(for linux)
|
||||
AC_EGREP_CPP(yes,
|
||||
[#ifdef linux
|
||||
yes
|
||||
#endif
|
||||
], AC_MSG_RESULT(yes)
|
||||
AC_MSG_CHECKING(for language by examining keymap)
|
||||
if test `dumpkeys | grep "keycode *26" | tr ' ' '\n' | grep -c udiaeresis` -ne 0; then
|
||||
AC_MSG_RESULT(De)
|
||||
LANG='-ALANG\(De\)'
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
LANG='-ALANG\(En\)'
|
||||
fi
|
||||
,
|
||||
AC_MSG_RESULT(no)
|
||||
LANG='-ALANG\(En\)'
|
||||
)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(for wine.ini in autoconf.h)
|
||||
if test -f ${TOP_SRCDIR}/autoconf.h; then
|
||||
|
@ -129,11 +76,7 @@ fi
|
|||
fi
|
||||
AC_SUBST(WINE_INI_GLOBAL)
|
||||
|
||||
|
||||
test -z "$LDFLAGS" && LDFLAGS=-g AC_SUBST(LDFLAGS)
|
||||
|
||||
|
||||
AC_OUTPUT(controls/Makefile ipc/Makefile loader/Makefile memory/Makefile misc/Makefile miscemu/Makefile multimedia/Makefile objects/Makefile windows/Makefile rc/Makefile debugger/Makefile debugger/readline/Makefile tools/Makefile if1632/Makefile Makefile autoconf.h, [touch stamp-config])
|
||||
AC_OUTPUT(controls/Makefile ipc/Makefile loader/Makefile memory/Makefile misc/Makefile miscemu/Makefile multimedia/Makefile objects/Makefile windows/Makefile rc/Makefile debugger/Makefile debugger/readline/Makefile tools/Makefile if1632/Makefile Makefile autoconf.h)
|
||||
|
||||
echo
|
||||
echo "Configure finished. Do 'make depend; make' to compile Wine."
|
||||
|
|
|
@ -27,7 +27,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
|
|
@ -261,7 +261,6 @@ static void PB_Paint( HWND hButton, HDC hDC, WORD action )
|
|||
HBRUSH hOldBrush;
|
||||
char *text;
|
||||
DWORD dwTextSize;
|
||||
int delta;
|
||||
TEXTMETRIC tm;
|
||||
WND *wndPtr = WIN_FindWndPtr( hButton );
|
||||
BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
|
||||
|
|
109
controls/menu.c
109
controls/menu.c
|
@ -697,7 +697,7 @@ static BOOL MENU_ShowPopup(HWND hwndOwner, HMENU hmenu, WORD id, int x, int y)
|
|||
/***********************************************************************
|
||||
* MENU_SelectItem
|
||||
*/
|
||||
static void MENU_SelectItem( HMENU hmenu, WORD wIndex )
|
||||
static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, WORD wIndex )
|
||||
{
|
||||
MENUITEM *items;
|
||||
LPPOPUPMENU lppop;
|
||||
|
@ -739,8 +739,9 @@ static void MENU_SelectItem( HMENU hmenu, WORD wIndex )
|
|||
MENU_DrawMenuItem( lppop->hWnd, hdc, &items[lppop->FocusedItem], lppop->Height,
|
||||
!(lppop->wFlags & MF_POPUP) );
|
||||
dprintf_menu(stddeb,"Sending WM_MENUSELECT %04x %04x\n", items[lppop->FocusedItem].item_id,items[lppop->FocusedItem].item_flags);
|
||||
SendMessage(lppop->hWnd, WM_MENUSELECT, items[lppop->FocusedItem].item_id,
|
||||
MAKELONG( items[lppop->FocusedItem].item_flags | MF_MOUSESELECT, hmenu));
|
||||
SendMessage( hwndOwner, WM_MENUSELECT,
|
||||
items[lppop->FocusedItem].item_id,
|
||||
MAKELONG( items[lppop->FocusedItem].item_flags | MF_MOUSESELECT, hmenu));
|
||||
}
|
||||
}
|
||||
ReleaseDC( lppop->hWnd, hdc );
|
||||
|
@ -750,7 +751,7 @@ static void MENU_SelectItem( HMENU hmenu, WORD wIndex )
|
|||
/***********************************************************************
|
||||
* MENU_SelectNextItem
|
||||
*/
|
||||
static void MENU_SelectNextItem( HMENU hmenu )
|
||||
static void MENU_SelectNextItem( HWND hwndOwner, HMENU hmenu )
|
||||
{
|
||||
int i;
|
||||
MENUITEM *items;
|
||||
|
@ -766,13 +767,13 @@ static void MENU_SelectNextItem( HMENU hmenu )
|
|||
{
|
||||
if (!(items[i].item_flags & MF_SEPARATOR))
|
||||
{
|
||||
MENU_SelectItem( hmenu, i );
|
||||
MENU_SelectItem( hwndOwner, hmenu, i );
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (MENU_HasSysMenu( menu ))
|
||||
{
|
||||
MENU_SelectItem( hmenu, SYSMENU_SELECTED );
|
||||
MENU_SelectItem( hwndOwner, hmenu, SYSMENU_SELECTED );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -780,18 +781,19 @@ static void MENU_SelectNextItem( HMENU hmenu )
|
|||
{
|
||||
if (!(items[i].item_flags & MF_SEPARATOR))
|
||||
{
|
||||
MENU_SelectItem( hmenu, i );
|
||||
MENU_SelectItem( hwndOwner, hmenu, i );
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (MENU_HasSysMenu( menu )) MENU_SelectItem( hmenu, SYSMENU_SELECTED );
|
||||
if (MENU_HasSysMenu( menu ))
|
||||
MENU_SelectItem( hwndOwner, hmenu, SYSMENU_SELECTED );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MENU_SelectPrevItem
|
||||
*/
|
||||
static void MENU_SelectPrevItem( HMENU hmenu )
|
||||
static void MENU_SelectPrevItem( HWND hwndOwner, HMENU hmenu )
|
||||
{
|
||||
int i;
|
||||
MENUITEM *items;
|
||||
|
@ -807,13 +809,13 @@ static void MENU_SelectPrevItem( HMENU hmenu )
|
|||
{
|
||||
if (!(items[i].item_flags & MF_SEPARATOR))
|
||||
{
|
||||
MENU_SelectItem( hmenu, i );
|
||||
MENU_SelectItem( hwndOwner, hmenu, i );
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (MENU_HasSysMenu( menu ))
|
||||
{
|
||||
MENU_SelectItem( hmenu, SYSMENU_SELECTED );
|
||||
MENU_SelectItem( hwndOwner, hmenu, SYSMENU_SELECTED );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -821,11 +823,12 @@ static void MENU_SelectPrevItem( HMENU hmenu )
|
|||
{
|
||||
if (!(items[i].item_flags & MF_SEPARATOR))
|
||||
{
|
||||
MENU_SelectItem( hmenu, i );
|
||||
MENU_SelectItem( hwndOwner, hmenu, i );
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (MENU_HasSysMenu( menu )) MENU_SelectItem( hmenu, SYSMENU_SELECTED );
|
||||
if (MENU_HasSysMenu( menu ))
|
||||
MENU_SelectItem( hwndOwner, hmenu, SYSMENU_SELECTED );
|
||||
}
|
||||
|
||||
|
||||
|
@ -856,7 +859,7 @@ static HMENU MENU_GetSubPopup( HMENU hmenu )
|
|||
*
|
||||
* Hide the sub-popup menus of this menu.
|
||||
*/
|
||||
static void MENU_HideSubPopups( HMENU hmenu )
|
||||
static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu )
|
||||
{
|
||||
MENUITEM *item;
|
||||
POPUPMENU *menu, *submenu;
|
||||
|
@ -877,9 +880,9 @@ static void MENU_HideSubPopups( HMENU hmenu )
|
|||
hsubmenu = item->item_id;
|
||||
}
|
||||
submenu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hsubmenu );
|
||||
MENU_HideSubPopups( hsubmenu );
|
||||
MENU_HideSubPopups( hwndOwner, hsubmenu );
|
||||
if (submenu->hWnd) ShowWindow( submenu->hWnd, SW_HIDE );
|
||||
MENU_SelectItem( hsubmenu, NO_SELECTED_ITEM );
|
||||
MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM );
|
||||
}
|
||||
|
||||
|
||||
|
@ -902,7 +905,7 @@ static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu, BOOL selectFirst )
|
|||
{
|
||||
MENU_ShowPopup(hwndOwner, wndPtr->hSysMenu, 0, wndPtr->rectClient.left,
|
||||
wndPtr->rectClient.top - menu->Height - 2*SYSMETRICS_CYBORDER);
|
||||
if (selectFirst) MENU_SelectNextItem( wndPtr->hSysMenu );
|
||||
if (selectFirst) MENU_SelectNextItem( hwndOwner, wndPtr->hSysMenu );
|
||||
return wndPtr->hSysMenu;
|
||||
}
|
||||
item = ((MENUITEM *)USER_HEAP_LIN_ADDR(menu->hItems)) + menu->FocusedItem;
|
||||
|
@ -921,7 +924,7 @@ static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu, BOOL selectFirst )
|
|||
wndPtr->rectWindow.left + item->rect.left,
|
||||
wndPtr->rectWindow.top + item->rect.bottom );
|
||||
}
|
||||
if (selectFirst) MENU_SelectNextItem( (HMENU)item->item_id );
|
||||
if (selectFirst) MENU_SelectNextItem( hwndOwner, (HMENU)item->item_id );
|
||||
return (HMENU)item->item_id;
|
||||
}
|
||||
|
||||
|
@ -1027,7 +1030,7 @@ static BOOL MENU_ButtonDown( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent,
|
|||
{
|
||||
if (menu->wFlags & MF_POPUP)
|
||||
{
|
||||
MENU_HideSubPopups( hmenu );
|
||||
MENU_HideSubPopups( hwndOwner, hmenu );
|
||||
*hmenuCurrent = hmenu;
|
||||
}
|
||||
else return FALSE;
|
||||
|
@ -1037,8 +1040,8 @@ static BOOL MENU_ButtonDown( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent,
|
|||
}
|
||||
else
|
||||
{
|
||||
MENU_HideSubPopups( hmenu );
|
||||
MENU_SelectItem( hmenu, id );
|
||||
MENU_HideSubPopups( hwndOwner, hmenu );
|
||||
MENU_SelectItem( hwndOwner, hmenu, id );
|
||||
*hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, FALSE );
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -1081,8 +1084,8 @@ static BOOL MENU_ButtonUp( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent,
|
|||
hsubmenu = item->item_id;
|
||||
}
|
||||
/* Select first item of sub-popup */
|
||||
MENU_SelectItem( hsubmenu, NO_SELECTED_ITEM );
|
||||
MENU_SelectNextItem( hsubmenu );
|
||||
MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM );
|
||||
MENU_SelectNextItem( hwndOwner, hsubmenu );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1113,12 +1116,12 @@ static BOOL MENU_MouseMove( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent,
|
|||
}
|
||||
if (id == NO_SELECTED_ITEM)
|
||||
{
|
||||
MENU_SelectItem( *hmenuCurrent, NO_SELECTED_ITEM );
|
||||
MENU_SelectItem( hwndOwner, *hmenuCurrent, NO_SELECTED_ITEM );
|
||||
}
|
||||
else if (menu->FocusedItem != id)
|
||||
{
|
||||
MENU_HideSubPopups( hmenu );
|
||||
MENU_SelectItem( hmenu, id );
|
||||
MENU_HideSubPopups( hwndOwner, hmenu );
|
||||
MENU_SelectItem( hwndOwner, hmenu, id );
|
||||
*hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, FALSE );
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -1143,12 +1146,12 @@ static void MENU_KeyLeft( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent )
|
|||
hmenutmp = MENU_GetSubPopup( hmenuprev );
|
||||
if (hmenutmp != *hmenuCurrent) hmenuprev = hmenutmp;
|
||||
}
|
||||
MENU_HideSubPopups( hmenuprev );
|
||||
MENU_HideSubPopups( hwndOwner, hmenuprev );
|
||||
|
||||
if ((hmenuprev == hmenu) && !(menu->wFlags & MF_POPUP))
|
||||
{
|
||||
/* Select previous item on the menu bar */
|
||||
MENU_SelectPrevItem( hmenu );
|
||||
MENU_SelectPrevItem( hwndOwner, hmenu );
|
||||
if (*hmenuCurrent != hmenu)
|
||||
{
|
||||
/* A popup menu was displayed -> display the next one */
|
||||
|
@ -1186,8 +1189,8 @@ static void MENU_KeyRight( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent )
|
|||
/* If on menu-bar, go to next item */
|
||||
if (!(menu->wFlags & MF_POPUP))
|
||||
{
|
||||
MENU_HideSubPopups( hmenu );
|
||||
MENU_SelectNextItem( hmenu );
|
||||
MENU_HideSubPopups( hwndOwner, hmenu );
|
||||
MENU_SelectNextItem( hwndOwner, hmenu );
|
||||
if (*hmenuCurrent != hmenu)
|
||||
{
|
||||
/* A popup menu was displayed -> display the next one */
|
||||
|
@ -1203,7 +1206,7 @@ static void MENU_KeyRight( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent )
|
|||
hmenutmp = MENU_GetSubPopup( hmenuprev );
|
||||
if (hmenutmp != *hmenuCurrent) hmenuprev = hmenutmp;
|
||||
}
|
||||
MENU_HideSubPopups( hmenuprev );
|
||||
MENU_HideSubPopups( hwndOwner, hmenuprev );
|
||||
*hmenuCurrent = hmenuprev;
|
||||
}
|
||||
}
|
||||
|
@ -1293,17 +1296,17 @@ static BOOL MENU_TrackMenu( HMENU hmenu, WORD wFlags, int x, int y,
|
|||
switch(msg->wParam)
|
||||
{
|
||||
case VK_HOME:
|
||||
MENU_SelectItem( hmenuCurrent, NO_SELECTED_ITEM );
|
||||
MENU_SelectNextItem( hmenuCurrent );
|
||||
MENU_SelectItem( hwnd, hmenuCurrent, NO_SELECTED_ITEM );
|
||||
MENU_SelectNextItem( hwnd, hmenuCurrent );
|
||||
break;
|
||||
|
||||
case VK_END:
|
||||
MENU_SelectItem( hmenuCurrent, NO_SELECTED_ITEM );
|
||||
MENU_SelectPrevItem( hmenuCurrent );
|
||||
MENU_SelectItem( hwnd, hmenuCurrent, NO_SELECTED_ITEM );
|
||||
MENU_SelectPrevItem( hwnd, hmenuCurrent );
|
||||
break;
|
||||
|
||||
case VK_UP:
|
||||
MENU_SelectPrevItem( hmenuCurrent );
|
||||
MENU_SelectPrevItem( hwnd, hmenuCurrent );
|
||||
break;
|
||||
|
||||
case VK_DOWN:
|
||||
|
@ -1311,7 +1314,7 @@ static BOOL MENU_TrackMenu( HMENU hmenu, WORD wFlags, int x, int y,
|
|||
if (!(menu->wFlags & MF_POPUP) && (hmenuCurrent == hmenu))
|
||||
hmenuCurrent = MENU_ShowSubPopup( hwnd, hmenu, TRUE );
|
||||
else
|
||||
MENU_SelectNextItem( hmenuCurrent );
|
||||
MENU_SelectNextItem( hwnd, hmenuCurrent );
|
||||
break;
|
||||
|
||||
case VK_LEFT:
|
||||
|
@ -1357,7 +1360,7 @@ static BOOL MENU_TrackMenu( HMENU hmenu, WORD wFlags, int x, int y,
|
|||
else if (pos == (WORD)-1) MessageBeep(0);
|
||||
else
|
||||
{
|
||||
MENU_SelectItem( hmenuCurrent, pos );
|
||||
MENU_SelectItem( hwnd, hmenuCurrent, pos );
|
||||
fClosed = !MENU_ExecFocusedItem( hwnd, hmenuCurrent,
|
||||
&hmenuCurrent );
|
||||
|
||||
|
@ -1378,9 +1381,10 @@ static BOOL MENU_TrackMenu( HMENU hmenu, WORD wFlags, int x, int y,
|
|||
}
|
||||
USER_HEAP_FREE( hMsg );
|
||||
ReleaseCapture();
|
||||
MENU_HideSubPopups( hmenu );
|
||||
MENU_HideSubPopups( hwnd, hmenu );
|
||||
if (menu->wFlags & MF_POPUP) ShowWindow( menu->hWnd, SW_HIDE );
|
||||
MENU_SelectItem( hmenu, NO_SELECTED_ITEM );
|
||||
MENU_SelectItem( hwnd, hmenu, NO_SELECTED_ITEM );
|
||||
SendMessage( hwnd, WM_MENUSELECT, 0, MAKELONG( 0xffff, 0 ) );
|
||||
fEndMenuCalled = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1412,8 +1416,8 @@ void MENU_TrackKbdMenuBar( HWND hwnd, WORD wParam )
|
|||
if (!wndPtr->wIDmenu) return;
|
||||
SendMessage( hwnd, WM_ENTERMENULOOP, 0, 0 );
|
||||
/* Select first selectable item */
|
||||
MENU_SelectItem( wndPtr->wIDmenu, NO_SELECTED_ITEM );
|
||||
MENU_SelectNextItem( (HMENU)wndPtr->wIDmenu );
|
||||
MENU_SelectItem( hwnd, wndPtr->wIDmenu, NO_SELECTED_ITEM );
|
||||
MENU_SelectNextItem( hwnd, (HMENU)wndPtr->wIDmenu );
|
||||
MENU_TrackMenu( (HMENU)wndPtr->wIDmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
|
||||
0, 0, hwnd, NULL );
|
||||
SendMessage( hwnd, WM_EXITMENULOOP, 0, 0 );
|
||||
|
@ -1595,8 +1599,8 @@ BOOL HiliteMenuItem(HWND hWnd, HMENU hMenu, WORD wItemID, WORD wHilite)
|
|||
if (!(lpitem = MENU_FindItem( &hMenu, &wItemID, wHilite ))) return FALSE;
|
||||
if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu))) return FALSE;
|
||||
if (menu->FocusedItem == wItemID) return TRUE;
|
||||
MENU_HideSubPopups( hMenu );
|
||||
MENU_SelectItem( hMenu, wItemID );
|
||||
MENU_HideSubPopups( hWnd, hMenu );
|
||||
MENU_SelectItem( hWnd, hMenu, wItemID );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1957,16 +1961,13 @@ BOOL DestroyMenu(HMENU hMenu)
|
|||
*/
|
||||
HMENU GetSystemMenu(HWND hWnd, BOOL bRevert)
|
||||
{
|
||||
WND *wndPtr;
|
||||
wndPtr = WIN_FindWndPtr(hWnd);
|
||||
if (!bRevert) {
|
||||
return wndPtr->hSysMenu;
|
||||
}
|
||||
else {
|
||||
DestroyMenu(wndPtr->hSysMenu);
|
||||
wndPtr->hSysMenu = CopySysMenu();
|
||||
}
|
||||
return wndPtr->hSysMenu;
|
||||
WND *wndPtr = WIN_FindWndPtr( hWnd );
|
||||
if (!wndPtr) return 0;
|
||||
|
||||
if (!bRevert) return wndPtr->hSysMenu;
|
||||
DestroyMenu(wndPtr->hSysMenu);
|
||||
wndPtr->hSysMenu = CopySysMenu();
|
||||
return wndPtr->hSysMenu;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
|
|
@ -41,11 +41,12 @@ depend:
|
|||
|
||||
clean:
|
||||
(cd readline; $(MAKE) clean)
|
||||
rm -f *.o \#*\# *~ dbg.tab.c dbg.tab.h lex.yy.c y.tab.c y.tab.h tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
rm -f dbg.tab.c dbg.tab.h lex.yy.c y.tab.c y.tab.h
|
||||
|
||||
distclean:
|
||||
(cd readline; $(MAKE) distclean)
|
||||
rm -f *.o \#*\# *~ dbg.tab.c dbg.tab.h lex.yy.c y.tab.c y.tab.h tmp_make Makefile
|
||||
rm -f *.o \#*\# *~ *.bak dbg.tab.c dbg.tab.h lex.yy.c y.tab.c y.tab.h tmp_make Makefile
|
||||
|
||||
countryclean:
|
||||
|
||||
|
|
|
@ -65,6 +65,71 @@ static void DEBUG_SetOpcode( const DBG_ADDR *addr, BYTE op )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DEBUG_IsStepOverInstr
|
||||
*
|
||||
* Determine if the instruction at CS:EIP is an instruction that
|
||||
* we need to step over (like a call or a repetitive string move).
|
||||
*/
|
||||
static BOOL DEBUG_IsStepOverInstr( struct sigcontext_struct *context )
|
||||
{
|
||||
BYTE *instr = (BYTE *)PTR_SEG_OFF_TO_LIN(CS_reg(context),EIP_reg(context));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch(*instr)
|
||||
{
|
||||
/* Skip all prefixes */
|
||||
|
||||
case 0x2e: /* cs: */
|
||||
case 0x36: /* ss: */
|
||||
case 0x3e: /* ds: */
|
||||
case 0x26: /* es: */
|
||||
case 0x64: /* fs: */
|
||||
case 0x65: /* gs: */
|
||||
case 0x66: /* opcode size prefix */
|
||||
case 0x67: /* addr size prefix */
|
||||
case 0xf0: /* lock */
|
||||
case 0xf2: /* repne */
|
||||
case 0xf3: /* repe */
|
||||
instr++;
|
||||
continue;
|
||||
|
||||
/* Handle call instructions */
|
||||
|
||||
case 0xe8: /* call <offset> */
|
||||
case 0x9a: /* lcall <seg>:<off> */
|
||||
return TRUE;
|
||||
|
||||
case 0xff: /* call <regmodrm> */
|
||||
return (((instr[1] & 0x38) == 0x10) ||
|
||||
((instr[1] & 0x38) == 0x18));
|
||||
|
||||
/* Handle string instructions */
|
||||
|
||||
case 0x6c: /* insb */
|
||||
case 0x6d: /* insw */
|
||||
case 0x6e: /* outsb */
|
||||
case 0x6f: /* outsw */
|
||||
case 0xa4: /* movsb */
|
||||
case 0xa5: /* movsw */
|
||||
case 0xa6: /* cmpsb */
|
||||
case 0xa7: /* cmpsw */
|
||||
case 0xaa: /* stosb */
|
||||
case 0xab: /* stosw */
|
||||
case 0xac: /* lodsb */
|
||||
case 0xad: /* lodsw */
|
||||
case 0xae: /* scasb */
|
||||
case 0xaf: /* scasw */
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DEBUG_SetBreakpoints
|
||||
*
|
||||
|
@ -257,14 +322,18 @@ void DEBUG_RestartExecution( struct sigcontext_struct *context,
|
|||
break;
|
||||
|
||||
case EXEC_STEP_OVER: /* Stepping over a call */
|
||||
EFL_reg(DEBUG_context) &= ~STEP_FLAG;
|
||||
addr.off += instr_len;
|
||||
breakpoints[0].addr = addr;
|
||||
breakpoints[0].enabled = TRUE;
|
||||
breakpoints[0].in_use = TRUE;
|
||||
breakpoints[0].opcode = *(BYTE *)DBG_ADDR_TO_LIN( &addr );
|
||||
DEBUG_SetBreakpoints( TRUE );
|
||||
break;
|
||||
if (DEBUG_IsStepOverInstr(DEBUG_context))
|
||||
{
|
||||
EFL_reg(DEBUG_context) &= ~STEP_FLAG;
|
||||
addr.off += instr_len;
|
||||
breakpoints[0].addr = addr;
|
||||
breakpoints[0].enabled = TRUE;
|
||||
breakpoints[0].in_use = TRUE;
|
||||
breakpoints[0].opcode = *(BYTE *)DBG_ADDR_TO_LIN( &addr );
|
||||
DEBUG_SetBreakpoints( TRUE );
|
||||
break;
|
||||
}
|
||||
/* else fall through to single-stepping */
|
||||
|
||||
case EXEC_STEP_INSTR: /* Single-stepping an instruction */
|
||||
EFL_reg(DEBUG_context) |= STEP_FLAG;
|
||||
|
|
|
@ -115,7 +115,7 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
|
|||
{
|
||||
fprintf(stderr," %04x", *wdump++);
|
||||
addr.off += 2;
|
||||
if ((i % 10) == 7) {
|
||||
if ((i % 8) == 7) {
|
||||
fprintf(stderr,"\n");
|
||||
DEBUG_PrintAddress( &addr, dbg_mode );
|
||||
fprintf(stderr,": ");
|
||||
|
@ -133,7 +133,7 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
|
|||
} else
|
||||
fprintf(stderr," %c", *pnt++);
|
||||
addr.off++;
|
||||
if ((i % 32) == 7) {
|
||||
if ((i % 32) == 31) {
|
||||
fprintf(stderr,"\n");
|
||||
DEBUG_PrintAddress( &addr, dbg_mode );
|
||||
fprintf(stderr,": ");
|
||||
|
@ -147,7 +147,7 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
|
|||
{
|
||||
fprintf(stderr," %02x", (*pnt++) & 0xff);
|
||||
addr.off++;
|
||||
if ((i % 32) == 7) {
|
||||
if ((i % 16) == 15) {
|
||||
fprintf(stderr,"\n");
|
||||
DEBUG_PrintAddress( &addr, dbg_mode );
|
||||
fprintf(stderr,": ");
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
DEFS = @DEFS@
|
||||
XINCL = @x_includes@
|
||||
TOPSRC = @top_srcdir@
|
||||
DIVINCL = -I$(TOPSRC)/include
|
||||
LD = @LD@
|
||||
LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
|
||||
DIVDEFS = @DEFS@ -DHIDE -DANSI_ARROWS
|
||||
DIVDEFS = $(DEFS) -DHIDE -DANSI_ARROWS
|
||||
|
||||
|
||||
MODULE = readline
|
||||
|
@ -28,7 +29,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
|
|
@ -4,10 +4,6 @@
|
|||
*/
|
||||
#include "editline.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_TCGETATTR)
|
||||
#include <termios.h>
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ DLLS32 = gdi32.spec kernel32.spec shell32.spec user32.spec winprocs32.spec
|
|||
|
||||
OBJS = $(SRCS:.c=.o) $(DLLS16:.spec=.o) $(DLLS32:.spec=.o) call16.o call32.o
|
||||
|
||||
SFILES = $(DLLS16:.spec=.S)
|
||||
SPEC16_FILES = $(DLLS16:.spec=.S)
|
||||
SPEC32_FILES = $(DLLS32:.spec=.c)
|
||||
|
||||
.SUFFIXES: .spec
|
||||
|
||||
|
@ -42,16 +43,16 @@ SFILES = $(DLLS16:.spec=.S)
|
|||
|
||||
all: checkbuild $(MODULE).o
|
||||
|
||||
$(SFILES): $(TOPSRC)/tools/build
|
||||
$(SPEC16_FILES) $(SPEC32_FILES): $(TOPSRC)/tools/build
|
||||
|
||||
checkbuild:
|
||||
cd $(TOPSRC)/tools; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)' build
|
||||
|
||||
call16.S: $(TOPSRC)/include/callback.h
|
||||
$(TOPSRC)/tools/build -call16 `cat $(TOPSRC)/include/callback.h | grep "extern.*CallTo16_" | sed 's/.*CallTo16_\(.*\)(.*/\1/' | sort | uniq` > call16.S
|
||||
call16.S: $(TOPSRC)/include/callback.h $(BUILD)
|
||||
$(BUILD) -call16 `cat $(TOPSRC)/include/callback.h | grep "extern.*CallTo16_" | sed 's/.*CallTo16_\(.*\)(.*/\1/' | sort | uniq` > call16.S
|
||||
|
||||
call32.S: $(SFILES)
|
||||
$(BUILD) -call32 `cat $(SFILES) | grep CallTo32_ | sed 's/.*CallTo32_\(.*\)/\1/' | sort | uniq` > call32.S
|
||||
call32.S: $(SPEC16_FILES)
|
||||
$(BUILD) -call32 `cat $(SPEC16_FILES) | grep CallTo32_ | sed 's/.*CallTo32_\(.*\)/\1/' | sort | uniq` > call32.S
|
||||
|
||||
$(MODULE).o: $(OBJS)
|
||||
$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
|
||||
|
@ -62,7 +63,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
rm -f $(DLLS16:.spec=.S) $(DLLS32:.spec=.c) call32.S call16.S
|
||||
|
||||
distclean: clean
|
||||
|
|
|
@ -245,7 +245,7 @@ id 3
|
|||
380 stub ENDPAGE
|
||||
381 stub SETABORTPROC
|
||||
382 stub ABORTDOC
|
||||
400 stub FASTWINDOWFRAME
|
||||
400 pascal16 FastWindowFrame(word long word word long) FastWindowFrame
|
||||
401 stub GDIMOVEBITMAP
|
||||
403 stub GDIINIT2
|
||||
405 stub FINALGDIINIT
|
||||
|
|
|
@ -232,7 +232,7 @@ id 1
|
|||
#351 BUNNY_351
|
||||
353 pascal lstrcpyn(segptr segptr word) lstrcpyn
|
||||
354 stub GetAppCompatFlags
|
||||
355 stub GetWinDebugInfo
|
||||
356 stub SetWinDebugInfo
|
||||
355 pascal16 GetWinDebugInfo(ptr word) GetWinDebugInfo
|
||||
356 pascal16 SetWinDebugInfo(ptr) SetWinDebugInfo
|
||||
403 pascal16 FarSetOwner(word word) FarSetOwner
|
||||
404 pascal16 FarGetOwner(word) FarGetOwner
|
||||
|
|
18
if1632/pop.h
18
if1632/pop.h
|
@ -1,18 +0,0 @@
|
|||
add $8,%esp
|
||||
popw %es
|
||||
add $2,%esp
|
||||
popw %ds
|
||||
add $2,%esp
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebp
|
||||
add $4,%esp
|
||||
popl %ebx
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popl %eax
|
||||
add $16,%esp
|
||||
popl %gs:return_value
|
||||
add $20,%esp
|
||||
pushl %gs:return_value
|
||||
popfl
|
|
@ -25,10 +25,4 @@ typedef struct
|
|||
HANDLE entries[1];
|
||||
} ATOMTABLE;
|
||||
|
||||
|
||||
ATOM LocalAddAtom( SEGPTR str );
|
||||
ATOM LocalDeleteAtom( ATOM atom );
|
||||
ATOM LocalFindAtom( SEGPTR str );
|
||||
WORD LocalGetAtomName( ATOM atom, LPSTR buffer, short count );
|
||||
|
||||
#endif /* ATOM_H */
|
||||
|
|
23
include/bitmaps/obm_close_95
Normal file
23
include/bitmaps/obm_close_95
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* XPM */
|
||||
static char * obm_close_95[] = {
|
||||
"16 14 6 1",
|
||||
" s button_highlight c white",
|
||||
"+ s button_edge c grey85",
|
||||
"X s button_face c grey75",
|
||||
"o s button_shadow c grey50",
|
||||
". s button_text c black",
|
||||
"O s window_frame c black",
|
||||
" O",
|
||||
" +++++++++++++oO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XX..XXXX..XXoO",
|
||||
" +XXX..XX..XXXoO",
|
||||
" +XXXX....XXXXoO",
|
||||
" +XXXXX..XXXXXoO",
|
||||
" +XXXX....XXXXoO",
|
||||
" +XXX..XX..XXXoO",
|
||||
" +XX..XXXX..XXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" ooooooooooooooO",
|
||||
"OOOOOOOOOOOOOOOO"};
|
23
include/bitmaps/obm_closed_95
Normal file
23
include/bitmaps/obm_closed_95
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* XPM */
|
||||
static char * obm_closed_95[] = {
|
||||
"16 14 6 1",
|
||||
" s button_highlight c white",
|
||||
"+ s button_edge c grey85",
|
||||
"X s button_face c grey75",
|
||||
"o s button_shadow c grey50",
|
||||
". s button_text c black",
|
||||
"O s window_frame c black",
|
||||
"OOOOOOOOOOOOOOO ",
|
||||
"Oooooooooooooo+ ",
|
||||
"OoXXXXXXXXXXXX+ ",
|
||||
"OoXXXXXXXXXXXX+ ",
|
||||
"OoXXX..XXXX..X+ ",
|
||||
"OoXXXX..XX..XX+ ",
|
||||
"OoXXXXX....XXX+ ",
|
||||
"OoXXXXXX..XXXX+ ",
|
||||
"OoXXXXX....XXX+ ",
|
||||
"OoXXXX..XX..XX+ ",
|
||||
"OoXXX..XXXX..X+ ",
|
||||
"OoXXXXXXXXXXXX+ ",
|
||||
"O++++++++++++++ ",
|
||||
" "};
|
23
include/bitmaps/obm_reduce_95
Normal file
23
include/bitmaps/obm_reduce_95
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* XPM */
|
||||
static char * obm_reduce_95[] = {
|
||||
"16 14 6 1",
|
||||
" s button_highlight c white",
|
||||
"+ s button_edge c grey85",
|
||||
"X s button_face c grey75",
|
||||
"o s button_shadow c grey50",
|
||||
". s button_text c black",
|
||||
"O s window_frame c black",
|
||||
" O",
|
||||
" +++++++++++++oO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XX......XXXXoO",
|
||||
" +XX......XXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" ooooooooooooooO",
|
||||
"OOOOOOOOOOOOOOOO"};
|
23
include/bitmaps/obm_reduced_95
Normal file
23
include/bitmaps/obm_reduced_95
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* XPM */
|
||||
static char * obm_reduced_95[] = {
|
||||
"16 14 6 1",
|
||||
"O s button_highlight c white",
|
||||
"o s button_edge c grey85",
|
||||
"X s button_face c grey75",
|
||||
"+ s button_shadow c grey50",
|
||||
". s button_text c black",
|
||||
" s window_frame c black",
|
||||
" ",
|
||||
" +++++++++++++oO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XXX......XXXoO",
|
||||
" +XXX......XXXoO",
|
||||
" ooooooooooooooO",
|
||||
"OOOOOOOOOOOOOOOO"};
|
23
include/bitmaps/obm_zoom_95
Normal file
23
include/bitmaps/obm_zoom_95
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* XPM */
|
||||
static char * obm_zoom_95[] = {
|
||||
"16 14 6 1",
|
||||
" s button_highlight c white",
|
||||
"+ s button_edge c grey85",
|
||||
"X s button_face c grey75",
|
||||
"o s button_shadow c grey50",
|
||||
". s button_text c black",
|
||||
"O s window_frame c black",
|
||||
" O",
|
||||
" +++++++++++++oO",
|
||||
" +X.........XXoO",
|
||||
" +X.........XXoO",
|
||||
" +X.XXXXXXX.XXoO",
|
||||
" +X.XXXXXXX.XXoO",
|
||||
" +X.XXXXXXX.XXoO",
|
||||
" +X.XXXXXXX.XXoO",
|
||||
" +X.XXXXXXX.XXoO",
|
||||
" +X.XXXXXXX.XXoO",
|
||||
" +X.........XXoO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" ooooooooooooooO",
|
||||
"OOOOOOOOOOOOOOOO"};
|
23
include/bitmaps/obm_zoomd_95
Normal file
23
include/bitmaps/obm_zoomd_95
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* XPM */
|
||||
static char * obm_zoomd_95[] = {
|
||||
"16 14 6 1",
|
||||
"O s button_highlight c white",
|
||||
"o s button_edge c grey85",
|
||||
"X s button_face c grey75",
|
||||
"+ s button_shadow c grey50",
|
||||
". s button_text c black",
|
||||
" s window_frame c black",
|
||||
" ",
|
||||
" +++++++++++++oO",
|
||||
" +XXXXXXXXXXXXoO",
|
||||
" +XX.........XoO",
|
||||
" +XX.........XoO",
|
||||
" +XX.XXXXXXX.XoO",
|
||||
" +XX.XXXXXXX.XoO",
|
||||
" +XX.XXXXXXX.XoO",
|
||||
" +XX.XXXXXXX.XoO",
|
||||
" +XX.XXXXXXX.XoO",
|
||||
" +XX.XXXXXXX.XoO",
|
||||
" +XX.........XoO",
|
||||
" ooooooooooooooO",
|
||||
"OOOOOOOOOOOOOOOO"};
|
|
@ -9,15 +9,20 @@
|
|||
*/
|
||||
#ifndef __WINE_DDE_ATOM_H
|
||||
#define __WINE_DDE_ATOM_H
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
#define DDE_ATOMS 157 /* a prime number for hashing */
|
||||
|
||||
void ATOM_GlobalInit(void);
|
||||
/*
|
||||
ATOM GlobalAddAtom( LPCSTR str );
|
||||
ATOM GlobalDeleteAtom( ATOM atom );
|
||||
ATOM GlobalFindAtom( LPCSTR str );
|
||||
WORD GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
|
||||
*/
|
||||
|
||||
ATOM DDE_GlobalAddAtom( SEGPTR str );
|
||||
ATOM DDE_GlobalDeleteAtom( ATOM atom );
|
||||
ATOM DDE_GlobalFindAtom( SEGPTR str );
|
||||
WORD DDE_GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
#endif __WINE_DDE_ATOM_H
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
*/
|
||||
#ifndef __WINE_DDE_MEM_H
|
||||
#define __WINE_DDE_MEM_H
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#include "wintypes.h"
|
||||
#include "global.h"
|
||||
#include "shm_block.h"
|
||||
|
@ -31,4 +34,6 @@ HANDLE DDE_GlobalSize(WORD);
|
|||
HANDLE DDE_GlobalHandle(WORD);
|
||||
HANDLE DDE_GlobalFlags(WORD);
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
#endif /* __WINE_DDE_MEM_H */
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
*/
|
||||
#ifndef __WINE_DDE_PROC_H
|
||||
#define __WINE_DDE_PROC_H
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#include <setjmp.h>
|
||||
#include "wintypes.h"
|
||||
#include "windows.h"
|
||||
|
@ -54,4 +57,7 @@ BOOL DDE_SendMessage( MSG *msg);
|
|||
int DDE_GetRemoteMessage();
|
||||
void DDE_DestroyWindow(HWND hwnd); /* delete DDE info regarding hwnd */
|
||||
void DDE_TestDDE(HWND hwnd); /* do we have dde handling in the window ?*/
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
#endif /* __WINE_DDE_PROC_H */
|
||||
|
|
|
@ -1,20 +1,39 @@
|
|||
/*
|
||||
* Misc. emulation definitions
|
||||
*
|
||||
* Copyright 1995 Alexandre Julliard
|
||||
*/
|
||||
|
||||
#ifndef __WINE_MISCEMU_H
|
||||
#define __WINE_MISCEMU_H
|
||||
|
||||
#include "wintypes.h"
|
||||
#include "registers.h"
|
||||
|
||||
|
||||
/* miscemu/dosmem.c */
|
||||
extern BOOL DOSMEM_Init(void);
|
||||
extern void DOSMEM_FillBiosSegment(void);
|
||||
extern HANDLE DOSMEM_BiosSeg;
|
||||
|
||||
/* miscemu/instr.c */
|
||||
extern BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context );
|
||||
|
||||
extern DWORD inport( int port, int count );
|
||||
extern void outport( int port, int count, DWORD value );
|
||||
|
||||
/* miscemu/interrupts.c */
|
||||
extern BOOL INT_Init(void);
|
||||
extern SEGPTR INT_GetHandler( BYTE intnum );
|
||||
extern void INT_SetHandler( BYTE intnum, SEGPTR handler );
|
||||
|
||||
/* miscemu/int1a.c */
|
||||
extern DWORD INT1A_GetTicksSinceMidnight(void);
|
||||
|
||||
/* miscemu/int21.c */
|
||||
extern void INT21_Init(void);
|
||||
|
||||
/* miscemu/ioports.c */
|
||||
extern DWORD inport( int port, int count );
|
||||
extern void outport( int port, int count, DWORD value );
|
||||
|
||||
|
||||
#define INT_BARF(context,num) \
|
||||
fprintf( stderr, "int%x: unknown/not implemented parameters:\n" \
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
*/
|
||||
#ifndef __WINE_SHM_BLOCK_H
|
||||
#define __WINE_SHM_BLOCK_H
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#include <sys/shm.h>
|
||||
#include "wintypes.h"
|
||||
#define SEGSIZE 0x10000 /* 64 */
|
||||
|
@ -83,4 +86,5 @@ struct shm_block *shm_attach_block(int shm_id, int proc_idx,
|
|||
/* delete chain of shm blocks (pointing to each other */
|
||||
void shm_delete_chain(int *shmid);
|
||||
|
||||
#endif /* __WINE_SHM_BLOCK_H */
|
||||
#endif /* CONFIG_IPC */
|
||||
#endif /* __WINE_SHM_BLOCK_H */
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#ifndef __WINE_SHM_FRAGMENT_H
|
||||
#define __WINE_SHM_FRAGMENT_H
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#include "shm_block.h"
|
||||
|
||||
#define NIL ((int) 0)
|
||||
|
@ -44,4 +46,6 @@ void shm_FragPtrFree(struct shm_block *block, void *ptr);
|
|||
/* This is used for debugging only */
|
||||
void shm_print_free_list(struct shm_block *block);
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
#endif /* __WINE_SHM_FRAGMENT_H */
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
*/
|
||||
#ifndef __WINE_SHM_MAIN_BLK_H
|
||||
#define __WINE_SHM_MAIN_BLK_H
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#include <sys/shm.h>
|
||||
#include "shm_block.h"
|
||||
#include "shm_semaph.h"
|
||||
|
@ -52,4 +55,6 @@ void DDE_mem_init();
|
|||
int DDE_no_of_attached();
|
||||
#define DDE_IPC_init() ( (main_block==NULL) ? (DDE_mem_init()) : 0 )
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
#endif /* __WINE_SHM_MAIN_BLK_H */
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#define __WINE_SHM_SEMAPH_H
|
||||
/* IMPORTANT: If possible, restrict usage of these functions. */
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
typedef int shm_sem;
|
||||
|
||||
void shm_read_wait(shm_sem semid);
|
||||
|
@ -21,4 +23,6 @@ void shm_read_signal(shm_sem semid);
|
|||
void shm_sem_init(shm_sem *semptr);
|
||||
void shm_sem_done(shm_sem *semptr);
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
#endif /* __WINE_SHM_SEMAPH_H */
|
||||
|
|
|
@ -11,30 +11,56 @@
|
|||
|
||||
|
||||
/* Constant system metrics */
|
||||
#ifdef WIN_95_LOOK
|
||||
#define SYSMETRICS_CXVSCROLL 14
|
||||
#define SYSMETRICS_CYHSCROLL 14
|
||||
#else
|
||||
#define SYSMETRICS_CXVSCROLL 16
|
||||
#define SYSMETRICS_CYHSCROLL 16
|
||||
#endif
|
||||
#define SYSMETRICS_CYCAPTION 20
|
||||
#define SYSMETRICS_CXBORDER 1
|
||||
#define SYSMETRICS_CYBORDER 1
|
||||
#ifdef WIN_95_LOOK
|
||||
#define SYSMETRICS_CXDLGFRAME 2
|
||||
#define SYSMETRICS_CYDLGFRAME 2
|
||||
#define SYSMETRICS_CYVTHUMB 13
|
||||
#define SYSMETRICS_CXHTHUMB 13
|
||||
#else
|
||||
#define SYSMETRICS_CXDLGFRAME 4
|
||||
#define SYSMETRICS_CYDLGFRAME 4
|
||||
#define SYSMETRICS_CYVTHUMB 16
|
||||
#define SYSMETRICS_CXHTHUMB 16
|
||||
#endif
|
||||
#define SYSMETRICS_CXICON 32
|
||||
#define SYSMETRICS_CYICON 32
|
||||
#define SYSMETRICS_CXCURSOR 32
|
||||
#define SYSMETRICS_CYCURSOR 32
|
||||
#define SYSMETRICS_CYMENU 18
|
||||
#ifdef WIN_95_LOOK
|
||||
#define SYSMETRICS_CYVSCROLL 14
|
||||
#define SYSMETRICS_CXHSCROLL 14
|
||||
#define SYSMETRICS_CXMIN 112
|
||||
#define SYSMETRICS_CYMIN 27
|
||||
#else
|
||||
#define SYSMETRICS_CYVSCROLL 16
|
||||
#define SYSMETRICS_CXHSCROLL 16
|
||||
#define SYSMETRICS_CXMIN 100
|
||||
#define SYSMETRICS_CYMIN 28
|
||||
#endif
|
||||
#define SYSMETRICS_CXSIZE 18
|
||||
#define SYSMETRICS_CYSIZE 18
|
||||
#ifdef WIN_95_LOOK
|
||||
#define SYSMETRICS_CXMINTRACK 112
|
||||
#define SYSMETRICS_CYMINTRACK 27
|
||||
#define SYSMETRICS_CXICONSPACING 75
|
||||
#define SYSMETRICS_CYICONSPACING 75
|
||||
#else
|
||||
#define SYSMETRICS_CXMINTRACK 100
|
||||
#define SYSMETRICS_CYMINTRACK 28
|
||||
#define SYSMETRICS_CXICONSPACING 20
|
||||
#define SYSMETRICS_CYICONSPACING 20
|
||||
#endif
|
||||
|
||||
/* Some non-constant system metrics */
|
||||
#define SYSMETRICS_CXSCREEN sysMetrics[SM_CXSCREEN]
|
||||
|
|
|
@ -2318,6 +2318,56 @@ typedef METAFILEPICT *LPMETAFILEPICT;
|
|||
#define META_CREATEBITMAP 0x06FE
|
||||
#define META_CREATEREGION 0x06FF
|
||||
|
||||
/* Debugging support (DEBUG SYSTEM ONLY) */
|
||||
typedef struct tagWINDEBUGINFO
|
||||
{
|
||||
UINT flags;
|
||||
DWORD dwOptions;
|
||||
DWORD dwFilter;
|
||||
char achAllocModule[8];
|
||||
DWORD dwAllocBreak;
|
||||
DWORD dwAllocCount;
|
||||
} WINDEBUGINFO;
|
||||
typedef WINDEBUGINFO FAR* LPWINDEBUGINFO;
|
||||
|
||||
/* WINDEBUGINFO flags values */
|
||||
#define WDI_OPTIONS 0x0001
|
||||
#define WDI_FILTER 0x0002
|
||||
#define WDI_ALLOCBREAK 0x0004
|
||||
|
||||
/* dwOptions values */
|
||||
#define DBO_CHECKHEAP 0x0001
|
||||
#define DBO_BUFFERFILL 0x0004
|
||||
#define DBO_DISABLEGPTRAPPING 0x0010
|
||||
#define DBO_CHECKFREE 0x0020
|
||||
|
||||
#define DBO_SILENT 0x8000
|
||||
|
||||
#define DBO_TRACEBREAK 0x2000
|
||||
#define DBO_WARNINGBREAK 0x1000
|
||||
#define DBO_NOERRORBREAK 0x0800
|
||||
#define DBO_NOFATALBREAK 0x0400
|
||||
#define DBO_INT3BREAK 0x0100
|
||||
|
||||
/* DebugOutput flags values */
|
||||
#define DBF_TRACE 0x0000
|
||||
#define DBF_WARNING 0x4000
|
||||
#define DBF_ERROR 0x8000
|
||||
#define DBF_FATAL 0xc000
|
||||
|
||||
/* dwFilter values */
|
||||
#define DBF_KERNEL 0x1000
|
||||
#define DBF_KRN_MEMMAN 0x0001
|
||||
#define DBF_KRN_LOADMODULE 0x0002
|
||||
#define DBF_KRN_SEGMENTLOAD 0x0004
|
||||
#define DBF_USER 0x0800
|
||||
#define DBF_GDI 0x0400
|
||||
#define DBF_MMSYSTEM 0x0040
|
||||
#define DBF_PENWIN 0x0020
|
||||
#define DBF_APPLICATION 0x0008
|
||||
#define DBF_DRIVER 0x0010
|
||||
|
||||
|
||||
#ifndef WINELIB
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
|
@ -2439,6 +2489,7 @@ Fa(BOOL,RemoveFontResource,LPSTR,a)
|
|||
Fa(BOOL,SetDeskWallPaper,LPSTR,a)
|
||||
Fa(BOOL,SetErrorMode,WORD,a)
|
||||
Fa(BOOL,SetMessageQueue,int,a)
|
||||
Fa(BOOL,SetWinDebugInfo,LPWINDEBUGINFO,a)
|
||||
Fa(BOOL,SwapMouseButton,BOOL,a)
|
||||
Fa(BOOL,TranslateMessage,LPMSG,a)
|
||||
Fa(BOOL,UnhookWindowsHookEx,HHOOK,a)
|
||||
|
@ -2623,6 +2674,7 @@ Fb(BOOL,GetCurrentPositionEx,HDC,a,LPPOINT,b)
|
|||
Fb(BOOL,GetTextMetrics,HDC,a,LPTEXTMETRIC,b)
|
||||
Fb(BOOL,GetViewportExtEx,HDC,a,LPPOINT,b)
|
||||
Fb(BOOL,GetViewportOrgEx,HDC,a,LPPOINT,b)
|
||||
Fb(BOOL,GetWinDebugInfo,LPWINDEBUGINFO,a,UINT,b)
|
||||
Fb(BOOL,GetWindowExtEx,HDC,a,LPPOINT,b)
|
||||
Fb(BOOL,GetWindowOrgEx,HDC,a,LPPOINT,b)
|
||||
Fb(BOOL,GetWindowPlacement,HWND,a,LPWINDOWPLACEMENT,b)
|
||||
|
|
|
@ -174,7 +174,7 @@ struct sockproto {
|
|||
* compatibility purposes.
|
||||
*/
|
||||
|
||||
#define h_errno WSAGetLastError()
|
||||
/* #define h_errno WSAGetLastError() */
|
||||
|
||||
/* Authoritative Answer: Host not found */
|
||||
#define WSAHOST_NOT_FOUND (WSABASEERR+1001)
|
||||
|
|
|
@ -2,32 +2,36 @@
|
|||
|
||||
MODULE = ipc
|
||||
|
||||
TEST_SRCS = \
|
||||
shm_fragment_test.c \
|
||||
bit_array_test.c\
|
||||
dde_proc_test.c \
|
||||
dde_atom_test.c \
|
||||
shm_semaph_test.c \
|
||||
wine_test_stub.c \
|
||||
hash_test.c \
|
||||
dde_mem_test.c
|
||||
|
||||
SRCS = bit_array.c \
|
||||
dde_atom.c \
|
||||
dde_mem.c \
|
||||
dde_proc.c \
|
||||
generic_hash.c \
|
||||
shm_block.c \
|
||||
shm_fragment.c \
|
||||
shm_main_blk.c \
|
||||
shm_semaph.c
|
||||
dde_atom.c \
|
||||
shm_semaph.c \
|
||||
dde_mem.c \
|
||||
shm_block.c \
|
||||
shm_fragment.c
|
||||
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
TEST_OBJS = $(TEST_SRCS:.c=.o)
|
||||
|
||||
SHM_OBJ=shm_block.o shm_semaph.o shm_main_blk.o dde_proc.o \
|
||||
dde_mem.o bit_array.o shm_fragment.o wine_test_stub.o
|
||||
|
||||
|
||||
WineRelocatableTarget($(MODULE),,$(OBJS))
|
||||
|
||||
DependTarget()
|
||||
|
||||
tests:: dde_mem_test dde_proc_test dde_atom_test shm_fragment_test \
|
||||
shm_semaph_test
|
||||
|
||||
NormalProgramTarget(bit_array_test, bit_array.o bit_array_test.o,,,)
|
||||
NormalProgramTarget(shm_semaph_test, shm_semaph_test.o shm_semaph.o,,,)
|
||||
NormalProgramTarget(shm_fragment_test, shm_fragment_test.o shm_fragment.o,,,)
|
||||
NormalProgramTarget(dde_atom_test, dde_atom_test.o dde_atom.o $(SHM_OBJ),,,)
|
||||
NormalProgramTarget(dde_mem_test, dde_mem_test.o $(SHM_OBJ),,,)
|
||||
NormalProgramTarget(dde_proc_test, dde_proc_test.o $(SHM_OBJ) ,,,)
|
||||
|
||||
|
||||
includes::
|
||||
|
||||
install::
|
||||
|
|
|
@ -35,7 +35,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
|
38
ipc/README
38
ipc/README
|
@ -1,8 +1,34 @@
|
|||
This is a pre-alpha code, it does not work for 100%,
|
||||
but it does not break anything (I hope).
|
||||
Proper documentation (LaTeX) will be ready for the next release.
|
||||
Technion- Israel Institute of Technology
|
||||
Electrical Engineering software lab.
|
||||
|
||||
You can use "ipcl" perl script to remove junk IPC stuff.
|
||||
You can use "ipcs" system program to find junk IPC stuff.
|
||||
|
||||
Michael
|
||||
|
||||
Author : Michael Veksler 11678223
|
||||
|
||||
Tutor: Avner Lottem
|
||||
|
||||
|
||||
DDE support for Wine
|
||||
====================
|
||||
|
||||
Wine emulator is able to run MS-Windows 3.1 applications under Linux
|
||||
(Linux is a UNIX clone) . Wine is also a toolkit allowing MS-Windows
|
||||
applications to compile under Linux. Wine is a world-wide Internet
|
||||
project with more than 20 developers. Wine is still under development
|
||||
so many vital MS-Windows features are still missing.
|
||||
|
||||
DDE is Dynamic Data Exchange used for communication between MS-Windows
|
||||
applications. This project adds DDE capabilities into Wine. The new
|
||||
improved Wine will be able to send messages and share memory between
|
||||
two different Wine processes.
|
||||
|
||||
This project uses System-V IPC mechanisms to implement DDE.
|
||||
|
||||
Besides sharing memory handles and sending DDE messages, Wine processes
|
||||
are synchronize to emulates MS-Windows non-preemptive task switching.
|
||||
(MS-Windows switches tasks only on given instructions). This is done
|
||||
without hurting the performance or stability of a single Wine process.
|
||||
|
||||
The project adds DDE to Wine emulator and to the toolkit. This allows
|
||||
old MS-Windows applications to be compiled for UNIX, and have DDE
|
||||
working among them.
|
||||
|
|
|
@ -14,13 +14,15 @@
|
|||
***************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
/*
|
||||
** uncoment the following line to disable assertions,
|
||||
** this may boost performance by up to 50%
|
||||
*/
|
||||
/* #define NDEBUG */
|
||||
|
||||
#ifndef NO_ASM
|
||||
#if defined(linux) && !defined(NO_ASM)
|
||||
#define HAS_BITOPS
|
||||
#endif
|
||||
|
||||
|
@ -275,3 +277,5 @@ int AllocateBit(bit_array *bits)
|
|||
|
||||
return bit_nr;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
|
962
ipc/dde.tex
Normal file
962
ipc/dde.tex
Normal file
|
@ -0,0 +1,962 @@
|
|||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%
|
||||
%% Written by Michael Veksler.
|
||||
%% May be freely redistributed as long as this header is unchanged.
|
||||
%% The file be modified as long as there will be appropriate comment
|
||||
%% containing the Author and a description.
|
||||
%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\documentstyle{article}
|
||||
\renewcommand{\thepage}{}
|
||||
\newcommand{\Wine}{Wine}
|
||||
\newcommand{\WINE}{{\em WINdows Emulator}}
|
||||
\newcommand{\DDE}{{\em Dynamic Data Exchange}}
|
||||
\newcommand{\windoz}{MS-Win\-dows}
|
||||
\newcommand{\fname}[1]{{\tt #1}}
|
||||
\newcommand{\libwine}{\fname{libwine.a}}
|
||||
\title{DDE\footnote{DDE is \DDE\ mechanism provided by \windoz.
|
||||
(Appendix~\protect\ref{sec:DDE}).
|
||||
}
|
||||
\ capability for \Wine\footnote{\Wine\ (\WINE) Runs \windoz\
|
||||
programs under UNIX\@. (Appendix~\protect\ref{sec:Wine}).
|
||||
}
|
||||
}
|
||||
\author{Michael Veksler 11678223}
|
||||
%%\date{Aug 6, 1995}
|
||||
\begin{document}
|
||||
\maketitle
|
||||
\vfill
|
||||
\abstract{\Wine{} provides an environment for running or compiling
|
||||
\windoz{} applications for UNIX clones (such as Linux).
|
||||
\Wine{} is not yet finished and lacks many basic important features.
|
||||
One of the missing features is DDE\@. DDE implementation
|
||||
(especially for \libwine) requires
|
||||
UNIX IPC\footnote{IPC - Inter-Process Communication}. This Project
|
||||
introduces the IPC mechanism into \Wine{}, thus allowing DDE to work
|
||||
between different \Wine{} processes.}
|
||||
|
||||
|
||||
\vfill
|
||||
{\LARGE
|
||||
\begin{itemize}
|
||||
\item[Instructor:] Avner Lottem
|
||||
\item[Done for:] Technion- Israel Institute of Technology,\\
|
||||
Electrical Engineering software lab$^{\mbox{\small\copyright}}$.
|
||||
\end{itemize}
|
||||
}
|
||||
\vfill
|
||||
|
||||
\newpage
|
||||
\renewcommand{\thepage}{\roman{page}}
|
||||
\setcounter{page}{1}
|
||||
\begin{center}
|
||||
{\LARGE Table Of Contents}
|
||||
\end{center}
|
||||
\tableofcontents
|
||||
|
||||
\newpage
|
||||
\renewcommand{\thepage}{\arabic{page}}
|
||||
\setcounter{page}{1}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%
|
||||
%% end of title
|
||||
%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Introduction}
|
||||
|
||||
\subsection{The project}
|
||||
The purpose of the project is to add DDE capabilities into \Wine.
|
||||
The project enables \Wine{} DDE client-server applications communication.
|
||||
This involved messing around with:
|
||||
\begin{itemize}
|
||||
\item \windoz\ message mechanism.
|
||||
\item \windoz\ memory management.
|
||||
\item \windoz\ task management.
|
||||
\item UNIX messages among \Wine\ processes.
|
||||
\item Exchanging (sharing) UNIX memory.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Problem description}
|
||||
DDE is essentially a communication protocol between \windoz\
|
||||
tasks. Implementing this protocol requires communication among
|
||||
\Wine{} processes and among tasks in one process (each \Wine{} process
|
||||
can contain several tasks). Since \Wine\ already provides
|
||||
communication among internal tasks, this project provides communication
|
||||
between \Wine\ processes.
|
||||
|
||||
Different \Wine\ processes should be able to send \windoz\ messages
|
||||
and to pass \windoz\ memory handles. There also has to be a
|
||||
synchronization mechanism between the processes (\windoz\ applications
|
||||
make assumptions about task switching - and don't use semaphores, or
|
||||
any \windoz\ equivalent).
|
||||
|
||||
Passing messages is a bit tricky. \windoz\ gives a feedback about the
|
||||
success of a message (fails if the window does not exist).
|
||||
In case of SendMessage (see Appendix~\ref{sec:WindozMsg}), the process
|
||||
will have to halt until the message has been processed.
|
||||
In case of PostMessage, things are simpler - only the existence of the
|
||||
recipient has to be checked.
|
||||
|
||||
\windoz\ switches tasks only when certain system calls are used (such
|
||||
as delivering or polling messages). \windoz\ applications rely on this
|
||||
behavior. The problem arises when two applications run on different
|
||||
\Wine\ processes. Since UNIX preempts processes there is no guaranty
|
||||
that the UNIX task will occur at the correct place (in respect of the
|
||||
application).
|
||||
One one hand is the need for compatibility (no UNIX ``current''
|
||||
execution), and on the other hand is performance and stability.
|
||||
|
||||
Another problem is passing handles between \Wine\ processes. \windoz\
|
||||
applications pass atoms\footnote{See appendix~\ref{sec:WhatAreAtoms}},
|
||||
memory handles and window handles. These handles have to be allocated
|
||||
globally (in shared memory) or translated on the fly.
|
||||
|
||||
|
||||
If a process dies from ``unnatural causes'' (e.g.\ kill $-9$). It will
|
||||
leave garbage in memory and other IPC handles will start floating
|
||||
around. There should be some way to collect this garbage.
|
||||
|
||||
\subsection{Solutions}
|
||||
\label{sec:ProjSolutions}
|
||||
\Wine\ uses Sys-V IPC mechanism (See
|
||||
Appendix~\ref{sec:SysV-IPC}). This allows sharing data and passing
|
||||
data between processes (The alternatives are not that good in that
|
||||
respect - see Appendix~\ref{DDE-Alternatives}).
|
||||
The shared data contains only essential information (performance or
|
||||
compatibility). The minimum is kept on shared memory in order to get
|
||||
maximum stability (\windoz\ is known as an unstable system, \Wine\
|
||||
should not imitate \windoz\ in this respect).
|
||||
|
||||
Communications are done by Sys-V messages and UNIX signals (a signal
|
||||
wakes \Wine\ up and the message passes the data). Sys-V messages are
|
||||
used for carrying \windoz\ messages, as well as synchronization
|
||||
information. There are 3 types of messages: sent, posted and ack.
|
||||
Ack message is used for synchronization as well as for returning error
|
||||
codes (In case sending/posting messages fail). When a message is sent,
|
||||
the sending process will block until \Wine's {\em ack}{} message is
|
||||
received.
|
||||
|
||||
Synchronization between \Wine\ processes is divided into 2 categories,
|
||||
in both cases the sender of a message waits for an ack message:
|
||||
\begin{enumerate}
|
||||
\item Sent messages - Wait until the recipient delivers ack message.
|
||||
(When the recipient finished message processing)
|
||||
\item Posted message - The recipient will send ack only during
|
||||
task switching instructions (like PostMessage, GetMessage, Yield,
|
||||
etc.). This way nothing will be done after PostMessage until it is
|
||||
safe.
|
||||
\end{enumerate}
|
||||
|
||||
There is no real \Wine\ server. Every \Wine\ process has to handle
|
||||
it's end. This approach somehow resembles a distributed OS\@. This
|
||||
introduces some problems (Resources might not be freed in case of a
|
||||
crash). On the other hand this ``distributed OS'' approach simplifies
|
||||
installation and use, and improves performance.
|
||||
|
||||
Atoms are stored on shared memory, so every two \Wine\ processes will
|
||||
be in sync in this respect (atom 5 will mean the same on both
|
||||
processes). Shared memory handles are stored on shared memory as
|
||||
well. Shared memory handles are not from the same range as local
|
||||
memory handles (\windoz\ requires an plication to declare about it's
|
||||
shared memory). Since local memory handles have different range they
|
||||
can be allocated locally (without any sync requirements - handle x may
|
||||
appear on 10 different \Wine\ processes and address different data).
|
||||
|
||||
Window handles are allocated locally. This approach gives stability,
|
||||
but window handles are no longer unique (same handle may appear
|
||||
on different processes). This requires on the fly window handle
|
||||
translation. When an \windoz\ message is transfered, \Wine\ will
|
||||
translate any contained window handle. The sender translates the
|
||||
handle to a global (unique) handle, the receiver translates the global
|
||||
handle to the local window handle.
|
||||
|
||||
Collecting the garbage of dead processes is done in two cases:
|
||||
\begin{enumerate}
|
||||
\item When setting up a new \Wine\ process: If no \Wine\ process is
|
||||
running and shared memory is floating around all the IPC stuff is
|
||||
deleted.
|
||||
\item When sending a message: If the recipient is dead it's IPC
|
||||
handles are deleted.
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
|
||||
\section{The software}
|
||||
|
||||
\subsection{DDE project structure}
|
||||
Old \Wine\ functions call the new DDE functions whenever needed.
|
||||
(e.g.\ when sending a DDE message, the original SendMessage function calls
|
||||
DDE\_SendMessage). This approach minimizes changes to original \Wine{}
|
||||
code. The new code was written in C. The new capabilities where written
|
||||
as much as possible in OOP\footnote{OOP stands for Object Oriented
|
||||
Programming}{} style.
|
||||
|
||||
Currently DDE uses Sys-V IPC mechanism, for it's operation.
|
||||
|
||||
|
||||
\paragraph{Major OOP objects and files:}
|
||||
|
||||
\begin{table}[h]
|
||||
\begin{center}
|
||||
\leavevmode
|
||||
\begin{tabular}{|l|p{20em}|} \hline
|
||||
Object & Description \\ \hline
|
||||
shm\_block & shared memory block operations. \\
|
||||
shm\_main\_block & (derived from shm\_block.) Things all
|
||||
DDE applications need access to. \\
|
||||
shm\_fragment & Allocation of in-block fragments. \\
|
||||
shm\_semaph & Semaphore operations. \\
|
||||
dde\_proc & Process and DDE message handling. \\
|
||||
dde\_mem & Front end of DDE memory handling
|
||||
(Interface of DDE to outer world). \\
|
||||
dde\_atom & Handling global atoms. \\
|
||||
bit\_array & Array of bits. It has atomic
|
||||
operations, so bits can be used instead
|
||||
of semaphores. \\ \hline
|
||||
\end{tabular}
|
||||
\caption{Objects constructing the DDE extension.}
|
||||
\label{tab:ObjList}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
Table~\ref{tab:ObjList}{} lists the objects used in the DDE code.
|
||||
The following rules apply to objects:
|
||||
|
||||
\begin{itemize}
|
||||
\item Object names that begin with {\em dde\_$\cdots$}{} are the front
|
||||
end. These objects are working directly with the rest of
|
||||
\Wine. Objects that start with {\em shm\_$\cdots$}{} are the back
|
||||
end. These objects provide services for the rest of the
|
||||
implementation.
|
||||
\item The objects are stored in file with the same name as the object.
|
||||
(e.g.\ dde\_mem is stored in dde\_mem.c and dde\_mem.h).
|
||||
\item For each object there is a test file (that partially tests it).
|
||||
The name of this file is object's name with the word ``test''
|
||||
(e.g.\ dde\_mem object has dde\_mem\_test.c).
|
||||
\item dde.h file has declarations used by dde\_proc and external DDE
|
||||
users.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
\subsection{Major algorithms}
|
||||
|
||||
\paragraph{Delivering messages:}
|
||||
\label{sec:DeliveringMessages}
|
||||
\windoz\ messages are passed using Sys-V IPC messages. Processing
|
||||
starts with SendMessage() or PostMessage() \windoz\ system
|
||||
functions:
|
||||
\begin{enumerate}
|
||||
\item SendMessage and PostMessage call the DDE functions (same names
|
||||
prefixed with DDE\_). If the DDE functions pass, don't go any
|
||||
further. If it fails try to process the message in the
|
||||
conventional way.
|
||||
\item The DDE message functions call DDE\_DoMessage, which is
|
||||
the main DDE message processing function. From now on there is no
|
||||
difference between sending and posting messages (from initiator's
|
||||
point of view).
|
||||
\item If the message is not a DDE message or the recipient is not
|
||||
remote, fail and return to original message functions.
|
||||
\item Bring the message to a format suitable for IPC delivery. The
|
||||
format includes:
|
||||
\begin{itemize}
|
||||
\item message type (sent or posted).
|
||||
\item Sender window handle (translated to global window id.)
|
||||
\item Other message ingredients (msg, lParam).
|
||||
\end{itemize}
|
||||
\item Deliver the message to every recipients using
|
||||
DDE\_DoOneMessage. There might be many recipients in case of a
|
||||
broadcast (when the ``recipient'' window is -1).
|
||||
\item DDE\_DoOneMessage delivers the message and waits for response.
|
||||
Fail if timeout is reached.
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
\paragraph{Receiving messages:}
|
||||
Messages from other \Wine\ processes are received. Processing start
|
||||
from DDE\_GetRemoteMessage():
|
||||
\begin{enumerate}
|
||||
\item DDE\_GetRemoteMessage is called whenever wine is going to wait
|
||||
or receive X-windows message. If wine is sleeping (waiting for X),
|
||||
it will waken by a SIGUSR2 signal. In this case the handler will
|
||||
siglongjmp() out of the select() function.
|
||||
\item If no remote message is pending in the message queue - exit.
|
||||
(Sys-V message queue holds the remote messages until they are
|
||||
read).
|
||||
\item If the message is broadcasted, goto stage~\ref{BroadcastAlgo}.
|
||||
\item Translate the global window handle of the recipient to local
|
||||
handle.
|
||||
\item Do this if the message was sent. Send the message to the
|
||||
recipient window. Reply with ack to the sender. (Reply with the
|
||||
return code of the SendMessage function). {\em \bf Return}\ with
|
||||
positive return value.
|
||||
\item Post the message.
|
||||
\item If PostMessage fails - send failing ack message.
|
||||
\item If PostMessage passes, add the message data into a FIFO\@. This
|
||||
FIFO contains all messages that have to be acknowledged (who's
|
||||
sender is waiting for ack). Whenever internal task switch occurs,
|
||||
a item from this FIFO is popped out and an ack message is sent.
|
||||
\item \label{BroadcastAlgo} Iterate through the local windows and
|
||||
deliver the message to every one of them.
|
||||
\item Send a positive ack message.
|
||||
\end{enumerate}
|
||||
|
||||
\paragraph{Allocating memory:}
|
||||
Shared memory allocation is divided into two categories: internal wine
|
||||
and \windoz\ application. The memory used by \windoz\ applications is
|
||||
allocated in two phases - allocate internal wine, and then prepare all
|
||||
the stuff needed by \windoz.
|
||||
|
||||
The internal allocation (DDE\_malloc):
|
||||
\begin{enumerate}
|
||||
\item Try to allocate big enough memory fragment in allocated shared
|
||||
memory.
|
||||
\item If fragment could not be allocated, allocate a new shared
|
||||
memory block. Allocate the memory fragment.
|
||||
\item Allocate a shared memory handle (call the dde\_alloc\_handle()
|
||||
function). The allocated handle is from a range used only by
|
||||
shared memory handles. This allocation function is used only for
|
||||
shared DDE memory.
|
||||
\item Write the handle in the data structure. Also write the
|
||||
relative location of this handle (Pointer location is useless since
|
||||
it differs from one \Wine\ process to another).
|
||||
This information is written in the main shared memory block.
|
||||
\end{enumerate}
|
||||
When a fragment is allocated, it is removed from the list of free
|
||||
memory.
|
||||
|
||||
Allocation for \windoz\ applications (this is done in GlobalAlloc):
|
||||
\begin{enumerate}
|
||||
\item Do the internal allocation (instead of malloc in the local
|
||||
allocation).
|
||||
\item Everything else is the same as with local memory. A segment is
|
||||
allocated for the new memory, and it's data is kept in the data
|
||||
structure.
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
\paragraph{Atoms:}
|
||||
Atoms have pretty simple algorithms operating on them. Since atoms are
|
||||
supposed to give a unique number for each string - atoms are
|
||||
implemented as hash tables. The id of the atom is the entry in the
|
||||
hash table. The disadvantage of this approach is that there is a limit
|
||||
on the number of atoms, the big advantages are simplicity and
|
||||
speed.
|
||||
|
||||
Since implementing a hash tables is strait forward, I will not
|
||||
discuss it in depth. This hash table has two hash functions - primary
|
||||
and secondary. When searching for an item (for deletion, addition, or
|
||||
a seek) the following steps are taken:
|
||||
\begin{enumerate}
|
||||
\item The primary hash function returns the first entry.
|
||||
\item \label{AtomHashLoop}
|
||||
If the entry is empty or no unchecked entries {\bf \em fail}.
|
||||
\item If the entry is correct, {\bf \em success!!!}.
|
||||
\item Add the result of secondary hash function to the item index.
|
||||
\item Goto step~\ref{AtomHashLoop}.
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
\subsection{Major data structures}
|
||||
There are two kinds of data structure, local and shared. The local
|
||||
data structures are strait forward and will not be discussed in
|
||||
detail.
|
||||
|
||||
The shared data structures have four level hierarchy. Each level
|
||||
depend on the other and can not exist without it. Most structures have
|
||||
much less than four levels.
|
||||
|
||||
\paragraph{Level one data structure - the main block:}
|
||||
This data structure is part of the shm\_main\_block object. It
|
||||
contains essential information needed by all \Wine\ processes. :
|
||||
\begin{enumerate}
|
||||
\item Semaphore identifier used for locking the data structure.
|
||||
\item A table containing information about \Wine\ processes.
|
||||
\item Relative pointers to atoms.
|
||||
\item A table containing window information.
|
||||
\item Tables with global memory handles.
|
||||
\end{enumerate}
|
||||
|
||||
The first level is allocated and initialized when \Wine\ calls a DDE
|
||||
function the first time. DDE functions are: global memory allocation,
|
||||
global atoms or DDE messages.
|
||||
|
||||
The first level data structure contains the second level data
|
||||
structure.
|
||||
|
||||
|
||||
\paragraph{Atom element (level two):}
|
||||
Each element is allocated dynamically (the size of the string is
|
||||
unknown). The allocation is gained from the shm\_fragment object (each
|
||||
atom is an instance of that object). Each atom contains:
|
||||
\begin{enumerate}
|
||||
\item Count of links. Each allocation of the atom establishes a new
|
||||
link and each deallocation deletes one link (until all links are
|
||||
removed).
|
||||
\item The string of the atom. The string ends with a null character.
|
||||
\end{enumerate}
|
||||
|
||||
\paragraph{Wine processes data (level two):}
|
||||
(part of the dde\_proc object) :
|
||||
\begin{enumerate}
|
||||
\item pid (\Wine\ process id).
|
||||
\item Message queue id.
|
||||
\item Semaphore used for locking process's data structure.
|
||||
\item Sys-V shared memory id of the first block in the chain of
|
||||
process's blocks.
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
\paragraph{Window information (level two):}
|
||||
This is part of the dde\_proc object. The index of array entry
|
||||
specifies the window handle. Each entry contains:
|
||||
\begin{enumerate}
|
||||
\item The process index of the \Wine\ process running this window.
|
||||
\item The local window handle of this window (remember that each DDE
|
||||
window has different global and local handles).
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
\paragraph{Global memory handles (Level two):}
|
||||
(part of bit\_array and dde\_mem objects):
|
||||
\begin{enumerate}
|
||||
\item A bit array contains '1' in every entry that refers to
|
||||
used global memory handle.
|
||||
\item Array of handles contains handle data. Each entry refers
|
||||
to a global memory handle (The index is a function of the
|
||||
handle). The data includes: 1) Sys-V shared memory handles 2)
|
||||
offset into the memory block.
|
||||
\end{enumerate}
|
||||
|
||||
\paragraph{Block allocation data structure (Level three):}
|
||||
This data structure a part of the shm\_block object. It is local to
|
||||
each shared memory block, so every memory block has it's own data
|
||||
structure. The shared memory blocks are organized in chains grouped by
|
||||
processes (each DDE process has one and only one chain):
|
||||
\begin{enumerate}
|
||||
\item The id of the next shared memory block in the chain.
|
||||
\item The size of the block.
|
||||
\item Number of free bytes in the block.
|
||||
\item The index of the owner process.
|
||||
\item The first item in the free list (a linked list of free items).
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
\paragraph{Fragment allocation (Level four):}
|
||||
This data is a part of the shm\_fragment object. It is a part of the shared
|
||||
memory allocation mechanism. Every fragment is a part of shared memory
|
||||
block. Each fragments contain:
|
||||
\begin{enumerate}
|
||||
\item The size of the fragment (for allocating and freeing this
|
||||
fragment).
|
||||
\item A union that contains one of:
|
||||
\begin{itemize}
|
||||
\item data - if it is allocated.
|
||||
\item offset of the next free fragment (if it is a member of the
|
||||
free list).
|
||||
\end{itemize}
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
\paragraph{Local reference to global memory:}
|
||||
Global memory blocks are referenced from local memory. This is used
|
||||
for storing pointers that refer to the memory block. It contains:
|
||||
\begin{enumerate}
|
||||
\item next item in the list.
|
||||
\item shared memory block id.
|
||||
\item Owner process.
|
||||
\item Pointer to the data.
|
||||
\end{enumerate}
|
||||
|
||||
\paragraph{Local mirroring of global handles:}
|
||||
Global handles require local segments handles (when they are locked).
|
||||
These segments have to be deleted when the handle is freed.
|
||||
There is a minimal mirroring of handles in the original tables of
|
||||
wine, this information is stored the way local handles have always
|
||||
been stored.
|
||||
|
||||
\subsection{Interface and IO}
|
||||
The DDE section of wine has several interfaces to different entities:
|
||||
\begin{enumerate}
|
||||
\item User debug information.
|
||||
\item Interface between several \Wine\ processes.
|
||||
\item Interface to the `old' code of \Wine.
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
\paragraph{User debug information:}
|
||||
The debug information is written according to \Wine's
|
||||
conventions. This means that dprintf\_$\cdots$ macros are used to
|
||||
print the debug information. (These macros allow runtime or compile time
|
||||
disabling of a any sort of debug information).
|
||||
|
||||
In some cases the dprintf\_$\cdots$ macros are not powerful enough. In
|
||||
those cases the following construct is used instead:
|
||||
\begin{verbatim}
|
||||
if (debugging_dde) {
|
||||
/* print whatever is needed for dde debugging */
|
||||
}
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
\paragraph{Interface between \Wine\ processes:}
|
||||
The interface between processes includes:
|
||||
\begin{itemize}
|
||||
\item Message delivery (see Section~\ref{sec:DeliveringMessages}).
|
||||
\item Sharing \windoz\ constructs (atoms, memory, window
|
||||
handles).
|
||||
\item Synchronization among different \Wine\ processes so it will
|
||||
appear to a \windoz\ as if there is only one process.
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{Interface to the rest of \Wine:}
|
||||
Most of the interface has been minimized to an additional few lines in
|
||||
the original functions. The hook for DDE are in the following
|
||||
locations:
|
||||
\begin{itemize}
|
||||
\item Global atoms functions - these are called directly from
|
||||
\windoz\ applications.
|
||||
\item Message delivery - a hook calls the DDE functions from the
|
||||
original message delivery functions.
|
||||
\item Initialization - Every PeekMessage() call a DDE function to
|
||||
check if the current window has DDE management (by sending
|
||||
a dummy WM\_DDE\_INITIATE message).
|
||||
\item Waiting on messages - The original code for waiting on X
|
||||
messages was enhanced to wait on DDE messages as well. This
|
||||
includes aborting sleeps when SIGUSR2 signal is sent. The actual
|
||||
test for DDE messages is done in the DDE code.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Major functions and their role}
|
||||
\paragraph{Message delivery functions:}
|
||||
\begin{itemize}
|
||||
\item DDE\_SendMessage and DDE\_PostMessage - hooks used by original
|
||||
\Wine's SendMessage and PostMessage. They return true if the
|
||||
message could be successfully sent to a remote \Wine\ process.
|
||||
Only in this case SendMessage and PostMessage stop further
|
||||
processing.
|
||||
\item DDE\_DoMessage - Try to post or send a message to another
|
||||
\Wine\ process. This function can do broadcasting as well as
|
||||
sending. (A message is `broadcasted' if it is delivered to every
|
||||
window on the system).
|
||||
\item DDE\_DoOneMessage - Deliver a message to a given wine
|
||||
{\bf process}.
|
||||
\item dde\_proc\_send\_ack - Send ack message to \Wine\
|
||||
process. The input window handle is used for detecting the
|
||||
process.
|
||||
\item get\_ack - wait for ack or timeout.
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{Memory allocation functions:}
|
||||
\begin{itemize}
|
||||
\item DDE\_malloc - Allocate a shared memory fragment. This function
|
||||
also allocates global memory handle.
|
||||
\item DDE\_GlobalFree - Free a shared memory fragment according to
|
||||
it's handle. And free the handle.
|
||||
\item DDE\_SyncHandle - synchronize the global handles mirrored
|
||||
locally. Delete any outdated handles, or remap reallocated
|
||||
handles.
|
||||
\item DDE\_mem\_init - initialize or attach the main shared memory
|
||||
block, and relevant local data structures.
|
||||
\item shm\_delete\_all - delete all IPC stuff related to this
|
||||
process. Kill the main memory block if appropriate.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
\section{Software testing}
|
||||
The testing of this module was a substantial part of the
|
||||
development. Testing revealed bugs just as they where created.
|
||||
|
||||
\subsection{Testing methods utilized}
|
||||
\label{sec:TestMethod}
|
||||
Two major testing methods where used:
|
||||
\begin{enumerate}
|
||||
\item Running DDE \windoz\ applications. The applications used are
|
||||
DDE demonstration applications. This applications seem to show
|
||||
precisely what DDE is all about. The applications used where:
|
||||
ddepop1.exe (server), showpop1.exe (client). These
|
||||
applications come with \windoz\ programming manual by Charles
|
||||
Petzold \cite{bib:WinManual}.
|
||||
\item Running standalone DDE objects linked with a test
|
||||
object. Every object was tested this way. Some objects had to be
|
||||
linked with a stub that emulated \Wine's functions. The stub is
|
||||
pretty poor with dde\_mem object since this object requires hard
|
||||
to emulate functionalities (things like allocating a segment).
|
||||
|
||||
For some objects the coverage seems to be perfect (100\%). For
|
||||
some object the coverage is poor. The objects with massive stub
|
||||
usage suffer from this (especially dde\_mem).
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{input for testing}
|
||||
Most of the testing described in section~\ref{sec:TestMethod} has no
|
||||
input. Most of the testing knowledge is in the test objects
|
||||
themselves. There are two exceptions to this rule:
|
||||
\begin{enumerate}
|
||||
\item The \windoz\ applications described in
|
||||
section~\ref{sec:TestMethod} - which are essentially an input to
|
||||
the software. These applications can't be distributed since it
|
||||
will be a \copyright{} violation.
|
||||
\item A trace file which is used for comparing test's output with
|
||||
the expected trace result. This trace file is used for
|
||||
shm\_fragment validation. This file is implementation Dependants
|
||||
and should be updated whenever the object is rewritten. When
|
||||
updating the trace, it should be inspected manually before it is
|
||||
released.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{usage instructions}
|
||||
|
||||
\paragraph{Running the DDE applications:}
|
||||
To test the DDE applications one must run:
|
||||
\begin{verbatim}
|
||||
prompt> wine /full-path/ddepop1.exe > /dev/null &
|
||||
\end{verbatim}
|
||||
Wait for the server window to pop up (A tiny window should appear at
|
||||
the lower left corner of your screen). Then activate the client by
|
||||
typing:
|
||||
\begin{verbatim}
|
||||
prompt> wine /full-path/showpop1.exe > /dev/null
|
||||
\end{verbatim}
|
||||
The server updates ``USA population'' data every 5 seconds. The client
|
||||
asks for a hot link (i.e.\ it sends a WM\_DDE\_ADVISE on every
|
||||
item). From that point on the server updates the client of any
|
||||
population change.
|
||||
|
||||
|
||||
\paragraph{Running the object tests:}
|
||||
The {\em run\_tests}{} script is provided to automate the object
|
||||
tests. Every object test is run and the script checks for results. At
|
||||
the end the script prints a nice summary table.
|
||||
|
||||
Invoking tests outside the {\em run\_tests}{} script is not as simple
|
||||
as it may look. Every test has differently looking output.
|
||||
\begin{itemize}
|
||||
\item dde\_atom\_test - The executable is run. It passes if no
|
||||
errors are printed at the bottom.
|
||||
\item dde\_mem\_test - The same as for dde\_atom\_test.
|
||||
\item shm\_semaph\_test - The same as for dde\_atom\_test.
|
||||
\item bit\_array\_test - The same as for dde\_atom\_test.
|
||||
\item shm\_fragment\_test - After the executable is run, the output
|
||||
has to be compared with TEST\_FRAGMENT.std
|
||||
\item dde\_proc\_test - This actually runs as a client and as a
|
||||
server. To activate the server one should write:
|
||||
\begin{verbatim}
|
||||
prompt> dde_proc_test 1 > server.log
|
||||
\end{verbatim}
|
||||
Then the client has to be activated within five seconds by
|
||||
writing:
|
||||
\begin{verbatim}
|
||||
prompt> dde_proc_test > client.log
|
||||
\end{verbatim}
|
||||
The log files should contain:
|
||||
\begin{description}
|
||||
\item[server.log:] Should contain traces of received
|
||||
WM\_DDE\_INITIATE message, and ack sent for it. (Pretty much
|
||||
the same what {\em run\_tests}{} does).
|
||||
\item[client.log:] Should contain traces of sending
|
||||
WM\_DDE\_INITIATE and then receiving an ack message.
|
||||
\end{description}
|
||||
No `timeout' traces should be present in the log files.
|
||||
|
||||
\end{itemize}
|
||||
|
||||
|
||||
\section{Summary}
|
||||
\subsection{Software limitations}
|
||||
\begin{itemize}
|
||||
\item Only most fundamental memory management functions where
|
||||
written. This means that the following functions will not work:
|
||||
\begin{itemize}
|
||||
\item GlobalReAlloc
|
||||
\item GlobalSize - two line fix.
|
||||
\item GlobalFlags - two line fix.
|
||||
\item LockSegment - two line fix.
|
||||
\item UnlockSegment - two line fix.
|
||||
\item GlobalFreeAll - will not free DDE memory.
|
||||
\item GlobalPageLock - two line fix.
|
||||
\item GlobalPageUnlock - two line fix.
|
||||
\item GlobalFix - two line fix.
|
||||
\item GlobalUnfix - two line fix.
|
||||
\end{itemize}
|
||||
\item Non DDE messages to remote windows will not work. This is
|
||||
currently only a sanity check, it may be removed in the future.
|
||||
\item Message sending has a timeout limit. This is incompatible with
|
||||
\windoz. This limit increases stability of a singe \Wine\ process.
|
||||
\item Synchronization mechanism between wine processes is not
|
||||
perfect. It was not proved theoretically. I never saw it fail.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Concluding Remarks}
|
||||
This extension to \Wine{} enables further development of \windoz\ IPC
|
||||
support. Things like OLE can be extended using these features -
|
||||
although some modifications might be inevitable.
|
||||
|
||||
The most important contribution of this project is the support for
|
||||
\libwine{}. Any \windoz\ application compiled under UNIX and linked to
|
||||
\libwine{} will need the IPC mechanism provided by this project.
|
||||
|
||||
During the progress of the project it got a bit outdated. During that
|
||||
time \Wine{} started to handle tasks internally, so the external IPC
|
||||
was no longer needed for the emulator configuration of
|
||||
wine. Nevertheless the support of IPC for \libwine will never
|
||||
be obsolete.
|
||||
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%
|
||||
%% Appendixes
|
||||
%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\clearpage
|
||||
\appendix
|
||||
|
||||
\section{\Wine}
|
||||
\label{sec:Wine}
|
||||
\Wine\ stand for {\em WINdows Emulator}. It is an X-windows - UNIX
|
||||
application (Linux and FreeBSD). \Wine\ emulates \windoz\ environment
|
||||
for the \windoz\ applications. It has two uses:
|
||||
\begin{enumerate}
|
||||
\item Run \windoz\ binary code (compiled under \windoz).
|
||||
\item To be used as a toolkit for compiling \windoz\ applications
|
||||
under UNIX. (The \libwine\ library is provided)
|
||||
\end{enumerate}
|
||||
For emulation, only Intel-Architecture CPU (386, 486, Pentium) are
|
||||
supported. \libwine\ Toolkit should run on any platforms, but it was not
|
||||
tested. \Wine\ is still in alpha state, and does not support all \windoz\
|
||||
capabilities yet.
|
||||
|
||||
|
||||
\section{Messages under \windoz}
|
||||
\label{sec:WindozMsg}
|
||||
Messages are the means of communication to a user window (from another
|
||||
window or from \windoz\ itself).
|
||||
Messages can be delivered in two ways:
|
||||
\begin{itemize}
|
||||
\item Messages can be sent. The sent message enters the window handler
|
||||
asynchronously (The handler may be reentered many times).
|
||||
A window sending the message waits for the recipient to process
|
||||
the message and return an exit code.
|
||||
\item Messages can be posted. The posted message enters a queue, and
|
||||
it's up to the recipient to process it. If the recipient ignores
|
||||
it, the message might be eventually sent to the recipient from
|
||||
WinMain handler.
|
||||
\end{itemize}
|
||||
|
||||
\section{DDE}
|
||||
\label{sec:DDE}
|
||||
DDE stands for \DDE\@. DDE is an \windoz\
|
||||
protocol used for data exchange between applications.
|
||||
It has synchronous and asynchronous operation modes.
|
||||
DDE mechanism is based on messages, atoms
|
||||
(Section~\ref{sec:WhatAreAtoms}) and shared memory.
|
||||
|
||||
DDE applications are divided roughly into two classes: servers AND
|
||||
clients. Clients have the initiative, they try to connect to the
|
||||
server. Servers only maintain an existing DDE link.
|
||||
|
||||
|
||||
\subsection{DDE Messages}
|
||||
\paragraph{DDE message format}:
|
||||
|
||||
\label{sec:DDEMessageFormat}
|
||||
|
||||
DDE messages contain the following fields.
|
||||
\begin{description}
|
||||
\item[wnd] The recipient of this message ($-1$ if every window
|
||||
should receive).
|
||||
\item[msg] The ID of the message.
|
||||
\item[wParam] Who sent this message.
|
||||
\item[lParam] 32 bit parameter, divided into two 16 bit words.
|
||||
Usually, the lower 16 bits contain a memory handle. The handle
|
||||
points to some extra DATA about this message.
|
||||
|
||||
\end{description}
|
||||
|
||||
\paragraph{Available messages:}
|
||||
\begin{description}
|
||||
\item[WM\_DDE\_INITIATE]
|
||||
This message is sent by the client to the whole ``world''.
|
||||
{\em lParam}{} contains the two atoms used for passing the topic and
|
||||
application information.
|
||||
|
||||
Every server application checks if this message refers to it
|
||||
(According to the Application and the Topic atoms).
|
||||
|
||||
|
||||
\item[WM\_DDE\_ACK]
|
||||
This is a generic response to various events
|
||||
(one of them is WM\_DDE\_INITIATE).
|
||||
The low part of {\em lParam}{} passes extra information, such as
|
||||
success/failure.
|
||||
|
||||
\item[WM\_DDE\_TERMINATE]
|
||||
Kill the DDE link.
|
||||
|
||||
|
||||
\item[WM\_DDE\_ADVISE]
|
||||
Tell the server to inform the client of any updates.
|
||||
|
||||
|
||||
\item[WM\_DDE\_UNADVISE]
|
||||
Stop the WM\_DDE\_UNADVISE mode.
|
||||
|
||||
|
||||
\item[WM\_DDE\_DATA]
|
||||
Transfer data handle (note that the data handle must be globally allocated
|
||||
with the GMEM\_DDESHARE flag).
|
||||
|
||||
\item[WM\_DDE\_REQUEST]
|
||||
Request a data item from the server. This message is used in a
|
||||
cold link. {\em lParam}{} contains an atom describing the desired
|
||||
item, and a WORD describing the wanted data format.
|
||||
\item[WM\_DDE\_POKE]
|
||||
The client gives the server new data.
|
||||
\item[WM\_DDE\_EXECUTE]
|
||||
The client asks the server to execute a procedure (according to a
|
||||
command string).
|
||||
|
||||
\end{description}
|
||||
|
||||
\subsection{Atoms}
|
||||
\label{sec:WhatAreAtoms}
|
||||
Atoms are represented by numbers. Every atom maps uniquely to a string
|
||||
(i.e.\ two atoms can't map to the same string).
|
||||
There are two types of atoms - local and global. The local are visible
|
||||
only to the application that created them. Global atoms are seen by all
|
||||
\windoz\ applications.
|
||||
|
||||
Functions:
|
||||
\begin{description}
|
||||
\item[AddAtom(str)] create a local atom that maps to ``str''.
|
||||
If it exists, increment the allocation-counter,
|
||||
and return the atom.
|
||||
\item[DeleteAtom(atom)] decrement the allocation-counter. When it
|
||||
reaches zero the atom, will be deleted.
|
||||
\item[FindAtom(str)] Find the atom that maps to this string (if exist).
|
||||
|
||||
\item[GetAtomName(\ldots)] Find the string that this atom points to.
|
||||
\end{description}
|
||||
|
||||
NOTE:
|
||||
\begin{description}
|
||||
\item[Global atoms] Add ``Global'' before the listed names to get Global
|
||||
atom functions.
|
||||
\item[Case sensitivity] All atom operations ignore case.
|
||||
\end{description}
|
||||
|
||||
|
||||
\section{DDE under \Wine\ - Alternatives}
|
||||
\label{DDE-Alternatives}
|
||||
There where three possible approaches for this project. I have chosen
|
||||
System-V IPC, but it can be easily changed.
|
||||
|
||||
\subsection{IPC - Inter-Process Communication}
|
||||
\label{sec:SysV-IPC}
|
||||
|
||||
The IPC mechanism was originated from System-V UNIX\@. This mechanism
|
||||
allows complicate communication between two process (on the same machine).
|
||||
IPC includes the following capabilities:
|
||||
\begin{enumerate}
|
||||
\item Shared Memory (shm) - can be shared among few processes and users.
|
||||
\item Semaphores (These semaphores allow grouped operations - i.e.\
|
||||
operations gathered as an atomic operation).
|
||||
\item Message Queues (allow few messages at a time).
|
||||
\end{enumerate}
|
||||
|
||||
The advantages of IPC over the other variants are:
|
||||
\begin{itemize}
|
||||
\item Memory access speed is good. (after the memory was attached).
|
||||
\item Easy to block critical code (don't enter critical code from two
|
||||
processes at the same time)
|
||||
\end{itemize}
|
||||
Disadvantages of IPC:
|
||||
\begin{itemize}
|
||||
\item Impossible to communicate to other machine.
|
||||
\item Requires complex mechanism to wait both for X and IPC messages.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{X-Windows Communication mechanisms}
|
||||
The advantages of X-Windows Communication over the other variants are:
|
||||
\begin{itemize}
|
||||
\item Possible to communicate to other machines.
|
||||
\item No need for additional mechanism that will wait both for X and DDE\@.
|
||||
\item Many of the required capabilities are already there.
|
||||
\end{itemize}
|
||||
Disadvantages of X-windows communication:
|
||||
\begin{itemize}
|
||||
\item {\em Slow}\ and complex memory access.
|
||||
\item May be hard to avoid two applications from entering critical
|
||||
code at the same time.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{BSD Sockets}
|
||||
The advantages of Sockets are:
|
||||
\begin{itemize}
|
||||
\item Possible to communicate to other machines.
|
||||
\item No need for complex mechanism that will wait both for X and
|
||||
DDE\@. (can use one ``select'' on X-windows socket in concert with
|
||||
the DDE socket).
|
||||
\end{itemize}
|
||||
Disadvantages of socket are:
|
||||
\begin{itemize}
|
||||
\item {\em Slow}{} and complex memory access. (note that mmap on a
|
||||
descriptor does not work for Linux 0.99).
|
||||
\item May be hard to avoid two applications from entering critical
|
||||
code at the same time.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Why was it written in C? Pros and cons.}
|
||||
Advantages of C:
|
||||
|
||||
\begin{itemize}
|
||||
\item History- \Wine{} is already written in C.
|
||||
\item Portability- not all systems have C++.
|
||||
\item Speed- C++ sometimes makes it very difficult to write fast code.
|
||||
\item Maintenance- More programmers know C than C++.
|
||||
\end{itemize}
|
||||
|
||||
Advantages of C++:
|
||||
|
||||
\begin{itemize}
|
||||
\item smaller code - Templates allow Smaller and more readable code.
|
||||
\item Maintenance - It is easier to add and modify code in C++ (than in C).
|
||||
\item Verification - Functionality can be verified and debugged for
|
||||
individual objects.
|
||||
\end{itemize}
|
||||
|
||||
I have decided to use C. Most of C++ advantages can be acquired
|
||||
by using OOP methodologies. OOP methods that require inline functions
|
||||
can't be used (without performance impact). GCC supports inline functions,
|
||||
but this solution is not compatible.
|
||||
|
||||
|
||||
|
||||
\section{\Wine\ basics}
|
||||
\subsection{How it runs}
|
||||
\Wine\ works in the following order:
|
||||
\begin{enumerate}
|
||||
\item \Wine\ loads the \windoz\ application into it's memory.
|
||||
(in the process it, links
|
||||
DLL's\footnote{DLL (Dynamically Linked Library) is linked on load-time.}
|
||||
creates 16-bit segments).
|
||||
\item \windoz\ code is executed.
|
||||
\end{enumerate}
|
||||
|
||||
\section{bibliography}
|
||||
\begin{thebibliography}{99}
|
||||
\bibitem{bib:WinManual} Charles Petzold {\em Programming
|
||||
Windows~3.1}{} - 1992. \\
|
||||
On cover: {\em the Microsoft guide to writing applications for
|
||||
windows~3.1}. \\
|
||||
Published by {\em Microsoft press}.
|
||||
\end{thebibliography}
|
||||
|
||||
|
||||
\newpage
|
||||
|
||||
|
||||
\end{document}
|
|
@ -6,6 +6,7 @@
|
|||
* File: dde_atom.c
|
||||
* Purpose : atom functionality for DDE
|
||||
*/
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
@ -106,11 +107,11 @@ void ATOM_GlobalInit(void)
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GlobalAddAtom (USER.268)
|
||||
* DDE_GlobalAddAtom
|
||||
*/
|
||||
|
||||
/* important! don't forget to unlock semaphores before return */
|
||||
ATOM GlobalAddAtom( SEGPTR name )
|
||||
ATOM DDE_GlobalAddAtom( SEGPTR name )
|
||||
{
|
||||
int atom_idx;
|
||||
int atom_ofs;
|
||||
|
@ -164,10 +165,10 @@ ATOM GlobalAddAtom( SEGPTR name )
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GlobalDeleteAtom (USER.269)
|
||||
* DDE_GlobalDeleteAtom
|
||||
*/
|
||||
|
||||
ATOM GlobalDeleteAtom( ATOM atom )
|
||||
ATOM DDE_GlobalDeleteAtom( ATOM atom )
|
||||
{
|
||||
int atom_idx;
|
||||
int atom_ofs;
|
||||
|
@ -203,9 +204,9 @@ ATOM GlobalDeleteAtom( ATOM atom )
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GlobalFindAtom (USER.270)
|
||||
* DDE_GlobalFindAtom
|
||||
*/
|
||||
ATOM GlobalFindAtom( SEGPTR name )
|
||||
ATOM DDE_GlobalFindAtom( SEGPTR name )
|
||||
{
|
||||
int atom_idx;
|
||||
int atom_ofs;
|
||||
|
@ -242,9 +243,9 @@ ATOM GlobalFindAtom( SEGPTR name )
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GlobalGetAtomName (USER.271)
|
||||
* DDE_GlobalGetAtomName
|
||||
*/
|
||||
WORD GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
|
||||
WORD DDE_GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
|
||||
{
|
||||
int atom_idx, atom_ofs;
|
||||
int size;
|
||||
|
@ -283,3 +284,4 @@ WORD GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
|
|||
return size;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* Purpose : shared DDE memory functionality for DDE
|
||||
***************************************************************************
|
||||
*/
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddebug.h>
|
||||
#include <debug.h>
|
||||
|
@ -280,3 +282,5 @@ void DDE_mem_init()
|
|||
nr_of_bits= BITS_PER_BYTE * sizeof(main_block->free_handles);
|
||||
AssembleArray( &free_handles, main_block->free_handles, nr_of_bits);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
|
|
@ -7,6 +7,12 @@
|
|||
* Purpose : DDE signals and processes functionality for DDE
|
||||
***************************************************************************
|
||||
*/
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
#define msgbuf mymsg
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -716,3 +722,4 @@ void DDE_DestroyWindow(HWND hwnd)
|
|||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* Purpose : dynamically growing hash, may use shared or local memory.
|
||||
***************************************************************************
|
||||
*/
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
@ -677,3 +679,5 @@ HASH_ITEM *access_local_hash(HASH_PTR ptr)
|
|||
{
|
||||
return ptr.ptr;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* Purpose: Treat a shared memory block.
|
||||
***************************************************************************
|
||||
*/
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#define inline __inline__
|
||||
#include <sys/types.h>
|
||||
|
@ -76,7 +77,7 @@ struct shm_block *shm_attach_block(int shm_id, int proc_idx,
|
|||
shmctl(shm_id, IPC_STAT, &ds );
|
||||
|
||||
block=(struct shm_block*)shmat(shm_id, NULL, 0);
|
||||
if (block==NULL) return NULL;
|
||||
if (block==NULL || block == (struct shm_block*) -1) return NULL;
|
||||
|
||||
this=(struct local_shm_map *)malloc(sizeof(*this));
|
||||
this->next= shm_map;
|
||||
|
@ -190,3 +191,5 @@ void shm_delete_chain(int *shmid)
|
|||
*shmid=-1;
|
||||
shmdt((char *)block);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* Purpose: Data fragments and free list items. Allocate and free blocks.
|
||||
***************************************************************************
|
||||
*/
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#include <stdio.h> /* for debugging only */
|
||||
#include <stddebug.h>
|
||||
#include <debug.h> /* for "stddeb" */
|
||||
|
@ -176,3 +178,5 @@ void shm_print_free_list(struct shm_block *block)
|
|||
fprintf(stddeb," [total free=%04x]\n",block->free);
|
||||
fflush(stddeb);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* Purpose: Main Wine's shared memory block
|
||||
***************************************************************************
|
||||
*/
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#define inline __inline__
|
||||
#include <sys/types.h>
|
||||
#include <sys/sem.h>
|
||||
|
@ -265,3 +267,5 @@ static void shm_main_refresh()
|
|||
for (proc_idx= 0 ; proc_idx < DDE_PROCS ; proc_idx++)
|
||||
dde_proc_refresh( &main_block->proc[proc_idx] );
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* Purpose: Handle semaphores for shared memory operations.
|
||||
***************************************************************************
|
||||
*/
|
||||
#ifdef CONFIG_IPC
|
||||
|
||||
#define inline __inline__
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
@ -134,3 +136,5 @@ void shm_sem_done(shm_sem *semptr)
|
|||
|
||||
*semptr= -1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IPC */
|
||||
|
|
|
@ -23,7 +23,7 @@ int LDT_GetEntry( int entry, ldt_entry *content )
|
|||
return 0;
|
||||
}
|
||||
|
||||
int LDT_SetEntry( int entry, ldt_entry *content )
|
||||
int LDT_SetEntry( int entry, ldt_entry const *content )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
|
|
@ -66,6 +66,9 @@ int MAIN_Init(void)
|
|||
/* Initialize interrupt vectors */
|
||||
if (!INT_Init()) return 0;
|
||||
|
||||
/* Initialize DOS memory */
|
||||
if (!DOSMEM_Init()) return 0;
|
||||
|
||||
/* Initialize signal handling */
|
||||
init_wine_signals();
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ BOOL MODULE_Init(void)
|
|||
NE_MODULE *pModule;
|
||||
SEGTABLEENTRY *pSegTable;
|
||||
struct dll_table_s *table;
|
||||
char *dosmem;
|
||||
int i;
|
||||
|
||||
/* Create the built-in modules */
|
||||
|
@ -82,47 +81,10 @@ BOOL MODULE_Init(void)
|
|||
hFirstModule = hModule;
|
||||
}
|
||||
|
||||
/* Initialize some KERNEL exported values */
|
||||
/* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
|
||||
|
||||
if (!(hModule = GetModuleHandle( "KERNEL" ))) return TRUE;
|
||||
MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
|
||||
|
||||
/* KERNEL.178: __WINFLAGS */
|
||||
MODULE_SetEntryPoint( hModule, 178, GetWinFlags() );
|
||||
|
||||
/* Allocate 7 64k segments for 0000, A000, B000, C000, D000, E000, F000. */
|
||||
|
||||
dosmem = malloc( 0x70000 );
|
||||
|
||||
MODULE_SetEntryPoint( hModule, 183, /* KERNEL.183: __0000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 193, /* KERNEL.193: __0040H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x400,
|
||||
0x100, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 174, /* KERNEL.174: __A000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x10000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 181, /* KERNEL.181: __B000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x20000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 182, /* KERNEL.182: __B800H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x28000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 195, /* KERNEL.195: __C000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x30000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 179, /* KERNEL.179: __D000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x40000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 190, /* KERNEL.190: __E000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x50000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 173, /* KERNEL.173: __ROMBIOS */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x60000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 194, /* KERNEL.194: __F000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x60000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ BOOL NE_LoadSegment( HMODULE hModule, WORD segnum )
|
|||
int fd;
|
||||
struct relocation_entry_s *rep, *reloc_entries;
|
||||
BYTE *func_name;
|
||||
int size;
|
||||
char* mem;
|
||||
|
||||
char buffer[100];
|
||||
int ordinal, additive;
|
||||
|
@ -51,23 +53,37 @@ BOOL NE_LoadSegment( HMODULE hModule, WORD segnum )
|
|||
|
||||
if (!pSeg->filepos) return TRUE; /* No file image, just return */
|
||||
|
||||
if (pSeg->flags & NE_SEGFLAGS_ITERATED)
|
||||
{
|
||||
fprintf(stderr, "Sorry, iterated segments are not supported\n"
|
||||
"Please report that %*.*s, segment %d is such a segment\n",
|
||||
*((BYTE*)pModule + pModule->name_table),
|
||||
*((BYTE*)pModule + pModule->name_table),
|
||||
(char *)pModule + pModule->name_table + 1,
|
||||
segnum
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd = MODULE_OpenFile( hModule );
|
||||
dprintf_module( stddeb, "Loading segment %d, selector=%04x\n",
|
||||
segnum, pSeg->selector );
|
||||
lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
|
||||
read( fd, GlobalLock( pSeg->selector ), pSeg->size ? pSeg->size : 0x10000);
|
||||
size = pSeg->size ? pSeg->size : 0x10000;
|
||||
mem = GlobalLock(pSeg->selector);
|
||||
if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
|
||||
read(fd, mem, size);
|
||||
else {
|
||||
/*
|
||||
The following bit of code for "iterated segments" was written without
|
||||
any documentation on the format of these segments. It seems to work,
|
||||
but may be missing something. If you have any doco please either send
|
||||
it to me or fix the code yourself. gfm@werple.mira.net.au
|
||||
*/
|
||||
char* buff = malloc(size);
|
||||
char* curr = buff;
|
||||
read(fd, buff, size);
|
||||
while(curr < buff + size) {
|
||||
unsigned int rept = *((short*) curr)++;
|
||||
unsigned int len = *((short*) curr)++;
|
||||
for(; rept > 0; rept--) {
|
||||
char* bytes = curr;
|
||||
unsigned int byte;
|
||||
for(byte = 0; byte < len; byte++)
|
||||
*mem++ = *bytes++;
|
||||
}
|
||||
curr += len;
|
||||
}
|
||||
free(buff);
|
||||
}
|
||||
|
||||
if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
|
||||
return TRUE; /* No relocation data, we are done */
|
||||
|
|
|
@ -80,19 +80,21 @@ void init_wine_signals(void)
|
|||
it aligned */
|
||||
segv_act.sa_restorer =
|
||||
(void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
|
||||
usr2_act.sa_restorer= segv_act.sa_restorer;
|
||||
usr2_act.sa_handler = (__sighandler_t) stop_wait;
|
||||
/* Point to the top of the stack, minus 4 just in case, and make
|
||||
it aligned */
|
||||
wine_sigaction(SIGSEGV, &segv_act, NULL);
|
||||
wine_sigaction(SIGILL, &segv_act, NULL);
|
||||
wine_sigaction(SIGFPE, &segv_act, NULL);
|
||||
wine_sigaction(SIGUSR2, &usr2_act, NULL);
|
||||
#ifdef SIGBUS
|
||||
wine_sigaction(SIGBUS, &segv_act, NULL);
|
||||
#endif
|
||||
wine_sigaction(SIGTRAP, &segv_act, NULL); /* For breakpoints */
|
||||
#endif
|
||||
#ifdef CONFIG_IPC
|
||||
usr2_act.sa_restorer= segv_act.sa_restorer;
|
||||
usr2_act.sa_handler = (__sighandler_t) stop_wait;
|
||||
wine_sigaction(SIGUSR2, &usr2_act, NULL);
|
||||
#endif /* CONFIG_IPC */
|
||||
#endif /* linux */
|
||||
#if defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
sigset_t sig_mask;
|
||||
struct sigaltstack ss;
|
||||
|
@ -134,6 +136,7 @@ void init_wine_signals(void)
|
|||
perror("sigaction: SIGTRAP");
|
||||
exit(1);
|
||||
}
|
||||
#ifdef CONFIG_IPC
|
||||
usr2_act.sa_handler = (void (*)) stop_wait; /* For breakpoints */
|
||||
usr2_act.sa_flags = SA_ONSTACK;
|
||||
usr2_act.sa_mask = sig_mask;
|
||||
|
@ -141,7 +144,8 @@ void init_wine_signals(void)
|
|||
perror("sigaction: SIGUSR2");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_IPC */
|
||||
#endif /* __FreeBSD__ || __NetBSD__ */
|
||||
}
|
||||
|
||||
#endif /* ifndef WINELIB */
|
||||
|
|
|
@ -528,7 +528,7 @@ HTASK TASK_CreateTask( HMODULE hModule, HANDLE hInstance, HANDLE hPrevInstance,
|
|||
/***********************************************************************
|
||||
* TASK_DeleteTask
|
||||
*/
|
||||
void TASK_DeleteTask( HTASK hTask )
|
||||
static void TASK_DeleteTask( HTASK hTask )
|
||||
{
|
||||
TDB *pTask;
|
||||
|
||||
|
@ -600,11 +600,16 @@ void TASK_Reschedule(void)
|
|||
TDB *pOldTask = NULL, *pNewTask;
|
||||
HTASK hTask = 0;
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
dde_reschedule();
|
||||
#endif
|
||||
/* First check if there's a task to kill */
|
||||
|
||||
if (hTaskToKill && (hTaskToKill != hCurrentTask))
|
||||
{
|
||||
TASK_DeleteTask( hTaskToKill );
|
||||
hTaskToKill = 0;
|
||||
}
|
||||
|
||||
/* If current task is locked, simply return */
|
||||
|
||||
|
|
756
loader/wine.c
756
loader/wine.c
|
@ -1,756 +0,0 @@
|
|||
static char RCSId[] = "$Id: wine.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
|
||||
static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#ifdef linux
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/head.h>
|
||||
#include <linux/ldt.h>
|
||||
#include <linux/segment.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "neexe.h"
|
||||
#include "segmem.h"
|
||||
#include "prototypes.h"
|
||||
#include "dlls.h"
|
||||
#include "wine.h"
|
||||
#include "windows.h"
|
||||
#include "wineopts.h"
|
||||
#include "arch.h"
|
||||
#include "options.h"
|
||||
|
||||
/* #define DEBUG_FIXUP */
|
||||
|
||||
extern int CallToInit16(unsigned long csip, unsigned long sssp,
|
||||
unsigned short ds);
|
||||
extern void CallTo32();
|
||||
|
||||
char * GetModuleName(struct w_files * wpnt, int index, char *buffer);
|
||||
extern unsigned char ran_out;
|
||||
extern char WindowsPath[256];
|
||||
char *WIN_ProgramName;
|
||||
|
||||
unsigned short WIN_StackSize;
|
||||
unsigned short WIN_HeapSize;
|
||||
|
||||
struct w_files * wine_files = NULL;
|
||||
|
||||
int WineForceFail = 0;
|
||||
|
||||
char **Argv;
|
||||
int Argc;
|
||||
struct mz_header_s *CurrentMZHeader;
|
||||
struct ne_header_s *CurrentNEHeader;
|
||||
int CurrentNEFile;
|
||||
HINSTANCE hSysRes;
|
||||
|
||||
static char *DLL_Extensions[] = { "dll", "exe", NULL };
|
||||
static char *EXE_Extensions[] = { "exe", NULL };
|
||||
static char *WinePath = NULL;
|
||||
|
||||
FILE *SpyFp = NULL;
|
||||
|
||||
/**********************************************************************
|
||||
* myerror
|
||||
*/
|
||||
void
|
||||
myerror(const char *s)
|
||||
{
|
||||
if (s == NULL)
|
||||
perror("wine");
|
||||
else
|
||||
fprintf(stderr, "wine: %s\n", s);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* GetFilenameFromInstance
|
||||
*/
|
||||
char *
|
||||
GetFilenameFromInstance(unsigned short instance)
|
||||
{
|
||||
register struct w_files *w = wine_files;
|
||||
|
||||
while (w && w->hinstance != instance)
|
||||
w = w->next;
|
||||
|
||||
if (w)
|
||||
return w->filename;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct w_files *
|
||||
GetFileInfo(unsigned short instance)
|
||||
{
|
||||
register struct w_files *w = wine_files;
|
||||
|
||||
while (w && w->hinstance != instance)
|
||||
w = w->next;
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
#ifndef WINELIB
|
||||
/**********************************************************************
|
||||
*
|
||||
* Load MZ Header
|
||||
*/
|
||||
void load_mz_header(int fd, struct mz_header_s *mz_header)
|
||||
{
|
||||
if (read(fd, mz_header, sizeof(struct mz_header_s)) !=
|
||||
sizeof(struct mz_header_s))
|
||||
{
|
||||
myerror("Unable to read MZ header from file");
|
||||
}
|
||||
}
|
||||
|
||||
void load_ne_header (int fd, struct ne_header_s *ne_header)
|
||||
{
|
||||
if (read(fd, ne_header, sizeof(struct ne_header_s))
|
||||
!= sizeof(struct ne_header_s))
|
||||
{
|
||||
myerror("Unable to read NE header from file");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**********************************************************************
|
||||
* LoadImage
|
||||
* Load one NE format executable into memory
|
||||
*/
|
||||
HINSTANCE LoadImage(char *modulename, int filetype, int change_dir)
|
||||
{
|
||||
unsigned int read_size;
|
||||
int i;
|
||||
struct w_files * wpnt, *wpnt1;
|
||||
unsigned int status;
|
||||
char buffer[256];
|
||||
char *fullname;
|
||||
|
||||
/*
|
||||
* search file
|
||||
*/
|
||||
fullname = FindFile(buffer, sizeof(buffer), modulename,
|
||||
(filetype == EXE ? EXE_Extensions : DLL_Extensions),
|
||||
WindowsPath);
|
||||
if (fullname == NULL)
|
||||
{
|
||||
fprintf(stderr, "LoadImage: I can't find %s.dll | %s.exe !\n",
|
||||
modulename, modulename);
|
||||
return (HINSTANCE) NULL;
|
||||
}
|
||||
|
||||
fullname = GetDosFileName(fullname);
|
||||
WIN_ProgramName = strdup(fullname);
|
||||
|
||||
fprintf(stderr,"LoadImage: loading %s (%s)\n [%s]\n",
|
||||
modulename, buffer, WIN_ProgramName);
|
||||
|
||||
if (change_dir && fullname)
|
||||
{
|
||||
char dirname[256];
|
||||
char *p;
|
||||
|
||||
strcpy(dirname, fullname);
|
||||
p = strrchr(dirname, '\\');
|
||||
*p = '\0';
|
||||
|
||||
DOS_SetDefaultDrive(dirname[0] - 'A');
|
||||
DOS_ChangeDir(dirname[0] - 'A', dirname + 2);
|
||||
}
|
||||
|
||||
/* First allocate a spot to store the info we collect, and add it to
|
||||
* our linked list.
|
||||
*/
|
||||
|
||||
wpnt = (struct w_files *) malloc(sizeof(struct w_files));
|
||||
if(wine_files == NULL)
|
||||
wine_files = wpnt;
|
||||
else {
|
||||
wpnt1 = wine_files;
|
||||
while(wpnt1->next) wpnt1 = wpnt1->next;
|
||||
wpnt1->next = wpnt;
|
||||
};
|
||||
wpnt->next = NULL;
|
||||
|
||||
/*
|
||||
* Open file for reading.
|
||||
*/
|
||||
wpnt->fd = open(buffer, O_RDONLY);
|
||||
if (wpnt->fd < 0)
|
||||
{
|
||||
myerror(NULL);
|
||||
}
|
||||
/*
|
||||
* Establish header pointers.
|
||||
*/
|
||||
wpnt->filename = strdup(buffer);
|
||||
wpnt->name = NULL;
|
||||
if(modulename) wpnt->name = strdup(modulename);
|
||||
|
||||
wpnt->mz_header = (struct mz_header_s *) malloc(sizeof(struct mz_header_s));;
|
||||
status = lseek(wpnt->fd, 0, SEEK_SET);
|
||||
load_mz_header (wpnt->fd, wpnt->mz_header);
|
||||
if (wpnt->mz_header->must_be_0x40 != 0x40)
|
||||
myerror("This is not a Windows program");
|
||||
|
||||
wpnt->ne_header = (struct ne_header_s *) malloc(sizeof(struct ne_header_s));
|
||||
status = lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET);
|
||||
load_ne_header (wpnt->fd, wpnt->ne_header);
|
||||
if (wpnt->ne_header->header_type[0] != 'N' ||
|
||||
wpnt->ne_header->header_type[1] != 'E')
|
||||
myerror("This is not a Windows program");
|
||||
|
||||
if(wine_files == wpnt){
|
||||
CurrentMZHeader = wpnt->mz_header;
|
||||
CurrentNEHeader = wpnt->ne_header;
|
||||
CurrentNEFile = wpnt->fd;
|
||||
|
||||
WIN_StackSize = wpnt->ne_header->stack_length;
|
||||
WIN_HeapSize = wpnt->ne_header->local_heap_length;
|
||||
};
|
||||
|
||||
/*
|
||||
* Create segment selectors.
|
||||
*/
|
||||
#ifndef WINELIB
|
||||
status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
|
||||
wpnt->ne_header->segment_tab_offset,
|
||||
SEEK_SET);
|
||||
read_size = wpnt->ne_header->n_segment_tab *
|
||||
sizeof(struct ne_segment_table_entry_s);
|
||||
wpnt->seg_table = (struct ne_segment_table_entry_s *) malloc(read_size);
|
||||
if (read(wpnt->fd, wpnt->seg_table, read_size) != read_size)
|
||||
myerror("Unable to read segment table header from file");
|
||||
wpnt->selector_table = CreateSelectors(wpnt);
|
||||
wpnt->hinstance
|
||||
= wpnt->
|
||||
selector_table[wpnt->ne_header->auto_data_seg-1].selector;
|
||||
|
||||
/* Get the lookup table. This is used for looking up the addresses
|
||||
of functions that are exported */
|
||||
|
||||
read_size = wpnt->ne_header->entry_tab_length;
|
||||
wpnt->lookup_table = (char *) malloc(read_size);
|
||||
lseek(wpnt->fd, wpnt->mz_header->ne_offset +
|
||||
wpnt->ne_header->entry_tab_offset, SEEK_SET);
|
||||
if (read(wpnt->fd, wpnt->lookup_table, read_size) != read_size)
|
||||
myerror("Unable to read lookup table header from file");
|
||||
|
||||
/* Get the iname table. This is used for looking up the names
|
||||
of functions that are exported */
|
||||
|
||||
status = lseek(wpnt->fd, wpnt->ne_header->nrname_tab_offset, SEEK_SET);
|
||||
read_size = wpnt->ne_header->nrname_tab_length;
|
||||
wpnt->nrname_table = (char *) malloc(read_size);
|
||||
if (read(wpnt->fd, wpnt->nrname_table, read_size) != read_size)
|
||||
myerror("Unable to read nrname table header from file");
|
||||
|
||||
status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
|
||||
wpnt->ne_header->rname_tab_offset, SEEK_SET);
|
||||
read_size = wpnt->ne_header->moduleref_tab_offset -
|
||||
wpnt->ne_header->rname_tab_offset;
|
||||
wpnt->rname_table = (char *) malloc(read_size);
|
||||
if (read(wpnt->fd, wpnt->rname_table, read_size) != read_size)
|
||||
myerror("Unable to read rname table header from file");
|
||||
|
||||
/* Now get the module name */
|
||||
|
||||
wpnt->name = (char*) malloc(*wpnt->rname_table + 1);
|
||||
memcpy(wpnt->name, wpnt->rname_table+1, *wpnt->rname_table);
|
||||
wpnt->name[*wpnt->rname_table] = 0;
|
||||
#endif
|
||||
/*
|
||||
* Now load any DLLs that this module refers to.
|
||||
*/
|
||||
for(i=0; i<wpnt->ne_header->n_mod_ref_tab; i++){
|
||||
char buff[14];
|
||||
char buff2[256];
|
||||
int fd, j;
|
||||
GetModuleName(wpnt, i + 1, buff);
|
||||
|
||||
#ifndef WINELIB
|
||||
if(FindDLLTable(buff)) continue; /* This module already loaded */
|
||||
#endif
|
||||
|
||||
LoadImage(buff, DLL, 0);
|
||||
/*
|
||||
fprintf(stderr,"Unable to load:%s\n", buff);
|
||||
*/
|
||||
}
|
||||
return(wpnt->hinstance);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* main
|
||||
*/
|
||||
_WinMain(int argc, char **argv)
|
||||
{
|
||||
int segment;
|
||||
char *p;
|
||||
char *sysresname;
|
||||
char filename[100];
|
||||
char syspath[256];
|
||||
char exe_path[256];
|
||||
#ifdef WINESTAT
|
||||
char * cp;
|
||||
#endif
|
||||
struct w_files * wpnt;
|
||||
int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
|
||||
int i;
|
||||
int rv;
|
||||
|
||||
Argc = argc - 1;
|
||||
Argv = argv + 1;
|
||||
|
||||
WinePath = malloc(1024);
|
||||
|
||||
getcwd(WinePath, 512);
|
||||
|
||||
if ((p = getenv("WINEPATH")) != NULL) {
|
||||
strcat(WinePath, ";");
|
||||
strcat(WinePath, p);
|
||||
}
|
||||
|
||||
if ((hInstMain = LoadImage(Argv[0], EXE, 1)) == (HINSTANCE) NULL ) {
|
||||
fprintf(stderr, "wine: can't find %s!.\n", Argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
GetPrivateProfileString("wine", "SystemResources", "sysres.dll",
|
||||
filename, sizeof(filename), WINE_INI);
|
||||
|
||||
hSysRes = LoadImage(filename, DLL);
|
||||
if (hSysRes == (HINSTANCE)NULL)
|
||||
fprintf(stderr, "wine: can't find %s!\n", filename);
|
||||
else
|
||||
printf("System Resources Loaded // hSysRes='%04X'\n", hSysRes);
|
||||
|
||||
/*
|
||||
* Fixup references.
|
||||
*/
|
||||
wpnt = wine_files;
|
||||
for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
|
||||
{
|
||||
for (segment = 0; segment < wpnt->ne_header->n_segment_tab; segment++)
|
||||
{
|
||||
if (FixupSegment(wpnt, segment) < 0)
|
||||
{
|
||||
myerror("fixup failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WINESTAT
|
||||
cp = strrchr(argv[0], '/');
|
||||
if(!cp) cp = argv[0];
|
||||
else cp++;
|
||||
if(strcmp(cp,"winestat") == 0) {
|
||||
winestat();
|
||||
exit(0);
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize signal handling.
|
||||
*/
|
||||
init_wine_signals();
|
||||
|
||||
/*
|
||||
* Fixup stack and jump to start.
|
||||
*/
|
||||
ds_reg = (wine_files->
|
||||
selector_table[wine_files->ne_header->auto_data_seg-1].selector);
|
||||
cs_reg = wine_files->selector_table[wine_files->ne_header->cs-1].selector;
|
||||
ip_reg = wine_files->ne_header->ip;
|
||||
ss_reg = wine_files->selector_table[wine_files->ne_header->ss-1].selector;
|
||||
sp_reg = wine_files->ne_header->sp;
|
||||
|
||||
if (Options.debug) wine_debug(0, NULL);
|
||||
|
||||
rv = CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
|
||||
printf ("rv = %x\n", rv);
|
||||
}
|
||||
|
||||
void InitializeLoadedDLLs()
|
||||
{
|
||||
struct w_files * wpnt;
|
||||
int cs_reg, ds_reg, ip_reg;
|
||||
int rv;
|
||||
|
||||
fprintf(stderr, "Initializing DLLs\n");
|
||||
|
||||
/*
|
||||
* Initialize libraries
|
||||
*/
|
||||
wpnt = wine_files;
|
||||
for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
|
||||
{
|
||||
/*
|
||||
* Is this a library?
|
||||
*/
|
||||
if (wpnt->ne_header->format_flags & 0x8000)
|
||||
{
|
||||
if (!(wpnt->ne_header->format_flags & 0x0001))
|
||||
{
|
||||
/* Not SINGLEDATA */
|
||||
fprintf(stderr, "Library is not marked SINGLEDATA\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ds_reg = wpnt->selector_table[wpnt->
|
||||
ne_header->auto_data_seg-1].selector;
|
||||
cs_reg = wpnt->selector_table[wpnt->ne_header->cs-1].selector;
|
||||
ip_reg = wpnt->ne_header->ip;
|
||||
|
||||
fprintf(stderr, "Initializing %s, cs:ip %04x:%04x, ds %04x\n",
|
||||
wpnt->name, cs_reg, ip_reg, ds_reg);
|
||||
|
||||
rv = CallTo16(cs_reg << 16 | ip_reg, ds_reg);
|
||||
printf ("rv = %x\n", rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* GetImportedName
|
||||
*/
|
||||
char *
|
||||
GetImportedName(int fd, struct mz_header_s *mz_header,
|
||||
struct ne_header_s *ne_header, int name_offset, char *buffer)
|
||||
{
|
||||
char *p;
|
||||
int length;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
|
||||
name_offset, SEEK_SET);
|
||||
length = 0;
|
||||
read(fd, &length, 1); /* Get the length byte */
|
||||
length = CONV_CHAR_TO_LONG (length);
|
||||
read(fd, buffer, length);
|
||||
buffer[length] = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* GetModuleName
|
||||
*/
|
||||
char *
|
||||
GetModuleName(struct w_files * wpnt, int index, char *buffer)
|
||||
{
|
||||
int fd = wpnt->fd;
|
||||
struct mz_header_s *mz_header = wpnt->mz_header;
|
||||
struct ne_header_s *ne_header = wpnt->ne_header;
|
||||
char *p;
|
||||
int length;
|
||||
WORD name_offset, status;
|
||||
int i;
|
||||
|
||||
status = lseek(fd, mz_header->ne_offset + ne_header->moduleref_tab_offset +
|
||||
2*(index - 1), SEEK_SET);
|
||||
name_offset = 0;
|
||||
read(fd, &name_offset, 2);
|
||||
name_offset = CONV_SHORT (name_offset);
|
||||
status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
|
||||
name_offset, SEEK_SET);
|
||||
length = 0;
|
||||
read(fd, &length, 1); /* Get the length byte */
|
||||
length = CONV_CHAR_TO_LONG (length);
|
||||
read(fd, buffer, length);
|
||||
buffer[length] = 0;
|
||||
|
||||
/* Module names are always upper case */
|
||||
for(i=0; i<length; i++)
|
||||
if(buffer[i] >= 'a' && buffer[i] <= 'z') buffer[i] &= ~0x20;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
#ifndef WINELIB
|
||||
/**********************************************************************
|
||||
* FixupSegment
|
||||
*/
|
||||
int
|
||||
FixupSegment(struct w_files * wpnt, int segment_num)
|
||||
{
|
||||
int fd = wpnt->fd;
|
||||
struct mz_header_s * mz_header = wpnt->mz_header;
|
||||
struct ne_header_s *ne_header = wpnt->ne_header;
|
||||
struct ne_segment_table_entry_s *seg_table = wpnt->seg_table;
|
||||
struct segment_descriptor_s *selector_table = wpnt->selector_table;
|
||||
struct relocation_entry_s *rep, *rep1;
|
||||
struct ne_segment_table_entry_s *seg;
|
||||
struct segment_descriptor_s *sel;
|
||||
struct dll_table_entry_s *dll_table;
|
||||
int status;
|
||||
unsigned short *sp;
|
||||
unsigned int selector, address;
|
||||
unsigned int next_addr;
|
||||
int ordinal;
|
||||
char dll_name[257];
|
||||
char func_name[257];
|
||||
int i, n_entries;
|
||||
int additive;
|
||||
|
||||
seg = &seg_table[segment_num];
|
||||
sel = &selector_table[segment_num];
|
||||
|
||||
#ifdef DEBUG_FIXUP
|
||||
printf("Segment fixups for %s, segment %d, selector %x\n",
|
||||
wpnt->name, segment_num, (int) sel->base_addr >> 16);
|
||||
#endif
|
||||
|
||||
if ((seg->seg_data_offset == 0) ||
|
||||
!(seg->seg_flags & NE_SEGFLAGS_RELOC_DATA))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Go through the relocation table on entry at a time.
|
||||
*/
|
||||
i = seg->seg_data_length;
|
||||
if (i == 0)
|
||||
i = 0x10000;
|
||||
|
||||
status = lseek(fd, seg->seg_data_offset *
|
||||
(1 << ne_header->align_shift_count) + i, SEEK_SET);
|
||||
n_entries = 0;
|
||||
read(fd, &n_entries, sizeof(short int));
|
||||
rep = (struct relocation_entry_s *)
|
||||
malloc(n_entries * sizeof(struct relocation_entry_s));
|
||||
|
||||
if (read(fd,rep, n_entries * sizeof(struct relocation_entry_s)) !=
|
||||
n_entries * sizeof(struct relocation_entry_s))
|
||||
{
|
||||
myerror("Unable to read relocation information");
|
||||
}
|
||||
|
||||
rep1 = rep;
|
||||
|
||||
for (i = 0; i < n_entries; i++, rep++)
|
||||
{
|
||||
/*
|
||||
* Get the target address corresponding to this entry.
|
||||
*/
|
||||
additive = 0;
|
||||
|
||||
switch (rep->relocation_type)
|
||||
{
|
||||
case NE_RELTYPE_ORDINALADD:
|
||||
additive = 1;
|
||||
|
||||
case NE_RELTYPE_ORDINAL:
|
||||
if (GetModuleName(wpnt, rep->target1,
|
||||
dll_name) == NULL)
|
||||
{
|
||||
fprintf(stderr, "NE_RELTYPE_ORDINAL failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ordinal = rep->target2;
|
||||
|
||||
status = GetEntryDLLOrdinal(dll_name, ordinal, &selector,
|
||||
&address);
|
||||
if (status)
|
||||
{
|
||||
char s[80];
|
||||
|
||||
sprintf(s, "Bad DLL name '%s.%d'", dll_name, ordinal);
|
||||
myerror(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FIXUP
|
||||
printf("%d: %s.%d: %04.4x:%04.4x\n", i + 1, dll_name, ordinal,
|
||||
selector, address);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case NE_RELTYPE_NAMEADD:
|
||||
additive = 1;
|
||||
|
||||
case NE_RELTYPE_NAME:
|
||||
if (GetModuleName(wpnt, rep->target1, dll_name)
|
||||
== NULL)
|
||||
{
|
||||
fprintf(stderr,"NE_RELTYPE_NAME failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (GetImportedName(fd, mz_header, ne_header,
|
||||
rep->target2, func_name) == NULL)
|
||||
{
|
||||
fprintf(stderr,"getimportedname failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = GetEntryDLLName(dll_name, func_name, &selector,
|
||||
&address);
|
||||
if (status)
|
||||
{
|
||||
char s[80];
|
||||
|
||||
sprintf(s, "Bad DLL name '%s (%s)'", dll_name,func_name);
|
||||
myerror(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FIXUP
|
||||
printf("%d: %s %s.%d: %04.4x:%04.4x\n", i + 1, func_name,
|
||||
dll_name, ordinal, selector, address);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case NE_RELTYPE_INTERNAL:
|
||||
case NE_RELTYPE_INT1:
|
||||
if (rep->target1 == 0x00ff)
|
||||
{
|
||||
address = GetEntryPointFromOrdinal(wpnt, rep->target2);
|
||||
selector = (address >> 16) & 0xffff;
|
||||
address &= 0xffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
selector = selector_table[rep->target1-1].selector;
|
||||
address = rep->target2;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FIXUP
|
||||
printf("%d: %04.4x:%04.4x\n", i + 1, selector, address);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 7:
|
||||
/* Relocation type 7:
|
||||
*
|
||||
* These appear to be used as fixups for the Windows
|
||||
* floating point emulator. Let's just ignore them and
|
||||
* try to use the hardware floating point. Linux should
|
||||
* successfully emulate the coprocessor if it doesn't
|
||||
* exist.
|
||||
*/
|
||||
#ifdef DEBUG_FIXUP
|
||||
printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
|
||||
i + 1, rep->address_type, rep->relocation_type,
|
||||
rep->offset);
|
||||
printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
|
||||
#endif
|
||||
continue;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
|
||||
i + 1, rep->address_type, rep->relocation_type,
|
||||
rep->offset);
|
||||
fprintf(stderr,"TARGET %04.4x %04.4x\n",
|
||||
rep->target1, rep->target2);
|
||||
free(rep1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stuff the right size result in.
|
||||
*/
|
||||
sp = (unsigned short *) ((char *) sel->base_addr + rep->offset);
|
||||
if (additive)
|
||||
{
|
||||
if (FindDLLTable(dll_name) == NULL)
|
||||
additive = 2;
|
||||
|
||||
fprintf(stderr,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
|
||||
i + 1, rep->address_type, rep->relocation_type,
|
||||
rep->offset);
|
||||
fprintf(stderr,"TARGET %04.4x %04.4x\n",
|
||||
rep->target1, rep->target2);
|
||||
fprintf(stderr, " Additive = %d\n", additive);
|
||||
}
|
||||
|
||||
switch (rep->address_type)
|
||||
{
|
||||
case NE_RADDR_OFFSET16:
|
||||
do {
|
||||
#ifdef DEBUG_FIXUP
|
||||
printf(" %04.4x:%04.4x:%04.4x OFFSET16\n",
|
||||
(unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
|
||||
#endif
|
||||
next_addr = *sp;
|
||||
*sp = (unsigned short) address;
|
||||
if (additive == 2)
|
||||
*sp += next_addr;
|
||||
sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
|
||||
}
|
||||
while (next_addr != 0xffff && !additive);
|
||||
|
||||
break;
|
||||
|
||||
case NE_RADDR_POINTER32:
|
||||
do {
|
||||
#ifdef DEBUG_FIXUP
|
||||
printf(" %04.4x:%04.4x:%04.4x POINTER32\n",
|
||||
(unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
|
||||
#endif
|
||||
next_addr = *sp;
|
||||
*sp = (unsigned short) address;
|
||||
if (additive == 2)
|
||||
*sp += next_addr;
|
||||
*(sp+1) = (unsigned short) selector;
|
||||
sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
|
||||
}
|
||||
while (next_addr != 0xffff && !additive);
|
||||
|
||||
break;
|
||||
|
||||
case NE_RADDR_SELECTOR:
|
||||
do {
|
||||
#ifdef DEBUG_FIXUP
|
||||
printf(" %04.4x:%04.4x:%04.4x SELECTOR\n",
|
||||
(unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
|
||||
#endif
|
||||
next_addr = *sp;
|
||||
*sp = (unsigned short) selector;
|
||||
sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
|
||||
if (rep->relocation_type == NE_RELTYPE_INT1)
|
||||
break;
|
||||
}
|
||||
while (next_addr != 0xffff && !additive);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
|
||||
i + 1, rep->address_type, rep->relocation_type,
|
||||
rep->offset);
|
||||
printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
|
||||
free(rep1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
free(rep1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* GetProcAddress
|
||||
*/
|
||||
FARPROC GetProcAddress(HINSTANCE hinstance, char *proc_name)
|
||||
{
|
||||
if ((int) proc_name & 0xffff0000)
|
||||
printf("GetProcAddress: %#04x, '%s'\n", hinstance, proc_name);
|
||||
else
|
||||
printf("GetProcAddress: %#04x, %d\n", hinstance, (int) proc_name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
|
@ -32,7 +32,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
#include "stackframe.h"
|
||||
#include "user.h"
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
#include "dde_atom.h"
|
||||
#include "options.h"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_ATOMTABLE_SIZE 37
|
||||
#define MIN_STR_ATOM 0xc000
|
||||
|
||||
|
@ -321,36 +326,48 @@ WORD GetAtomName( ATOM atom, LPSTR buffer, short count )
|
|||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalAddAtom (USER.268)
|
||||
* GlobalAddAtom (USER.268)
|
||||
*/
|
||||
ATOM LocalAddAtom( SEGPTR str )
|
||||
ATOM GlobalAddAtom( SEGPTR str )
|
||||
{
|
||||
#ifdef CONFIG_IPC
|
||||
if (Options.ipc) return DDE_GlobalAddAtom( str );
|
||||
#endif
|
||||
return ATOM_AddAtom( USER_HeapSel, str );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalDeleteAtom (USER.269)
|
||||
* GlobalDeleteAtom (USER.269)
|
||||
*/
|
||||
ATOM LocalDeleteAtom( ATOM atom )
|
||||
ATOM GlobalDeleteAtom( ATOM atom )
|
||||
{
|
||||
#ifdef CONFIG_IPC
|
||||
if (Options.ipc) return DDE_GlobalDeleteAtom( atom );
|
||||
#endif
|
||||
return ATOM_DeleteAtom( USER_HeapSel, atom );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalFindAtom (USER.270)
|
||||
* GlobalFindAtom (USER.270)
|
||||
*/
|
||||
ATOM LocalFindAtom( SEGPTR str )
|
||||
ATOM GlobalFindAtom( SEGPTR str )
|
||||
{
|
||||
#ifdef CONFIG_IPC
|
||||
if (Options.ipc) return DDE_GlobalFindAtom( str );
|
||||
#endif
|
||||
return ATOM_FindAtom( USER_HeapSel, str );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalGetAtomName (USER.271)
|
||||
* GlobalGetAtomName (USER.271)
|
||||
*/
|
||||
WORD LocalGetAtomName( ATOM atom, LPSTR buffer, short count )
|
||||
WORD GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
|
||||
{
|
||||
#ifdef CONFIG_IPC
|
||||
if (Options.ipc) return DDE_GlobalGetAtomName( atom, buffer, count );
|
||||
#endif
|
||||
return ATOM_GetAtomName( USER_HeapSel, atom, buffer, count );
|
||||
}
|
||||
|
|
|
@ -81,21 +81,6 @@ void debug_handles()
|
|||
if (printed)
|
||||
printf("\n");
|
||||
}
|
||||
/***********************************************************************
|
||||
* GLOBAL_FindArena
|
||||
*
|
||||
* Find the arena for a given handle
|
||||
* (when handle is not serial - e.g. DDE)
|
||||
*/
|
||||
static GLOBALARENA *GLOBAL_FindArena( HGLOBAL handle)
|
||||
{
|
||||
int i;
|
||||
for (i = globalArenaSize-1 ; i>=0 ; i--) {
|
||||
if (pGlobalArena[i].size!=0 && pGlobalArena[i].handle == handle)
|
||||
return ( &pGlobalArena[i] );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -196,9 +181,11 @@ HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
|
|||
|
||||
/* Allocate the linear memory */
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
if ((flags & GMEM_DDESHARE) && Options.ipc)
|
||||
ptr= DDE_malloc(flags, size, &shmdata);
|
||||
ptr = DDE_malloc(flags, size, &shmdata);
|
||||
else
|
||||
#endif /* CONFIG_IPC */
|
||||
ptr = malloc( size );
|
||||
if (!ptr) return 0;
|
||||
|
||||
|
@ -216,6 +203,25 @@ HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
|
|||
return handle;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
/***********************************************************************
|
||||
* GLOBAL_FindArena
|
||||
*
|
||||
* Find the arena for a given handle
|
||||
* (when handle is not serial - e.g. DDE)
|
||||
*/
|
||||
static GLOBALARENA *GLOBAL_FindArena( HGLOBAL handle)
|
||||
{
|
||||
int i;
|
||||
for (i = globalArenaSize-1 ; i>=0 ; i--) {
|
||||
if (pGlobalArena[i].size!=0 && pGlobalArena[i].handle == handle)
|
||||
return ( &pGlobalArena[i] );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DDE_GlobalHandleToSel
|
||||
*/
|
||||
|
@ -238,6 +244,7 @@ WORD DDE_GlobalHandleToSel( HGLOBAL handle )
|
|||
|
||||
return SELECTOROF( segptr );
|
||||
}
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -268,11 +275,13 @@ HGLOBAL GlobalReAlloc( HGLOBAL handle, DWORD size, WORD flags )
|
|||
handle, size, flags );
|
||||
if (!handle) return 0;
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
if (Options.ipc && (flags & GMEM_DDESHARE || is_dde_handle(handle))) {
|
||||
fprintf(stdnimp,
|
||||
"GlobalReAlloc: shared memory reallocating unimplemented\n");
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
pArena = GET_ARENA_PTR( handle );
|
||||
|
||||
|
@ -366,7 +375,9 @@ HGLOBAL GlobalFree( HGLOBAL handle )
|
|||
|
||||
dprintf_global( stddeb, "GlobalFree: %04x\n", handle );
|
||||
if (!GLOBAL_FreeBlock( handle )) return handle; /* failed */
|
||||
#ifdef CONFIG_IPC
|
||||
if (is_dde_handle(handle)) return DDE_GlobalFree(handle);
|
||||
#endif /* CONFIG_IPC */
|
||||
if (ptr) free( ptr );
|
||||
return 0;
|
||||
}
|
||||
|
@ -382,9 +393,13 @@ SEGPTR WIN16_GlobalLock( HGLOBAL handle )
|
|||
dprintf_global( stddeb, "WIN16_GlobalLock(%04x) -> %08lx\n",
|
||||
handle, MAKELONG( 0, GlobalHandleToSel(handle)) );
|
||||
if (!handle) return 0;
|
||||
if ( !is_dde_handle(handle) && !GET_ARENA_PTR(handle)->base)
|
||||
return (SEGPTR)0;
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
if (is_dde_handle(handle))
|
||||
return (SEGPTR)MAKELONG( 0, DDE_GlobalHandleToSel(handle) );
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
if (!GET_ARENA_PTR(handle)->base) return (SEGPTR)0;
|
||||
return (SEGPTR)MAKELONG( 0, GlobalHandleToSel(handle) );
|
||||
}
|
||||
|
||||
|
@ -397,9 +412,9 @@ SEGPTR WIN16_GlobalLock( HGLOBAL handle )
|
|||
LPSTR GlobalLock( HGLOBAL handle )
|
||||
{
|
||||
if (!handle) return 0;
|
||||
if (is_dde_handle(handle)) {
|
||||
return DDE_AttachHandle(handle, NULL);
|
||||
}
|
||||
#ifdef CONFIG_IPC
|
||||
if (is_dde_handle(handle)) return DDE_AttachHandle(handle, NULL);
|
||||
#endif
|
||||
return (LPSTR)GET_ARENA_PTR(handle)->base;
|
||||
}
|
||||
|
||||
|
@ -644,9 +659,9 @@ WORD GlobalHandleToSel( HGLOBAL handle )
|
|||
{
|
||||
dprintf_toolhelp( stddeb, "GlobalHandleToSel: %04x\n", handle );
|
||||
if (!handle) return 0;
|
||||
if (is_dde_handle(handle))
|
||||
return DDE_GlobalHandleToSel(handle);
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
if (is_dde_handle(handle)) return DDE_GlobalHandleToSel(handle);
|
||||
#endif
|
||||
if (!(handle & 7))
|
||||
{
|
||||
fprintf( stderr, "Program attempted invalid selector conversion\n" );
|
||||
|
|
|
@ -36,7 +36,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
|
|
@ -143,6 +143,7 @@ HANDLE GetClipboardData(WORD wFormat)
|
|||
{
|
||||
LPCLIPFORMAT lpFormat = ClipFormats;
|
||||
dprintf_clipboard(stddeb,"GetClipboardData(%04X) !\n", wFormat);
|
||||
if (!hWndClipboardOwner) return 0;
|
||||
if(wFormat == CF_TEXT && !wineOwnsSelection)
|
||||
{ wait_for_selection=True;
|
||||
dprintf_clipboard(stddeb,"Requesting selection\n");
|
||||
|
|
|
@ -75,7 +75,7 @@ INT _lread (INT hFile, LPSTR lpBuffer, WORD wBytes)
|
|||
dprintf_file(stddeb, "_lread: handle %d, buffer = %p, length = %d\n",
|
||||
hFile, lpBuffer, wBytes);
|
||||
|
||||
result = wBytes == 0 ? 0 : read (hFile, lpBuffer, wBytes);
|
||||
result = (wBytes == 0) ? 0 : read (hFile, lpBuffer, wBytes);
|
||||
|
||||
if (result == -1)
|
||||
return HFILE_ERROR;
|
||||
|
@ -454,12 +454,12 @@ WORD SetErrorMode(WORD x)
|
|||
***************************************************************************/
|
||||
LONG _hread(INT hf, LPSTR hpvBuffer, LONG cbBuffer)
|
||||
{
|
||||
return cbBuffer == 0 ? 0 : read(hf, hpvBuffer, cbBuffer);
|
||||
return (cbBuffer == 0) ? 0 : read(hf, hpvBuffer, cbBuffer);
|
||||
}
|
||||
/***************************************************************************
|
||||
_hwrite
|
||||
***************************************************************************/
|
||||
LONG _hwrite(INT hf, LPCSTR hpvBuffer, LONG cbBuffer)
|
||||
{
|
||||
return cbBuffer == 0 ? 0 : write(hf, hpvBuffer, cbBuffer);
|
||||
return (cbBuffer == 0) ? 0 : write(hf, hpvBuffer, cbBuffer);
|
||||
}
|
||||
|
|
24
misc/main.c
24
misc/main.c
|
@ -846,3 +846,27 @@ void FileCDR(FARPROC x)
|
|||
{
|
||||
printf("FileCDR(%8x)\n", (int) x);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetWinDebugInfo (KERNEL.355)
|
||||
*/
|
||||
BOOL GetWinDebugInfo(WINDEBUGINFO FAR* lpwdi, UINT flags)
|
||||
{
|
||||
printf("GetWinDebugInfo(%8lx,%d) stub returning 0\n", (unsigned long)lpwdi, flags);
|
||||
/* 0 means not in debugging mode/version */
|
||||
/* Can this type of debugging be used in wine ? */
|
||||
/* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetWinDebugInfo (KERNEL.355)
|
||||
*/
|
||||
BOOL SetWinDebugInfo(WINDEBUGINFO FAR* lpwdi)
|
||||
{
|
||||
printf("SetWinDebugInfo(%8lx) stub returning 0\n", (unsigned long)lpwdi);
|
||||
/* 0 means not in debugging mode/version */
|
||||
/* Can this type of debugging be used in wine ? */
|
||||
/* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -382,6 +382,8 @@ WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default)
|
|||
BOOL WritePrivateProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String,
|
||||
LPSTR FileName)
|
||||
{
|
||||
if (!AppName || !KeyName || !String) /* Flush file to disk */
|
||||
return TRUE;
|
||||
return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName);
|
||||
}
|
||||
|
||||
|
|
|
@ -450,10 +450,14 @@ static char AppName[512], AppMisc[512];
|
|||
*/
|
||||
INT AboutDlgProc(HWND hWnd, WORD msg, WORD wParam, LONG lParam)
|
||||
{
|
||||
char Template[512], AppTitle[512];
|
||||
|
||||
switch(msg) {
|
||||
case WM_INITDIALOG:
|
||||
SendDlgItemMessage(hWnd,stc1,STM_SETICON,LOWORD(lParam),0);
|
||||
SetWindowText(hWnd, AppName);
|
||||
GetWindowText(hWnd, Template, 511);
|
||||
sprintf(AppTitle, Template, AppName);
|
||||
SetWindowText(hWnd, AppTitle);
|
||||
SetWindowText(GetDlgItem(hWnd,100), AppMisc);
|
||||
return 1;
|
||||
|
||||
|
@ -474,7 +478,7 @@ INT AboutDlgProc(HWND hWnd, WORD msg, WORD wParam, LONG lParam)
|
|||
INT ShellAbout(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon)
|
||||
{
|
||||
if (szApp) {
|
||||
sprintf(AppName, "About %s", szApp);
|
||||
strcpy(AppName, szApp);
|
||||
} else {
|
||||
*AppName = 0;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
MODULE = miscemu
|
||||
|
||||
SRCS = \
|
||||
dosmem.c \
|
||||
dpmi.c \
|
||||
emulate.c \
|
||||
instr.c \
|
||||
|
|
|
@ -9,9 +9,22 @@ LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
|
|||
|
||||
MODULE = miscemu
|
||||
|
||||
SRCS = dpmi.c emulate.c instr.c int10.c int13.c \
|
||||
int1a.c int21.c int25.c int26.c int2a.c int2f.c int5c.c interrupts.c \
|
||||
ioports.c
|
||||
SRCS = \
|
||||
dosmem.c \
|
||||
dpmi.c \
|
||||
emulate.c \
|
||||
instr.c \
|
||||
int10.c \
|
||||
int13.c \
|
||||
int1a.c \
|
||||
int21.c \
|
||||
int25.c \
|
||||
int26.c \
|
||||
int2a.c \
|
||||
int2f.c \
|
||||
int5c.c \
|
||||
interrupts.c \
|
||||
ioports.c
|
||||
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
||||
|
@ -29,7 +42,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
|
184
miscemu/dosmem.c
Normal file
184
miscemu/dosmem.c
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* DOS memory emulation
|
||||
*
|
||||
* Copyright 1995 Alexandre Julliard
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "windows.h"
|
||||
#include "global.h"
|
||||
#include "ldt.h"
|
||||
#include "miscemu.h"
|
||||
#include "module.h"
|
||||
|
||||
|
||||
HANDLE DOSMEM_BiosSeg; /* BIOS data segment at 0x40:0 */
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD Com1Addr; /* 00: COM1 I/O address */
|
||||
WORD Com2Addr; /* 02: COM2 I/O address */
|
||||
WORD Com3Addr; /* 04: COM3 I/O address */
|
||||
WORD Com4Addr; /* 06: COM4 I/O address */
|
||||
WORD Lpt1Addr; /* 08: LPT1 I/O address */
|
||||
WORD Lpt2Addr; /* 0a: LPT2 I/O address */
|
||||
WORD Lpt3Addr; /* 0c: LPT3 I/O address */
|
||||
WORD Lpt4Addr; /* 0e: LPT4 I/O address */
|
||||
WORD InstalledHardware; /* 10: Installed hardware flags */
|
||||
BYTE POSTstatus; /* 12: Power-On Self Test status */
|
||||
WORD MemSize WINE_PACKED; /* 13: Base memory size in Kb */
|
||||
WORD unused1 WINE_PACKED; /* 15: Manufacturing test scratch pad */
|
||||
BYTE KbdFlags1; /* 17: Keyboard flags 1 */
|
||||
BYTE KbdFlags2; /* 18: Keyboard flags 2 */
|
||||
BYTE unused2; /* 19: Keyboard driver workspace */
|
||||
WORD NextKbdCharPtr; /* 1a: Next character in kbd buffer */
|
||||
WORD FirstKbdCharPtr; /* 1c: First character in kbd buffer */
|
||||
WORD KbdBuffer[16]; /* 1e: Keyboard buffer */
|
||||
BYTE DisketteStatus1; /* 3e: Diskette recalibrate status */
|
||||
BYTE DisketteStatus2; /* 3f: Diskette motor status */
|
||||
BYTE DisketteStatus3; /* 40: Diskette motor timeout */
|
||||
BYTE DisketteStatus4; /* 41: Diskette last operation status */
|
||||
BYTE DiskStatus[7]; /* 42: Disk status/command bytes */
|
||||
BYTE VideoMode; /* 49: Video mode */
|
||||
WORD VideoColumns; /* 4a: Number of columns */
|
||||
WORD VideoPageSize; /* 4c: Video page size in bytes */
|
||||
WORD VideoPageStartAddr; /* 4e: Video page start address */
|
||||
BYTE VideoCursorPos[16]; /* 50: Cursor position for 8 pages */
|
||||
WORD VideoCursorType; /* 60: Video cursor type */
|
||||
BYTE VideoCurPage; /* 62: Video current page */
|
||||
WORD VideoCtrlAddr WINE_PACKED; /* 63: Video controller address */
|
||||
BYTE VideoReg1; /* 65: Video mode select register */
|
||||
BYTE VideoReg2; /* 66: Video CGA palette register */
|
||||
DWORD ResetEntry WINE_PACKED; /* 67: Warm reset entry point */
|
||||
BYTE LastIRQ; /* 6b: Last unexpected interrupt */
|
||||
DWORD Ticks; /* 6c: Ticks since midnight */
|
||||
BYTE TicksOverflow; /* 70: Timer overflow if past midnight */
|
||||
BYTE CtrlBreakFlag; /* 71: Ctrl-Break flag */
|
||||
WORD ResetFlag; /* 72: POST Reset flag */
|
||||
BYTE DiskOpStatus; /* 74: Last hard-disk operation status */
|
||||
BYTE NbHardDisks; /* 75: Number of hard disks */
|
||||
BYTE DiskCtrlByte; /* 76: Disk control byte */
|
||||
BYTE DiskIOPort; /* 77: Disk I/O port offset */
|
||||
BYTE LptTimeout[4]; /* 78: Timeouts for parallel ports */
|
||||
BYTE ComTimeout[4]; /* 7c: Timeouts for serial ports */
|
||||
WORD KbdBufferStart; /* 80: Keyboard buffer start */
|
||||
WORD KbdBufferEnd; /* 82: Keyboard buffer end */
|
||||
} BIOSDATA;
|
||||
|
||||
#pragma pack(4)
|
||||
|
||||
|
||||
static BIOSDATA *pBiosData = NULL;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSMEM_Init
|
||||
*
|
||||
* Create the dos memory segments, and store them into the KERNEL
|
||||
* exported values. MODULE_Init() must already have been called.
|
||||
*/
|
||||
BOOL DOSMEM_Init(void)
|
||||
{
|
||||
HMODULE hModule = GetModuleHandle( "KERNEL" );
|
||||
char *dosmem;
|
||||
|
||||
/* Allocate 7 64k segments for 0000, A000, B000, C000, D000, E000, F000. */
|
||||
|
||||
dosmem = malloc( 0x70000 );
|
||||
|
||||
MODULE_SetEntryPoint( hModule, 183, /* KERNEL.183: __0000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
DOSMEM_BiosSeg = GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x400, 0x100,
|
||||
hModule, FALSE, FALSE, FALSE, NULL );
|
||||
|
||||
MODULE_SetEntryPoint( hModule, 193, /* KERNEL.193: __0040H */
|
||||
DOSMEM_BiosSeg );
|
||||
MODULE_SetEntryPoint( hModule, 174, /* KERNEL.174: __A000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x10000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 181, /* KERNEL.181: __B000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x20000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 182, /* KERNEL.182: __B800H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x28000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 195, /* KERNEL.195: __C000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x30000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 179, /* KERNEL.179: __D000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x40000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 190, /* KERNEL.190: __E000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x50000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 173, /* KERNEL.173: __ROMBIOS */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x60000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
MODULE_SetEntryPoint( hModule, 194, /* KERNEL.194: __F000H */
|
||||
GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x60000,
|
||||
0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
|
||||
DOSMEM_FillBiosSegment();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSMEM_Alarm
|
||||
*
|
||||
* Increment the BIOS tick counter.
|
||||
*/
|
||||
static void DOSMEM_Alarm(void)
|
||||
{
|
||||
pBiosData->Ticks = INT1A_GetTicksSinceMidnight();
|
||||
printf( "Ticks = %d\n", pBiosData->Ticks );
|
||||
/*
|
||||
signal( SIGALRM, DOSMEM_Alarm );
|
||||
alarm( 1 );
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DOSMEM_FillBiosSegment
|
||||
*
|
||||
* Fill the BIOS data segment with dummy values.
|
||||
*/
|
||||
void DOSMEM_FillBiosSegment(void)
|
||||
{
|
||||
pBiosData = (BIOSDATA *)GlobalLock( DOSMEM_BiosSeg );
|
||||
|
||||
/* Clear all unused values */
|
||||
memset( pBiosData, 0, sizeof(*pBiosData) );
|
||||
|
||||
/* FIXME: should check the number of configured drives and ports */
|
||||
|
||||
pBiosData->Com1Addr = 0x3e8;
|
||||
pBiosData->Com2Addr = 0x2e8;
|
||||
pBiosData->Lpt1Addr = 0x378;
|
||||
pBiosData->Lpt2Addr = 0x278;
|
||||
pBiosData->InstalledHardware = 0x8443;
|
||||
pBiosData->MemSize = 640;
|
||||
pBiosData->NextKbdCharPtr = 0x1e;
|
||||
pBiosData->FirstKbdCharPtr = 0x1e;
|
||||
pBiosData->VideoMode = 0;
|
||||
pBiosData->VideoColumns = 80;
|
||||
pBiosData->VideoPageSize = 80 * 25 * 2;
|
||||
pBiosData->VideoPageStartAddr = 0xb800;
|
||||
pBiosData->VideoCtrlAddr = 0x3d4;
|
||||
pBiosData->Ticks = INT1A_GetTicksSinceMidnight();
|
||||
pBiosData->NbHardDisks = 2;
|
||||
pBiosData->KbdBufferStart = 0x1e;
|
||||
pBiosData->KbdBufferEnd = 0x3e;
|
||||
|
||||
/*
|
||||
signal( SIGALRM, DOSMEM_Alarm );
|
||||
alarm( 1 );
|
||||
*/
|
||||
}
|
|
@ -72,11 +72,12 @@ void WIN87_fpmath( struct sigcontext_struct context )
|
|||
/* IN: AX&0x0C00 rounding protocol */
|
||||
/* OUT: DX:AX variable popped */
|
||||
{
|
||||
DWORD dw,junk;
|
||||
DWORD dw;
|
||||
/* I don't know much about asm() programming. This could be
|
||||
* wrong.
|
||||
*/
|
||||
__asm__("fistp %1\nwait":"=m" (junk):"m" (dw):"memory");
|
||||
/* FIXME: could someone who really understands asm() fix this please? --AJ */
|
||||
/* __asm__("fistp %0;wait" : "=m" (dw) : : "memory"); */
|
||||
dprintf_int(stddeb,"emulate.c:On top of stack was %ld\n",dw);
|
||||
AX_reg(&context) = LOWORD(dw);
|
||||
DX_reg(&context) = HIWORD(dw);
|
||||
|
|
552
miscemu/instr.c
552
miscemu/instr.c
|
@ -11,6 +11,258 @@
|
|||
#include "registers.h"
|
||||
|
||||
|
||||
#define STACK_PTR(context) \
|
||||
(PTR_SEG_OFF_TO_LIN( SS_reg(context), \
|
||||
((GET_SEL_FLAGS(SS_reg(context)) & LDT_FLAGS_32BIT) ? \
|
||||
ESP_reg(context) : SP_reg(context))))
|
||||
|
||||
/***********************************************************************
|
||||
* INSTR_ReplaceSelector
|
||||
*
|
||||
* Try to replace an invalid selector by a valid one.
|
||||
* For now, only selector 0x40 is handled here.
|
||||
*/
|
||||
static WORD INSTR_ReplaceSelector( struct sigcontext_struct *context, WORD sel)
|
||||
{
|
||||
if (sel == 0x40)
|
||||
{
|
||||
fprintf( stderr, "Direct access to segment 0x40 (cs:ip=%04x:%04lx).\n",
|
||||
CS_reg(context), EIP_reg(context) );
|
||||
return DOSMEM_BiosSeg;
|
||||
}
|
||||
return 0; /* Can't replace selector */
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* INSTR_GetOperandAddr
|
||||
*
|
||||
* Return the address of an instruction operand (from the mod/rm byte).
|
||||
*/
|
||||
static BYTE *INSTR_GetOperandAddr( struct sigcontext_struct *context,
|
||||
BYTE *instr, int long_addr,
|
||||
int segprefix, int *len )
|
||||
{
|
||||
int mod, rm, base, index = 0, ss = 0, seg = 0, off;
|
||||
|
||||
#define GET_VAL(val,type) \
|
||||
{ *val = *(type *)instr; instr += sizeof(type); *len += sizeof(type); }
|
||||
|
||||
*len = 0;
|
||||
GET_VAL( &mod, BYTE );
|
||||
rm = mod & 7;
|
||||
mod >>= 6;
|
||||
|
||||
if (mod == 3)
|
||||
{
|
||||
switch(rm)
|
||||
{
|
||||
case 0: return (BYTE *)&EAX_reg(context);
|
||||
case 1: return (BYTE *)&ECX_reg(context);
|
||||
case 2: return (BYTE *)&EDX_reg(context);
|
||||
case 3: return (BYTE *)&EBX_reg(context);
|
||||
case 4: return (BYTE *)&ESP_reg(context);
|
||||
case 5: return (BYTE *)&EBP_reg(context);
|
||||
case 6: return (BYTE *)&ESI_reg(context);
|
||||
case 7: return (BYTE *)&EDI_reg(context);
|
||||
}
|
||||
}
|
||||
|
||||
if (long_addr)
|
||||
{
|
||||
if (rm == 4)
|
||||
{
|
||||
BYTE sib;
|
||||
GET_VAL( &sib, BYTE );
|
||||
rm = sib & 7;
|
||||
ss = sib >> 6;
|
||||
switch(sib >> 3)
|
||||
{
|
||||
case 0: index = EAX_reg(context); break;
|
||||
case 1: index = ECX_reg(context); break;
|
||||
case 2: index = EDX_reg(context); break;
|
||||
case 3: index = EBX_reg(context); break;
|
||||
case 4: index = 0; break;
|
||||
case 5: index = EBP_reg(context); break;
|
||||
case 6: index = ESI_reg(context); break;
|
||||
case 7: index = EDI_reg(context); break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(rm)
|
||||
{
|
||||
case 0: base = EAX_reg(context); seg = DS_reg(context); break;
|
||||
case 1: base = ECX_reg(context); seg = DS_reg(context); break;
|
||||
case 2: base = EDX_reg(context); seg = DS_reg(context); break;
|
||||
case 3: base = EBX_reg(context); seg = DS_reg(context); break;
|
||||
case 4: base = ESP_reg(context); seg = SS_reg(context); break;
|
||||
case 5: base = EBP_reg(context); seg = SS_reg(context); break;
|
||||
case 6: base = ESI_reg(context); seg = DS_reg(context); break;
|
||||
case 7: base = EDI_reg(context); seg = DS_reg(context); break;
|
||||
}
|
||||
switch (mod)
|
||||
{
|
||||
case 0:
|
||||
if (rm == 5) /* special case: ds:(disp32) */
|
||||
{
|
||||
GET_VAL( &base, DWORD );
|
||||
seg = DS_reg(context);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: /* 8-bit disp */
|
||||
GET_VAL( &off, BYTE );
|
||||
base += (signed char)off;
|
||||
break;
|
||||
|
||||
case 2: /* 32-bit disp */
|
||||
GET_VAL( &off, DWORD );
|
||||
base += (signed long)off;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /* short address */
|
||||
{
|
||||
switch(rm)
|
||||
{
|
||||
case 0: /* ds:(bx,si) */
|
||||
base = BX_reg(context) + SI_reg(context);
|
||||
seg = DS_reg(context);
|
||||
break;
|
||||
case 1: /* ds:(bx,di) */
|
||||
base = BX_reg(context) + DI_reg(context);
|
||||
seg = DS_reg(context);
|
||||
break;
|
||||
case 2: /* ss:(bp,si) */
|
||||
base = BP_reg(context) + SI_reg(context);
|
||||
seg = SS_reg(context);
|
||||
break;
|
||||
case 3: /* ss:(bp,di) */
|
||||
base = BP_reg(context) + DI_reg(context);
|
||||
seg = SS_reg(context);
|
||||
break;
|
||||
case 4: /* ds:(si) */
|
||||
base = SI_reg(context);
|
||||
seg = DS_reg(context);
|
||||
break;
|
||||
case 5: /* ds:(di) */
|
||||
base = DI_reg(context);
|
||||
seg = DS_reg(context);
|
||||
break;
|
||||
case 6: /* ss:(bp) */
|
||||
base = BP_reg(context);
|
||||
seg = SS_reg(context);
|
||||
break;
|
||||
case 7: /* ds:(bx) */
|
||||
base = BX_reg(context);
|
||||
seg = DS_reg(context);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(mod)
|
||||
{
|
||||
case 0:
|
||||
if (rm == 6) /* special case: ds:(disp16) */
|
||||
{
|
||||
GET_VAL( &base, WORD );
|
||||
seg = DS_reg(context);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: /* 8-bit disp */
|
||||
GET_VAL( &off, BYTE );
|
||||
base += (signed char)off;
|
||||
break;
|
||||
|
||||
case 2: /* 16-bit disp */
|
||||
GET_VAL( &off, WORD );
|
||||
base += (signed short)off;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (segprefix != -1) seg = segprefix;
|
||||
|
||||
return (BYTE *)PTR_SEG_OFF_TO_LIN( seg, (base + (index << ss)) );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* INSTR_EmulateLDS
|
||||
*
|
||||
* Emulate the LDS (and LES,LFS,etc.) instruction.
|
||||
*/
|
||||
static BOOL INSTR_EmulateLDS( struct sigcontext_struct *context,
|
||||
BYTE *instr, int long_op, int long_addr,
|
||||
int segprefix, int *len )
|
||||
{
|
||||
BYTE *regmodrm = instr + 1 + (*instr == 0x0f);
|
||||
BYTE *addr = INSTR_GetOperandAddr( context, regmodrm,
|
||||
long_addr, segprefix, len );
|
||||
WORD seg = *(WORD *)(addr + (long_op ? 4 : 2));
|
||||
|
||||
if (!(seg = INSTR_ReplaceSelector( context, seg )))
|
||||
return FALSE; /* Unable to emulate it */
|
||||
|
||||
/* Now store the offset in the correct register */
|
||||
|
||||
switch((*regmodrm >> 3) & 7)
|
||||
{
|
||||
case 0:
|
||||
if (long_op) EAX_reg(context) = *(DWORD *)addr;
|
||||
else AX_reg(context) = *(WORD *)addr;
|
||||
break;
|
||||
case 1:
|
||||
if (long_op) ECX_reg(context) = *(DWORD *)addr;
|
||||
else CX_reg(context) = *(WORD *)addr;
|
||||
break;
|
||||
case 2:
|
||||
if (long_op) EDX_reg(context) = *(DWORD *)addr;
|
||||
else DX_reg(context) = *(WORD *)addr;
|
||||
break;
|
||||
case 3:
|
||||
if (long_op) EBX_reg(context) = *(DWORD *)addr;
|
||||
else BX_reg(context) = *(WORD *)addr;
|
||||
break;
|
||||
case 4:
|
||||
if (long_op) ESP_reg(context) = *(DWORD *)addr;
|
||||
else SP_reg(context) = *(WORD *)addr;
|
||||
break;
|
||||
case 5:
|
||||
if (long_op) EBP_reg(context) = *(DWORD *)addr;
|
||||
else BP_reg(context) = *(WORD *)addr;
|
||||
break;
|
||||
case 6:
|
||||
if (long_op) ESI_reg(context) = *(DWORD *)addr;
|
||||
else SI_reg(context) = *(WORD *)addr;
|
||||
break;
|
||||
case 7:
|
||||
if (long_op) EDI_reg(context) = *(DWORD *)addr;
|
||||
else DI_reg(context) = *(WORD *)addr;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Store the correct segment in the segment register */
|
||||
|
||||
switch(*instr)
|
||||
{
|
||||
case 0xc4: ES_reg(context) = seg; break; /* les */
|
||||
case 0xc5: DS_reg(context) = seg; break; /* lds */
|
||||
case 0x0f: switch(instr[1])
|
||||
{
|
||||
case 0xb2: SS_reg(context) = seg; break; /* lss */
|
||||
case 0xb4: FS_reg(context) = seg; break; /* lfs */
|
||||
case 0xb5: GS_reg(context) = seg; break; /* lgs */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Add the opcode size to the total length */
|
||||
|
||||
*len += 1 + (*instr == 0x0f);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* INSTR_EmulateInstruction
|
||||
*
|
||||
|
@ -18,7 +270,7 @@
|
|||
*/
|
||||
BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context )
|
||||
{
|
||||
int prefix, segprefix, repX, long_op, long_addr;
|
||||
int prefix, segprefix, prefixlen, len, repX, long_op, long_addr;
|
||||
BYTE *instr;
|
||||
|
||||
long_op = long_addr = (GET_SEL_FLAGS(CS_reg(context)) & LDT_FLAGS_32BIT) != 0;
|
||||
|
@ -29,6 +281,7 @@ BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context )
|
|||
segprefix = -1; /* no prefix */
|
||||
prefix = 1;
|
||||
repX = 0;
|
||||
prefixlen = 0;
|
||||
while(prefix)
|
||||
{
|
||||
switch(*instr)
|
||||
|
@ -72,7 +325,7 @@ BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context )
|
|||
if (prefix)
|
||||
{
|
||||
instr++;
|
||||
EIP_reg(context)++;
|
||||
prefixlen++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,103 +333,59 @@ BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context )
|
|||
|
||||
switch(*instr)
|
||||
{
|
||||
case 0xcd: /* int <XX> */
|
||||
if (long_op)
|
||||
case 0x07: /* pop es */
|
||||
case 0x17: /* pop ss */
|
||||
case 0x1f: /* pop ds */
|
||||
{
|
||||
fprintf(stderr, "int xx from 32-bit code is not supported.\n");
|
||||
return FALSE; /* Unable to emulate it */
|
||||
WORD seg = *(WORD *)STACK_PTR( context );
|
||||
if ((seg = INSTR_ReplaceSelector( context, seg )) != 0)
|
||||
{
|
||||
switch(*instr)
|
||||
{
|
||||
case 0x07: ES_reg(context) = seg; break;
|
||||
case 0x17: SS_reg(context) = seg; break;
|
||||
case 0x1f: DS_reg(context) = seg; break;
|
||||
}
|
||||
SP_reg(context) += sizeof(WORD);
|
||||
EIP_reg(context) += prefixlen + 1;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
break; /* Unable to emulate it */
|
||||
|
||||
case 0x0f: /* extended instruction */
|
||||
switch(instr[1])
|
||||
{
|
||||
SEGPTR addr = INT_GetHandler( instr[1] );
|
||||
/* FIXME: should check the stack 'big' bit */
|
||||
WORD *stack = (WORD *)PTR_SEG_OFF_TO_LIN( SS_reg(context),
|
||||
SP_reg(context) );
|
||||
/* Push the flags and return address on the stack */
|
||||
*(--stack) = FL_reg(context);
|
||||
*(--stack) = CS_reg(context);
|
||||
*(--stack) = IP_reg(context) + 2;
|
||||
SP_reg(context) -= 3 * sizeof(WORD);
|
||||
/* Jump to the interrupt handler */
|
||||
CS_reg(context) = HIWORD(addr);
|
||||
EIP_reg(context) = LOWORD(addr);
|
||||
case 0xa1: /* pop fs */
|
||||
case 0xa9: /* pop gs */
|
||||
{
|
||||
WORD seg = *(WORD *)STACK_PTR( context );
|
||||
if ((seg = INSTR_ReplaceSelector( context, seg )) != 0)
|
||||
{
|
||||
switch(instr[1])
|
||||
{
|
||||
case 0xa1: FS_reg(context) = seg; break;
|
||||
case 0xa9: GS_reg(context) = seg; break;
|
||||
}
|
||||
SP_reg(context) += sizeof(WORD);
|
||||
EIP_reg(context) += prefixlen + 2;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb2: /* lss addr,reg */
|
||||
case 0xb4: /* lfs addr,reg */
|
||||
case 0xb5: /* lgs addr,reg */
|
||||
if (INSTR_EmulateLDS( context, instr, long_op,
|
||||
long_addr, segprefix, &len ))
|
||||
{
|
||||
EIP_reg(context) += prefixlen + len;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xcf: /* iret */
|
||||
if (long_op)
|
||||
{
|
||||
/* FIXME: should check the stack 'big' bit */
|
||||
DWORD *stack = (DWORD *)PTR_SEG_OFF_TO_LIN( SS_reg(context),
|
||||
SP_reg(context) );
|
||||
EIP_reg(context) = *stack++;
|
||||
CS_reg(context) = *stack++;
|
||||
EFL_reg(context) = *stack;
|
||||
SP_reg(context) += 3*sizeof(DWORD); /* Pop the return address and flags */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: should check the stack 'big' bit */
|
||||
WORD *stack = (WORD *)PTR_SEG_OFF_TO_LIN( SS_reg(context),
|
||||
SP_reg(context) );
|
||||
EIP_reg(context) = *stack++;
|
||||
CS_reg(context) = *stack++;
|
||||
FL_reg(context) = *stack;
|
||||
SP_reg(context) += 3*sizeof(WORD); /* Pop the return address and flags */
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xe4: /* inb al,XX */
|
||||
AL_reg(context) = inport( instr[1], 1 );
|
||||
EIP_reg(context) += 2;
|
||||
break;
|
||||
|
||||
case 0xe5: /* in (e)ax,XX */
|
||||
if (long_op) EAX_reg(context) = inport( instr[1], 4 );
|
||||
else AX_reg(context) = inport( instr[1], 2 );
|
||||
EIP_reg(context) += 2;
|
||||
break;
|
||||
|
||||
case 0xe6: /* outb XX,al */
|
||||
outport( instr[1], 1, AL_reg(context) );
|
||||
EIP_reg(context) += 2;
|
||||
break;
|
||||
|
||||
case 0xe7: /* out XX,(e)ax */
|
||||
if (long_op) outport( instr[1], 4, EAX_reg(context) );
|
||||
else outport( instr[1], 2, AX_reg(context) );
|
||||
EIP_reg(context) += 2;
|
||||
break;
|
||||
|
||||
case 0xec: /* inb al,dx */
|
||||
AL_reg(context) = inport( DX_reg(context), 1 );
|
||||
EIP_reg(context)++;
|
||||
break;
|
||||
|
||||
case 0xed: /* in (e)ax,dx */
|
||||
if (long_op) EAX_reg(context) = inport( DX_reg(context), 4 );
|
||||
else AX_reg(context) = inport( DX_reg(context), 2 );
|
||||
EIP_reg(context)++;
|
||||
break;
|
||||
|
||||
case 0xee: /* outb dx,al */
|
||||
outport( DX_reg(context), 1, AL_reg(context) );
|
||||
EIP_reg(context)++;
|
||||
break;
|
||||
|
||||
case 0xef: /* out dx,(e)ax */
|
||||
if (long_op) outport( DX_reg(context), 4, EAX_reg(context) );
|
||||
else outport( DX_reg(context), 2, AX_reg(context) );
|
||||
EIP_reg(context)++;
|
||||
break;
|
||||
|
||||
case 0xfa: /* cli, ignored */
|
||||
EIP_reg(context)++;
|
||||
break;
|
||||
|
||||
case 0xfb: /* sti, ignored */
|
||||
EIP_reg(context)++;
|
||||
break;
|
||||
break; /* Unable to emulate it */
|
||||
|
||||
case 0x6c: /* insb */
|
||||
case 0x6d: /* insw/d */
|
||||
|
@ -190,7 +399,7 @@ BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context )
|
|||
int opsize = (typ & 1) ? (long_op ? 4 : 2) : 1;
|
||||
int step = (EFL_reg(context) & 0x400) ? -opsize : +opsize;
|
||||
int seg = outp ? (segprefix >= 0 ? segprefix : DS_reg(context))
|
||||
: ES_reg(context);
|
||||
: ES_reg(context); /* FIXME: is this right? */
|
||||
|
||||
if (outp)
|
||||
/* FIXME: Check segment readable. */
|
||||
|
@ -245,14 +454,151 @@ BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context )
|
|||
break;
|
||||
}
|
||||
}
|
||||
EIP_reg(context)++;
|
||||
break;
|
||||
EIP_reg(context) += prefixlen + 1;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unexpected Windows program segfault"
|
||||
" - opcode = %x\n", *instr);
|
||||
return FALSE; /* Unable to emulate it */
|
||||
case 0x8e: /* mov reg,segment_reg */
|
||||
{
|
||||
WORD seg = *(WORD *)INSTR_GetOperandAddr( context, instr + 1,
|
||||
long_addr, segprefix, &len );
|
||||
if (!(seg = INSTR_ReplaceSelector( context, seg )))
|
||||
break; /* Unable to emulate it */
|
||||
|
||||
switch((instr[1] >> 3) & 7)
|
||||
{
|
||||
case 0:
|
||||
ES_reg(context) = seg;
|
||||
EIP_reg(context) += prefixlen + len + 1;
|
||||
return TRUE;
|
||||
case 1: /* cs */
|
||||
break;
|
||||
case 2:
|
||||
SS_reg(context) = seg;
|
||||
EIP_reg(context) += prefixlen + len + 1;
|
||||
return TRUE;
|
||||
case 3:
|
||||
DS_reg(context) = seg;
|
||||
EIP_reg(context) += prefixlen + len + 1;
|
||||
return TRUE;
|
||||
case 4:
|
||||
FS_reg(context) = seg;
|
||||
EIP_reg(context) += prefixlen + len + 1;
|
||||
return TRUE;
|
||||
case 5:
|
||||
GS_reg(context) = seg;
|
||||
EIP_reg(context) += prefixlen + len + 1;
|
||||
return TRUE;
|
||||
case 6: /* unused */
|
||||
case 7: /* unused */
|
||||
break;
|
||||
}
|
||||
}
|
||||
break; /* Unable to emulate it */
|
||||
|
||||
case 0xc4: /* les addr,reg */
|
||||
case 0xc5: /* lds addr,reg */
|
||||
if (INSTR_EmulateLDS( context, instr, long_op,
|
||||
long_addr, segprefix, &len ))
|
||||
{
|
||||
EIP_reg(context) += prefixlen + len;
|
||||
return TRUE;
|
||||
}
|
||||
break; /* Unable to emulate it */
|
||||
|
||||
case 0xcd: /* int <XX> */
|
||||
if (long_op)
|
||||
{
|
||||
fprintf(stderr, "int xx from 32-bit code is not supported.\n");
|
||||
break; /* Unable to emulate it */
|
||||
}
|
||||
else
|
||||
{
|
||||
SEGPTR addr = INT_GetHandler( instr[1] );
|
||||
WORD *stack = (WORD *)STACK_PTR( context );
|
||||
/* Push the flags and return address on the stack */
|
||||
*(--stack) = FL_reg(context);
|
||||
*(--stack) = CS_reg(context);
|
||||
*(--stack) = IP_reg(context) + prefixlen + 2;
|
||||
SP_reg(context) -= 3 * sizeof(WORD);
|
||||
/* Jump to the interrupt handler */
|
||||
CS_reg(context) = HIWORD(addr);
|
||||
EIP_reg(context) = LOWORD(addr);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case 0xcf: /* iret */
|
||||
if (long_op)
|
||||
{
|
||||
DWORD *stack = (DWORD *)STACK_PTR( context );
|
||||
EIP_reg(context) = *stack++;
|
||||
CS_reg(context) = *stack++;
|
||||
EFL_reg(context) = *stack;
|
||||
SP_reg(context) += 3*sizeof(DWORD); /* Pop the return address and flags */
|
||||
}
|
||||
else
|
||||
{
|
||||
WORD *stack = (WORD *)STACK_PTR( context );
|
||||
EIP_reg(context) = *stack++;
|
||||
CS_reg(context) = *stack++;
|
||||
FL_reg(context) = *stack;
|
||||
SP_reg(context) += 3*sizeof(WORD); /* Pop the return address and flags */
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case 0xe4: /* inb al,XX */
|
||||
AL_reg(context) = inport( instr[1], 1 );
|
||||
EIP_reg(context) += prefixlen + 2;
|
||||
return TRUE;
|
||||
|
||||
case 0xe5: /* in (e)ax,XX */
|
||||
if (long_op) EAX_reg(context) = inport( instr[1], 4 );
|
||||
else AX_reg(context) = inport( instr[1], 2 );
|
||||
EIP_reg(context) += prefixlen + 2;
|
||||
return TRUE;
|
||||
|
||||
case 0xe6: /* outb XX,al */
|
||||
outport( instr[1], 1, AL_reg(context) );
|
||||
EIP_reg(context) += prefixlen + 2;
|
||||
return TRUE;
|
||||
|
||||
case 0xe7: /* out XX,(e)ax */
|
||||
if (long_op) outport( instr[1], 4, EAX_reg(context) );
|
||||
else outport( instr[1], 2, AX_reg(context) );
|
||||
EIP_reg(context) += prefixlen + 2;
|
||||
return TRUE;
|
||||
|
||||
case 0xec: /* inb al,dx */
|
||||
AL_reg(context) = inport( DX_reg(context), 1 );
|
||||
EIP_reg(context) += prefixlen + 1;
|
||||
return TRUE;
|
||||
|
||||
case 0xed: /* in (e)ax,dx */
|
||||
if (long_op) EAX_reg(context) = inport( DX_reg(context), 4 );
|
||||
else AX_reg(context) = inport( DX_reg(context), 2 );
|
||||
EIP_reg(context) += prefixlen + 1;
|
||||
return TRUE;
|
||||
|
||||
case 0xee: /* outb dx,al */
|
||||
outport( DX_reg(context), 1, AL_reg(context) );
|
||||
EIP_reg(context) += prefixlen + 1;
|
||||
return TRUE;
|
||||
|
||||
case 0xef: /* out dx,(e)ax */
|
||||
if (long_op) outport( DX_reg(context), 4, EAX_reg(context) );
|
||||
else outport( DX_reg(context), 2, AX_reg(context) );
|
||||
EIP_reg(context) += prefixlen + 1;
|
||||
return TRUE;
|
||||
|
||||
case 0xfa: /* cli, ignored */
|
||||
EIP_reg(context) += prefixlen + 1;
|
||||
return TRUE;
|
||||
|
||||
case 0xfb: /* sti, ignored */
|
||||
EIP_reg(context) += prefixlen + 1;
|
||||
return TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
fprintf(stderr, "Unexpected Windows program segfault"
|
||||
" - opcode = %x\n", *instr);
|
||||
return FALSE; /* Unable to emulate it */
|
||||
}
|
||||
|
|
|
@ -14,6 +14,27 @@
|
|||
#define BIN_TO_BCD(x) ((x%10) + ((x/10)<<4))
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* INT1A_GetTicksSinceMidnight
|
||||
*
|
||||
* Return number of clock ticks since midnight.
|
||||
*/
|
||||
DWORD INT1A_GetTicksSinceMidnight(void)
|
||||
{
|
||||
struct tm *bdtime;
|
||||
struct timeval tvs;
|
||||
|
||||
/* This should give us the (approximately) correct
|
||||
* 18.206 clock ticks per second since midnight.
|
||||
*/
|
||||
gettimeofday( &tvs, NULL );
|
||||
bdtime = localtime( &tvs.tv_sec );
|
||||
return (((bdtime->tm_hour * 3600 + bdtime->tm_min * 60 +
|
||||
bdtime->tm_sec) * 18206) / 1000) +
|
||||
(tvs.tv_usec / 54927);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* INT_Int1aHandler
|
||||
*
|
||||
|
@ -24,25 +45,16 @@ void INT_Int1aHandler( struct sigcontext_struct context )
|
|||
time_t ltime;
|
||||
DWORD ticks;
|
||||
struct tm *bdtime;
|
||||
struct timeval tvs;
|
||||
|
||||
switch(AH_reg(&context))
|
||||
{
|
||||
case 0:
|
||||
/* This should give us the (approximately) correct
|
||||
* 18.206 clock ticks per second since midnight
|
||||
* expected from this interrupt
|
||||
*/
|
||||
gettimeofday(&tvs, NULL);
|
||||
bdtime = localtime(&tvs.tv_sec);
|
||||
ticks = (((bdtime->tm_hour * 3600 + bdtime->tm_min * 60 +
|
||||
bdtime->tm_sec) * 18206) / 1000) +
|
||||
(tvs.tv_usec / 54927);
|
||||
CX_reg(&context) = HIWORD(ticks);
|
||||
DX_reg(&context) = LOWORD(ticks);
|
||||
AX_reg(&context) = 0; /* No midnight rollover */
|
||||
dprintf_int(stddeb,"int1a_00 // ticks=%ld\n", ticks);
|
||||
break;
|
||||
ticks = INT1A_GetTicksSinceMidnight();
|
||||
CX_reg(&context) = HIWORD(ticks);
|
||||
DX_reg(&context) = LOWORD(ticks);
|
||||
AX_reg(&context) = 0; /* No midnight rollover */
|
||||
dprintf_int(stddeb,"int1a_00 // ticks=%ld\n", ticks);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ltime = time(NULL);
|
||||
|
|
|
@ -341,14 +341,9 @@ static void WriteFile(struct sigcontext_struct *context)
|
|||
AX_reg(context) = CX_reg(context);
|
||||
RESET_CFLAG(context);
|
||||
} else {
|
||||
size = write(BX_reg(context), ptr , CX_reg(context));
|
||||
if (size == 0) {
|
||||
Error (WriteFault, EC_Unknown, EL_Unknown);
|
||||
AX_reg(context) = ExtendedError;
|
||||
return;
|
||||
}
|
||||
|
||||
if (size == -1) {
|
||||
/* well, this function already handles everything we need */
|
||||
size = _lwrite(BX_reg(context),ptr,CX_reg(context));
|
||||
if (size == -1) { /* HFILE_ERROR == -1 */
|
||||
errno_to_doserr();
|
||||
AX_reg(context) = ExtendedError;
|
||||
SET_CFLAG(context);
|
||||
|
@ -417,8 +412,12 @@ static void ioctlGetDeviceInfo(struct sigcontext_struct *context)
|
|||
return;
|
||||
}
|
||||
|
||||
/* This isn't the right answer, but should be close enough. */
|
||||
DX_reg(context) = 0x0943;
|
||||
/* 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
|
||||
* bit 11 - media not removable
|
||||
*/
|
||||
}
|
||||
}
|
||||
RESET_CFLAG(context);
|
||||
|
@ -1526,7 +1525,13 @@ void DOS3Call( struct sigcontext_struct context )
|
|||
RESET_CFLAG(&context);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0a: /* check if handle (BX) is remote */
|
||||
/* returns DX, bit 15 set if remote, bit 14 set if date/time
|
||||
* not set on close
|
||||
*/
|
||||
DX_reg(&context) = 0;
|
||||
RESET_CFLAG(&context);
|
||||
break;
|
||||
case 0x0b: /* SET SHARING RETRY COUNT */
|
||||
if (!CX_reg(&context))
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@ SRCS = \
|
|||
joystick.c \
|
||||
mcianim.c \
|
||||
mcicda.c \
|
||||
mcistring.c \
|
||||
midi.c \
|
||||
mmaux.c \
|
||||
mmsystem.c \
|
||||
|
|
|
@ -9,9 +9,16 @@ LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
|
|||
|
||||
MODULE = multimedia
|
||||
|
||||
SRCS = audio.c joystick.c mcianim.c mcicda.c midi.c mmaux.c \
|
||||
mmsystem.c time.c
|
||||
|
||||
SRCS = \
|
||||
audio.c \
|
||||
joystick.c \
|
||||
mcianim.c \
|
||||
mcicda.c \
|
||||
mcistring.c \
|
||||
midi.c \
|
||||
mmaux.c \
|
||||
mmsystem.c \
|
||||
time.c
|
||||
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
||||
|
@ -29,7 +36,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#define SOUND_DEV "/dev/dsp"
|
||||
|
||||
#ifdef SOUND_VERSION
|
||||
#define IOCTL(a,b,c) ioctl(a,b,&c)
|
||||
#define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
|
||||
#else
|
||||
#define IOCTL(a,b,c) (c = ioctl(a,b,c) )
|
||||
#endif
|
||||
|
@ -863,10 +863,11 @@ static DWORD wodClose(WORD wDevID)
|
|||
close(WOutDev[wDevID].unixdev);
|
||||
WOutDev[wDevID].unixdev = 0;
|
||||
WOutDev[wDevID].bufsize = 0;
|
||||
WOutDev[wDevID].lpQueueHdr = NULL;
|
||||
if (WAVE_NotifyClient(wDevID, WOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
|
||||
dprintf_mciwave(stddeb,"Linux 'wodClose' // can't notify client !\n");
|
||||
return MMSYSERR_INVALPARAM;
|
||||
}
|
||||
}
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
|
@ -920,10 +921,13 @@ static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
|
|||
dprintf_mciwave(stddeb,"Linux 'wodPrepare' // can't prepare !\n");
|
||||
return MMSYSERR_NOTENABLED;
|
||||
}
|
||||
/* the COOL waveeditor feels much better without this check...
|
||||
* someone please have a look at available documentation
|
||||
if (WOutDev[wDevID].lpQueueHdr != NULL) {
|
||||
dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
|
||||
return MMSYSERR_NOTENABLED;
|
||||
}
|
||||
}
|
||||
*/
|
||||
WOutDev[wDevID].dwTotalPlayed = 0;
|
||||
WOutDev[wDevID].lpQueueHdr = lpWaveHdr;
|
||||
if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
|
||||
|
|
2177
multimedia/mcistring.c
Normal file
2177
multimedia/mcistring.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -28,11 +28,7 @@ static int InstalledCount;
|
|||
static int InstalledListLen;
|
||||
static LPSTR lpInstallNames = NULL;
|
||||
|
||||
static MCI_OPEN_DRIVER_PARMS mciDrv[MAXMCIDRIVERS];
|
||||
/* FIXME: I need to remember the aliasname of a spec. driver.
|
||||
* and this is the easiest way. *sigh*
|
||||
*/
|
||||
static MCI_OPEN_PARMS mciOpenDrv[MAXMCIDRIVERS];
|
||||
MCI_OPEN_DRIVER_PARMS mciDrv[MAXMCIDRIVERS];
|
||||
|
||||
UINT midiGetErrorText(UINT uError, LPSTR lpText, UINT uSize);
|
||||
UINT waveGetErrorText(UINT uError, LPSTR lpText, UINT uSize);
|
||||
|
@ -798,777 +794,6 @@ UINT mciGetDeviceID (LPCSTR lpstrName)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* someone was just short of a crisis seeing me putting xxx lines of code
|
||||
* in a single define. Well. What does the code hope for if not for the
|
||||
* care of the optimizer? (Stolen by Terry Pratchett, ok ;)
|
||||
*/
|
||||
#define _MCI_STR(s) do {\
|
||||
int __l__;\
|
||||
dprintf_mci(stddeb,"->returns \"%s\"",s);\
|
||||
if (lpstrReturnString) {\
|
||||
__l__=strlen(s);\
|
||||
if(__l__>uReturnLength) {\
|
||||
strncpy(lpstrReturnString,s,uReturnLength-1);\
|
||||
lpstrReturnString[uReturnLength-1]='\0';\
|
||||
} else\
|
||||
strcpy(lpstrReturnString,s);\
|
||||
dprintf_mci(stddeb,"-->\"%s\"\n",lpstrReturnString);\
|
||||
}\
|
||||
} while(0)
|
||||
/* calling DriverProc. We need to pass the struct as SEGMENTED POINTER. */
|
||||
#define _MCI_CALL_DRIVER(cmd,params) {\
|
||||
DWORD xparams;\
|
||||
xparams=MAKE_SEGPTR(¶ms);\
|
||||
switch(uDevTyp) {\
|
||||
case MCI_DEVTYPE_CD_AUDIO:\
|
||||
res=CDAUDIO_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags, xparams);\
|
||||
break;\
|
||||
case MCI_DEVTYPE_WAVEFORM_AUDIO:\
|
||||
res=WAVE_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags,xparams);\
|
||||
break;\
|
||||
case MCI_DEVTYPE_SEQUENCER:\
|
||||
res=MIDI_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags,xparams);\
|
||||
break;\
|
||||
case MCI_DEVTYPE_ANIMATION:\
|
||||
res=ANIM_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags,xparams);\
|
||||
break;\
|
||||
case MCI_DEVTYPE_DIGITAL_VIDEO:\
|
||||
dprintf_mci(stddeb,"_MCI_CALL_DRIVER //No DIGITAL_VIDEO yet !\n");\
|
||||
res=MCIERR_DEVICE_NOT_INSTALLED;\
|
||||
break;\
|
||||
default:\
|
||||
dprintf_mci(stddeb,"_MCI_CALL_DRIVER //Invalid Device Name '%s' !\n",dev);\
|
||||
res=MCIERR_INVALID_DEVICE_NAME;\
|
||||
break;\
|
||||
}\
|
||||
}
|
||||
/* yeah, I know this is BAD. but we have to do that for MCI_OPEN_PARMS
|
||||
* strings.
|
||||
*/
|
||||
#define _MCI_STRDUP_TO_SEG(dest,source) {\
|
||||
HANDLE x;\
|
||||
x=USER_HEAP_ALLOC(strlen(source));\
|
||||
dest=(LPSTR)MAKELONG(x,USER_HeapSel);\
|
||||
strcpy(PTR_SEG_TO_LIN(dest),source);\
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* mciSendString [MMSYSTEM.702]
|
||||
*/
|
||||
/* Well, it's easy. The usercode sends a string with a command (and flags)
|
||||
* expressed in words in it... We do our best to call approbiate drivers,
|
||||
* and return a errorcode AND a readable string (if lpstrRS!=NULL)
|
||||
* Info taken by watching cool134.exe and from Borland's mcistrwh.hlp
|
||||
*/
|
||||
DWORD mciSendString (LPCSTR lpstrCommand, LPSTR lpstrReturnString,
|
||||
UINT uReturnLength, HWND hwndCallback)
|
||||
{
|
||||
char *cmd,*dev,*args,**keywords;
|
||||
WORD uDevTyp,wDevID;
|
||||
DWORD dwFlags;
|
||||
int track,i,nrofkeywords,res,timef;
|
||||
|
||||
dprintf_mci(stdnimp,"mciSendString('%s', %p, %d, %X)\n", lpstrCommand,
|
||||
lpstrReturnString, uReturnLength, hwndCallback
|
||||
);
|
||||
/* format is <command> <device> <optargs> */
|
||||
cmd=strdup(lpstrCommand);
|
||||
dev=strchr(cmd,' ');
|
||||
if (dev==NULL) {
|
||||
free(cmd);
|
||||
return MCIERR_MISSING_DEVICE_NAME;
|
||||
}
|
||||
*dev++='\0';
|
||||
args=strchr(dev,' ');
|
||||
if (args!=NULL) *args++='\0';
|
||||
AnsiUpper(dev);
|
||||
AnsiUpper(cmd);
|
||||
if (args!=NULL) {
|
||||
char *s;
|
||||
AnsiUpper(args);
|
||||
i=1;/* nrofkeywords = nrofspaces+1 */
|
||||
s=args;
|
||||
while ((s=strchr(s,' '))!=NULL) i++,s++;
|
||||
keywords=(char**)malloc(sizeof(char*)*(i+2));
|
||||
nrofkeywords=i;
|
||||
s=args;i=0;
|
||||
while (s && i<nrofkeywords) {
|
||||
keywords[i++]=s;
|
||||
s=strchr(s,' ');
|
||||
if (s) *s++='\0';
|
||||
}
|
||||
keywords[i]=NULL;
|
||||
} else {
|
||||
nrofkeywords=0;
|
||||
keywords=(char**)malloc(sizeof(char*));
|
||||
}
|
||||
dwFlags = 0; /* default flags */
|
||||
i=0;
|
||||
while (i<nrofkeywords) {
|
||||
if (!strcmp(keywords[i],"WAIT")) {
|
||||
dwFlags |= MCI_WAIT;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(keywords[i],"NOTIFY")) {
|
||||
/* how should we callback? I don't know. */
|
||||
/*dwFlags |= MCI_NOTIFY;*/
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(keywords[i],"TRACK")) {
|
||||
if (i+1<nrofkeywords) {
|
||||
sscanf(keywords[i+1],"%d",&track);
|
||||
dwFlags |= MCI_TRACK;
|
||||
i++;
|
||||
/*FALLTHROUGH*/
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!strcmp(cmd,"OPEN")) {
|
||||
char *s;
|
||||
MCI_OPEN_PARMS openParams;
|
||||
|
||||
openParams.lpstrElementName = NULL;
|
||||
s=strchr(dev,'!');
|
||||
if (s!=NULL) {
|
||||
*s++='\0';
|
||||
_MCI_STRDUP_TO_SEG(openParams.lpstrElementName,s);
|
||||
}
|
||||
if (!strcmp(dev,"CDAUDIO")) {
|
||||
uDevTyp=MCI_DEVTYPE_CD_AUDIO;
|
||||
} else if (!strcmp(dev,"WAVEAUDIO")) {
|
||||
uDevTyp=MCI_DEVTYPE_WAVEFORM_AUDIO;
|
||||
} else if (!strcmp(dev,"SEQUENCER")) {
|
||||
uDevTyp=MCI_DEVTYPE_SEQUENCER;
|
||||
} else if (!strcmp(dev,"ANIMATION1")) {
|
||||
uDevTyp=MCI_DEVTYPE_ANIMATION;
|
||||
} else if (!strcmp(dev,"AVIVIDEO")) {
|
||||
uDevTyp=MCI_DEVTYPE_DIGITAL_VIDEO;
|
||||
} else {
|
||||
free(keywords);free(cmd);
|
||||
return MCIERR_INVALID_DEVICE_NAME;
|
||||
}
|
||||
wDevID=0;
|
||||
while(mciDrv[wDevID].wType) {
|
||||
if (++wDevID>=MAXMCIDRIVERS) {
|
||||
dprintf_mci(stddeb, "MCI_OPEN // MAXMCIDRIVERS reached !\n");
|
||||
free(keywords);free(cmd);
|
||||
return MCIERR_INTERNAL;
|
||||
}
|
||||
}
|
||||
mciDrv[wDevID].wType = uDevTyp;
|
||||
mciDrv[wDevID].wDeviceID = wDevID;
|
||||
openParams.dwCallback = 0;
|
||||
openParams.wDeviceID = wDevID;
|
||||
/* all strings must be copied */
|
||||
_MCI_STRDUP_TO_SEG(openParams.lpstrDeviceType,dev);
|
||||
openParams.lpstrAlias = NULL;
|
||||
dwFlags |= MCI_OPEN_TYPE;
|
||||
i=0;
|
||||
while (i<nrofkeywords) {
|
||||
if (!strcmp(keywords[i],"SHAREABLE")) {
|
||||
dwFlags|=MCI_OPEN_SHAREABLE;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(keywords[i],"ALIAS") && (i+1<nrofkeywords)) {
|
||||
dwFlags|=MCI_OPEN_ALIAS;
|
||||
_MCI_STRDUP_TO_SEG(openParams.lpstrAlias,keywords[i]);
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(keywords[i],"ELEMENT") && (i+1<nrofkeywords)) {
|
||||
dwFlags|=MCI_OPEN_ELEMENT;
|
||||
_MCI_STRDUP_TO_SEG(openParams.lpstrElementName,keywords[i]);
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
_MCI_CALL_DRIVER(MCI_OPEN,openParams);
|
||||
if (res==0)
|
||||
memcpy(&mciOpenDrv[wDevID],&openParams,sizeof(MCI_OPEN_PARMS));
|
||||
free(keywords);free(cmd);
|
||||
return res;
|
||||
}
|
||||
/* all other commands use the alias set in MCI_OPEN or (if not set)
|
||||
* the devicetype
|
||||
*/
|
||||
wDevID=0;
|
||||
while(1) {
|
||||
SEGPTR dname;
|
||||
dname=(SEGPTR)mciOpenDrv[wDevID].lpstrAlias;
|
||||
if (dname==NULL)
|
||||
dname=(SEGPTR)mciOpenDrv[wDevID].lpstrDeviceType;
|
||||
if (!strcasecmp(PTR_SEG_TO_LIN(dname),dev))
|
||||
break;
|
||||
if (++wDevID >= MAXMCIDRIVERS) {
|
||||
dprintf_mci(stddeb, "mciSendString // MAXMCIDRIVERS reached !\n");
|
||||
free(keywords);free(cmd);
|
||||
return MCIERR_INTERNAL;
|
||||
}
|
||||
}
|
||||
uDevTyp=mciDrv[wDevID].wType;
|
||||
|
||||
if (!strcmp(cmd,"STATUS")) {
|
||||
MCI_STATUS_PARMS statusParams;
|
||||
|
||||
if (args==NULL) {
|
||||
free(keywords);free(cmd);
|
||||
return MCIERR_MISSING_STRING_ARGUMENT;
|
||||
}
|
||||
statusParams.dwCallback = 0;
|
||||
if (dwFlags & MCI_TRACK)
|
||||
statusParams.dwTrack = track;
|
||||
dwFlags |= MCI_STATUS_ITEM;
|
||||
/* we need that later for printing... */
|
||||
statusParams.dwItem = MCI_STATUS_TIME_FORMAT;
|
||||
_MCI_CALL_DRIVER(MCI_STATUS,statusParams);
|
||||
timef=statusParams.dwReturn;
|
||||
statusParams.dwReturn=0;
|
||||
statusParams.dwItem=0;
|
||||
i=0;
|
||||
while (i<nrofkeywords) {
|
||||
if ( !strcmp(keywords[i],"CURRENT") &&
|
||||
(i+1<nrofkeywords) &&
|
||||
!strcmp(keywords[i+1],"TRACK")
|
||||
) {
|
||||
statusParams.dwItem=MCI_STATUS_CURRENT_TRACK;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(keywords[i],"TIME") &&
|
||||
(i+1<nrofkeywords) &&
|
||||
!strcmp(keywords[i+1],"FORMAT")
|
||||
) {
|
||||
statusParams.dwItem=MCI_STATUS_TIME_FORMAT;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(keywords[i],"READY")) {
|
||||
statusParams.dwItem=MCI_STATUS_READY;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(keywords[i],"MODE")) {
|
||||
statusParams.dwItem=MCI_STATUS_MODE;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(keywords[i],"NUMBER") &&
|
||||
(i+2<nrofkeywords) &&
|
||||
!strcmp(keywords[i+1],"OF") &&
|
||||
!strcmp(keywords[i+2],"TRACKS")
|
||||
) {
|
||||
statusParams.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
|
||||
i+=3;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(keywords[i],"LENGTH")) {
|
||||
statusParams.dwItem = MCI_STATUS_LENGTH;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(keywords[i],"POSITION")) {
|
||||
statusParams.dwItem = MCI_STATUS_POSITION;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(keywords[i],"MEDIA") &&
|
||||
(i+1<nrofkeywords) &&
|
||||
!strcmp(keywords[i+1],"PRESENT")
|
||||
) {
|
||||
statusParams.dwItem = MCI_STATUS_MEDIA_PRESENT;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
_MCI_CALL_DRIVER(MCI_STATUS,statusParams);
|
||||
if (res==0) {
|
||||
switch (statusParams.dwItem) {
|
||||
case MCI_STATUS_MODE:
|
||||
switch (statusParams.dwReturn) {
|
||||
case MCI_MODE_NOT_READY:_MCI_STR("not ready");break;
|
||||
case MCI_MODE_STOP:_MCI_STR("stopped");break;
|
||||
case MCI_MODE_PLAY:_MCI_STR("playing");break;
|
||||
case MCI_MODE_RECORD:_MCI_STR("recording");break;
|
||||
case MCI_MODE_SEEK:_MCI_STR("seeking");break;
|
||||
case MCI_MODE_PAUSE:_MCI_STR("paused");break;
|
||||
case MCI_MODE_OPEN:_MCI_STR("open");break;
|
||||
default:break;
|
||||
}
|
||||
break;
|
||||
case MCI_STATUS_MEDIA_PRESENT:
|
||||
if (statusParams.dwReturn)
|
||||
_MCI_STR("true");
|
||||
else
|
||||
_MCI_STR("false");
|
||||
break;
|
||||
case MCI_STATUS_NUMBER_OF_TRACKS:
|
||||
case MCI_STATUS_CURRENT_TRACK:
|
||||
{ char buf[16];
|
||||
sprintf(buf,"%ld",statusParams.dwReturn);
|
||||
_MCI_STR(buf);
|
||||
break;
|
||||
}
|
||||
case MCI_STATUS_POSITION:
|
||||
case MCI_STATUS_LENGTH:
|
||||
{ char buf[100];
|
||||
switch (timef) {
|
||||
case MCI_FORMAT_MILLISECONDS:
|
||||
case MCI_FORMAT_FRAMES:
|
||||
case MCI_FORMAT_BYTES:
|
||||
case MCI_FORMAT_SAMPLES:
|
||||
sprintf(buf,"%ld",statusParams.dwReturn);
|
||||
_MCI_STR(buf);
|
||||
break;
|
||||
case MCI_FORMAT_HMS:
|
||||
/* well, the macros have the same content*/
|
||||
/*FALLTRHOUGH*/
|
||||
case MCI_FORMAT_MSF:
|
||||
sprintf(buf,"%d:%d:%d",
|
||||
MCI_HMS_HOUR(statusParams.dwReturn),
|
||||
MCI_HMS_MINUTE(statusParams.dwReturn),
|
||||
MCI_HMS_SECOND(statusParams.dwReturn)
|
||||
);
|
||||
_MCI_STR(buf);
|
||||
break;
|
||||
case MCI_FORMAT_TMSF:
|
||||
sprintf(buf,"%d:%d:%d:%d",
|
||||
MCI_TMSF_TRACK(statusParams.dwReturn),
|
||||
MCI_TMSF_MINUTE(statusParams.dwReturn),
|
||||
MCI_TMSF_SECOND(statusParams.dwReturn),
|
||||
MCI_TMSF_FRAME(statusParams.dwReturn)
|
||||
);
|
||||
_MCI_STR(buf);
|
||||
break;
|
||||
default:
|
||||
fprintf(stdnimp,"mciSendString:STATUS:missing timeformat for %d, report.\n",timef);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MCI_STATUS_TIME_FORMAT:
|
||||
switch (timef) {
|
||||
case MCI_FORMAT_MILLISECONDS:_MCI_STR("milliseconds");break;
|
||||
case MCI_FORMAT_FRAMES:_MCI_STR("frames");break;
|
||||
case MCI_FORMAT_BYTES:_MCI_STR("bytes");break;
|
||||
case MCI_FORMAT_SAMPLES:_MCI_STR("samples");break;
|
||||
case MCI_FORMAT_HMS:_MCI_STR("hms");break;
|
||||
case MCI_FORMAT_MSF:_MCI_STR("msf");break;
|
||||
case MCI_FORMAT_TMSF:_MCI_STR("tmsf");break;
|
||||
default:
|
||||
fprintf(stdnimp,"mciSendString:STATUS:missing timeformat for %d, report.\n",timef);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stdnimp,"mciSendString:STATUS:missing result for %ld, report.\n",statusParams.dwItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(keywords);free(cmd);
|
||||
return res;
|
||||
}
|
||||
if (!strcmp(cmd,"SET")) {
|
||||
MCI_SET_PARMS setParams;
|
||||
|
||||
if (args==NULL) {
|
||||
free(keywords);free(cmd);
|
||||
return MCIERR_MISSING_STRING_ARGUMENT;
|
||||
}
|
||||
setParams.dwCallback = 0;
|
||||
i=0;
|
||||
while (i<nrofkeywords) {
|
||||
if (!strcmp(keywords[i],"DOOR") && i+1<nrofkeywords) {
|
||||
if (!strcmp(keywords[i+1],"OPEN"))
|
||||
dwFlags |= MCI_SET_DOOR_OPEN;
|
||||
if (!strcmp(keywords[i+1],"CLOSED"))
|
||||
dwFlags |= MCI_SET_DOOR_CLOSED;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(keywords[i],"TIME") &&
|
||||
(i+2<nrofkeywords) &&
|
||||
!strcmp(keywords[i+1],"FORMAT")
|
||||
) {
|
||||
dwFlags |= MCI_SET_TIME_FORMAT;
|
||||
if (!strcmp(keywords[i+2],"MS"))
|
||||
setParams.dwTimeFormat = MCI_FORMAT_MSF;
|
||||
if (!strcmp(keywords[i+2],"MILLISECONDS"))
|
||||
setParams.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
|
||||
if (!strcmp(keywords[i+2],"MSF"))
|
||||
setParams.dwTimeFormat = MCI_FORMAT_MSF;
|
||||
if (!strcmp(keywords[i+2],"HMS")) /* untested */
|
||||
setParams.dwTimeFormat = MCI_FORMAT_HMS;
|
||||
if (!strcmp(keywords[i+2],"FRAMES")) /* untested */
|
||||
setParams.dwTimeFormat = MCI_FORMAT_FRAMES;
|
||||
if (!strcmp(keywords[i+2],"BYTES")) /* untested */
|
||||
setParams.dwTimeFormat = MCI_FORMAT_BYTES;
|
||||
if (!strcmp(keywords[i+2],"SAMPLES")) /* untested */
|
||||
setParams.dwTimeFormat = MCI_FORMAT_SAMPLES;
|
||||
if (!strcmp(keywords[i+2],"TMSF")) /* untested */
|
||||
setParams.dwTimeFormat = MCI_FORMAT_TMSF;
|
||||
if (!strcmp(keywords[i+2],"SMPTE") && (i+3<nrofkeywords)) {
|
||||
/* all untested */
|
||||
if (!strcmp(keywords[i+3],"24"))
|
||||
setParams.dwTimeFormat = MCI_FORMAT_SMPTE_24;
|
||||
if (!strcmp(keywords[i+3],"25"))
|
||||
setParams.dwTimeFormat = MCI_FORMAT_SMPTE_25;
|
||||
if (!strcmp(keywords[i+3],"30"))
|
||||
setParams.dwTimeFormat = MCI_FORMAT_SMPTE_30;
|
||||
if (!strcmp(keywords[i+3],"30DROP"))
|
||||
setParams.dwTimeFormat = MCI_FORMAT_SMPTE_30DROP;
|
||||
i++;
|
||||
/*FALLTHROUGH*/
|
||||
}
|
||||
i+=3;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(args,"AUDIO") && (i+1<nrofkeywords)) {
|
||||
dwFlags |= MCI_SET_AUDIO;
|
||||
/* I'm not sure if those belong to the flags...
|
||||
* they could belong to setParams.dwAudio
|
||||
*/
|
||||
if (!strcmp(args,"ALL"))
|
||||
dwFlags |= MCI_SET_AUDIO_ALL;
|
||||
if (!strcmp(args,"LEFT"))
|
||||
dwFlags |= MCI_SET_AUDIO_LEFT;
|
||||
if (!strcmp(args,"RIGHT"))
|
||||
dwFlags |= MCI_SET_AUDIO_RIGHT;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(args,"VIDEO")) {
|
||||
/* how to handle those? */
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(args,"ON")) {
|
||||
dwFlags |= MCI_SET_ON;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(args,"OFF")) {
|
||||
dwFlags |= MCI_SET_ON;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
_MCI_CALL_DRIVER(MCI_SET,setParams);
|
||||
if (res==0) { /* does set return data? */ }
|
||||
free(keywords);free(cmd);
|
||||
return res;
|
||||
}
|
||||
if (!strcmp(cmd,"CAPABILITY")) {
|
||||
MCI_GETDEVCAPS_PARMS gdcParams;
|
||||
|
||||
gdcParams.dwCallback = 0;
|
||||
if (args==NULL) {
|
||||
free(keywords);free(cmd);
|
||||
return MCIERR_MISSING_STRING_ARGUMENT;
|
||||
}
|
||||
dwFlags |= MCI_GETDEVCAPS_ITEM;
|
||||
gdcParams.dwItem = 0;
|
||||
i=0;
|
||||
while (i<nrofkeywords) {
|
||||
if ( !strcmp(keywords[i],"DEVICE") &&
|
||||
(i+1<nrofkeywords) &&
|
||||
!strcmp(keywords[i+1],"TYPE")
|
||||
) {
|
||||
gdcParams.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(keywords[i],"HAS") &&
|
||||
(i+1<nrofkeywords) &&
|
||||
!strcmp(keywords[i+1],"AUDIO")
|
||||
) {
|
||||
gdcParams.dwItem = MCI_GETDEVCAPS_HAS_AUDIO;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(keywords[i],"HAS") &&
|
||||
(i+1<nrofkeywords) &&
|
||||
!strcmp(keywords[i+1],"VIDEO")
|
||||
) {
|
||||
gdcParams.dwItem = MCI_GETDEVCAPS_HAS_VIDEO;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(keywords[i],"USES") &&
|
||||
(i+1<nrofkeywords) &&
|
||||
!strcmp(keywords[i+1],"FILES")
|
||||
) {
|
||||
gdcParams.dwItem = MCI_GETDEVCAPS_HAS_VIDEO;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(keywords[i],"COMPOUND") &&
|
||||
(i+1<nrofkeywords) &&
|
||||
!strcmp(keywords[i+1],"DEVICE")
|
||||
) {
|
||||
gdcParams.dwItem = MCI_GETDEVCAPS_COMPOUND_DEVICE;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(keywords[i],"CAN") && (i+1<nrofkeywords)) {
|
||||
if (!strcmp(keywords[i+1],"RECORD"))
|
||||
gdcParams.dwItem = MCI_GETDEVCAPS_CAN_RECORD;
|
||||
if (!strcmp(keywords[i+1],"PLAY"))
|
||||
gdcParams.dwItem = MCI_GETDEVCAPS_CAN_PLAY;
|
||||
if (!strcmp(keywords[i+1],"EJECT"))
|
||||
gdcParams.dwItem = MCI_GETDEVCAPS_CAN_EJECT;
|
||||
if (!strcmp(keywords[i+1],"SAVE"))
|
||||
gdcParams.dwItem = MCI_GETDEVCAPS_CAN_SAVE;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
res=-1;
|
||||
_MCI_CALL_DRIVER(MCI_GETDEVCAPS,gdcParams);
|
||||
fprintf(stderr,"GETDEVCAPS returned res=%d\n",res);
|
||||
if (res==0) {
|
||||
switch (gdcParams.dwItem) {
|
||||
case MCI_GETDEVCAPS_DEVICE_TYPE:
|
||||
switch (gdcParams.dwReturn) {
|
||||
case MCI_DEVTYPE_VCR:_MCI_STR("vcr");break;
|
||||
case MCI_DEVTYPE_VIDEODISC:_MCI_STR("videodisc");break;
|
||||
case MCI_DEVTYPE_CD_AUDIO:_MCI_STR("cd audio");break;
|
||||
case MCI_DEVTYPE_OVERLAY:_MCI_STR("overlay");break;
|
||||
case MCI_DEVTYPE_DAT:_MCI_STR("dat");break;
|
||||
case MCI_DEVTYPE_SCANNER:_MCI_STR("scanner");break;
|
||||
case MCI_DEVTYPE_ANIMATION:_MCI_STR("animation");break;
|
||||
case MCI_DEVTYPE_DIGITAL_VIDEO:_MCI_STR("digital video");break;
|
||||
case MCI_DEVTYPE_OTHER:_MCI_STR("other");break;
|
||||
case MCI_DEVTYPE_WAVEFORM_AUDIO:_MCI_STR("waveform audio");break;
|
||||
case MCI_DEVTYPE_SEQUENCER:_MCI_STR("sequencer");break;
|
||||
default:fprintf(stdnimp,"mciSendString:GETCAPS_DEVTYPE:unknown type %ld, report.\n",gdcParams.dwReturn);break;
|
||||
}
|
||||
break;
|
||||
case MCI_GETDEVCAPS_CAN_PLAY:
|
||||
case MCI_GETDEVCAPS_CAN_EJECT:
|
||||
case MCI_GETDEVCAPS_CAN_RECORD:
|
||||
case MCI_GETDEVCAPS_CAN_SAVE:
|
||||
case MCI_GETDEVCAPS_HAS_AUDIO:
|
||||
case MCI_GETDEVCAPS_HAS_VIDEO:
|
||||
case MCI_GETDEVCAPS_COMPOUND_DEVICE:
|
||||
case MCI_GETDEVCAPS_USES_FILES:
|
||||
/* well, is this right? no example here */
|
||||
if (gdcParams.dwReturn)
|
||||
_MCI_STR("true");
|
||||
else
|
||||
_MCI_STR("false");
|
||||
break;
|
||||
default:fprintf(stdnimp,"mciSendString:GETDEVCAPS:unknown type %ld, report.\n",gdcParams.dwItem);break;
|
||||
}
|
||||
}
|
||||
free(keywords);free(cmd);
|
||||
return res;
|
||||
}
|
||||
if (!strcmp(cmd,"PAUSE")) {
|
||||
MCI_GENERIC_PARMS genParams;
|
||||
genParams.dwCallback=0;
|
||||
_MCI_CALL_DRIVER(MCI_PAUSE,genParams);
|
||||
free(keywords);free(cmd);
|
||||
return res;
|
||||
}
|
||||
if (!strcmp(cmd,"PLAY")) {
|
||||
int nrargs,j,k,a[4];
|
||||
char *parsestr;
|
||||
MCI_PLAY_PARMS playParams;
|
||||
MCI_STATUS_PARMS statusParams;
|
||||
|
||||
statusParams.dwCallback=0;
|
||||
statusParams.dwItem=MCI_STATUS_TIME_FORMAT;
|
||||
dwFlags |= MCI_STATUS_ITEM;
|
||||
_MCI_CALL_DRIVER(MCI_STATUS,statusParams);
|
||||
dwFlags &= ~MCI_STATUS_ITEM;
|
||||
timef=statusParams.dwReturn;
|
||||
switch (timef) {
|
||||
case MCI_FORMAT_MILLISECONDS:
|
||||
case MCI_FORMAT_FRAMES:
|
||||
case MCI_FORMAT_BYTES:
|
||||
case MCI_FORMAT_SAMPLES:
|
||||
nrargs=1;
|
||||
parsestr="%d";
|
||||
break;
|
||||
case MCI_FORMAT_HMS:
|
||||
case MCI_FORMAT_MSF:
|
||||
parsestr="%d:%d:%d";
|
||||
nrargs=3;
|
||||
break;
|
||||
case MCI_FORMAT_TMSF:
|
||||
parsestr="%d:%d:%d:%d";
|
||||
nrargs=4;
|
||||
break;
|
||||
default:fprintf(stdnimp,"mciSendString:PLAY:unknown timeformat %d, please report.\n",timef);
|
||||
parsestr="%d";
|
||||
nrargs=1;
|
||||
break;
|
||||
}
|
||||
playParams.dwCallback=0;
|
||||
i=0;
|
||||
while (i<nrofkeywords) {
|
||||
if ( !strcmp(keywords[i],"TO") &&
|
||||
(i+1<nrofkeywords)
|
||||
) {
|
||||
dwFlags |= MCI_TO;
|
||||
a[0]=a[1]=a[2]=a[3]=0;
|
||||
j=sscanf(keywords[i+1],parsestr,&a[0],&a[1],&a[2],&a[3]);
|
||||
/* add up all integers we got, if we have more
|
||||
* shift them. (Well I should use the macros in
|
||||
* mmsystem.h, right).
|
||||
*/
|
||||
playParams.dwTo=0;
|
||||
for (k=0;k<j;k++)
|
||||
playParams.dwTo+=a[k]<<(8*(nrargs-k));
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(keywords[i],"FROM") &&
|
||||
(i+1<nrofkeywords)
|
||||
) {
|
||||
dwFlags |= MCI_FROM;
|
||||
a[0]=a[1]=a[2]=a[3]=0;
|
||||
j=sscanf(keywords[i+1],parsestr,&a[0],&a[1],&a[2],&a[3]);
|
||||
/* dito. */
|
||||
playParams.dwFrom=0;
|
||||
for (k=0;k<j;k++)
|
||||
playParams.dwFrom+=a[k]<<(8*(nrargs-k));
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
_MCI_CALL_DRIVER(MCI_PLAY,playParams);
|
||||
free(keywords);free(cmd);
|
||||
return res;
|
||||
}
|
||||
if (!strcmp(cmd,"STOP")) {
|
||||
MCI_GENERIC_PARMS genParams;
|
||||
genParams.dwCallback=0;
|
||||
_MCI_CALL_DRIVER(MCI_STOP,genParams);
|
||||
free(keywords);free(cmd);
|
||||
return res;
|
||||
}
|
||||
if (!strcmp(cmd,"SEEK")) {
|
||||
int nrargs,j,k,a[4];
|
||||
char *parsestr;
|
||||
MCI_STATUS_PARMS statusParams;
|
||||
MCI_SEEK_PARMS seekParams;
|
||||
|
||||
statusParams.dwCallback=0;
|
||||
statusParams.dwItem=MCI_STATUS_TIME_FORMAT;
|
||||
dwFlags |= MCI_STATUS_ITEM;
|
||||
_MCI_CALL_DRIVER(MCI_STATUS,statusParams);
|
||||
dwFlags &= ~MCI_STATUS_ITEM;
|
||||
timef=statusParams.dwReturn;
|
||||
switch (timef) {
|
||||
case MCI_FORMAT_MILLISECONDS:
|
||||
case MCI_FORMAT_FRAMES:
|
||||
case MCI_FORMAT_BYTES:
|
||||
case MCI_FORMAT_SAMPLES:
|
||||
nrargs=1;
|
||||
parsestr="%d";
|
||||
break;
|
||||
case MCI_FORMAT_HMS:
|
||||
case MCI_FORMAT_MSF:
|
||||
parsestr="%d:%d:%d";
|
||||
nrargs=3;
|
||||
break;
|
||||
case MCI_FORMAT_TMSF:
|
||||
parsestr="%d:%d:%d:%d";
|
||||
nrargs=4;
|
||||
break;
|
||||
default:fprintf(stdnimp,"mciSendString:SEEK:unknown timeformat %d, please report.\n",timef);
|
||||
parsestr="%d";
|
||||
nrargs=1;
|
||||
break;
|
||||
}
|
||||
seekParams.dwCallback=0;
|
||||
i=0;
|
||||
while (i<nrofkeywords) {
|
||||
if ( !strcmp(keywords[i],"TO") &&
|
||||
(i+1<nrofkeywords)
|
||||
) {
|
||||
if (!strcmp(keywords[i+1],"START")) {
|
||||
dwFlags=MCI_SEEK_TO_START;
|
||||
seekParams.dwTo=0;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(keywords[i+1],"END")) {
|
||||
dwFlags=MCI_SEEK_TO_END;
|
||||
seekParams.dwTo=0;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
dwFlags=MCI_TO;
|
||||
i+=2;
|
||||
a[0]=a[1]=a[2]=a[3]=0;
|
||||
j=sscanf(keywords[i+1],parsestr,&a[0],&a[1],&a[2],&a[3]);
|
||||
seekParams.dwTo=0;
|
||||
for (k=0;k<j;k++)
|
||||
seekParams.dwTo+=a[k]<<(8*(nrargs-k));
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
_MCI_CALL_DRIVER(MCI_SEEK,seekParams);
|
||||
free(keywords);free(cmd);
|
||||
return res;
|
||||
}
|
||||
if (!strcmp(cmd,"CLOSE")) {
|
||||
MCI_GENERIC_PARMS closeParams;
|
||||
|
||||
closeParams.dwCallback=0;
|
||||
_MCI_CALL_DRIVER(MCI_CLOSE,closeParams);
|
||||
free(keywords);free(cmd);
|
||||
return res;
|
||||
}
|
||||
if (!strcmp(cmd,"INFO")) {
|
||||
MCI_INFO_PARMS infoParams;
|
||||
|
||||
dwFlags=-1;
|
||||
while (i<nrofkeywords) {
|
||||
if (!strcmp(keywords[i],"PRODUCT")) {
|
||||
dwFlags=MCI_INFO_PRODUCT;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(keywords[i],"FILE")) {
|
||||
dwFlags=MCI_INFO_FILE;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (dwFlags==-1) {
|
||||
free(keywords);free(cmd);
|
||||
return MCIERR_MISSING_STRING_ARGUMENT;
|
||||
}
|
||||
_MCI_CALL_DRIVER(MCI_INFO,infoParams);
|
||||
if (res==0) {
|
||||
_MCI_STR(infoParams.lpstrReturn);
|
||||
}
|
||||
free(cmd);free(keywords);
|
||||
return res;
|
||||
}
|
||||
fprintf(stdnimp, "mciSendString('%s', %p, %u, %X) // unimplemented, please report.\n", lpstrCommand,
|
||||
lpstrReturnString, uReturnLength, hwndCallback
|
||||
);
|
||||
free(keywords);free(cmd);
|
||||
return MCIERR_MISSING_COMMAND_STRING;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* mciSetYieldProc [MMSYSTEM.714]
|
||||
*/
|
||||
|
|
|
@ -29,7 +29,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
|
|
@ -1302,3 +1302,11 @@ BOOL StretchBlt( HDC hdcDst, short xDst, short yDst,
|
|||
dcDst, xDst, yDst, widthDst, heightDst,
|
||||
dcSrc, xSrc, ySrc, widthSrc, heightSrc, rop );
|
||||
}
|
||||
/***********************************************************************
|
||||
* FastWindowFrame (GDI.400)
|
||||
*/
|
||||
WORD
|
||||
FastWindowFrame(WORD x1,DWORD x2,WORD x3,WORD x4,DWORD x5) {
|
||||
dprintf_gdi(stdnimp,"FastWindowFrame (%04x, %08lx, %04x, %04x, %08lx) // unimplemented!\n",x1,x2,x3,x4,x5);
|
||||
return 0xFFFF; /* failed? */
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ BOOL FONT_Init( void )
|
|||
FontNames[0].x11 = strdup( temp );
|
||||
|
||||
} else {
|
||||
FontNames[0].window = NULL; FontNames[0].x11 = "bitstream-courier";
|
||||
FontNames[0].window = NULL; FontNames[0].x11 = "*-helvetica";
|
||||
FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
|
||||
FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
|
||||
FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
|
||||
|
@ -313,7 +313,8 @@ HFONT CreateFont( int height, int width, int esc, int orient, int weight,
|
|||
{
|
||||
LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
|
||||
strikeout, charset, outpres, clippres, quality, pitch, };
|
||||
strncpy( logfont.lfFaceName, name, LF_FACESIZE );
|
||||
if (name) strncpy( logfont.lfFaceName, name, LF_FACESIZE );
|
||||
else logfont.lfFaceName[0] = '\0';
|
||||
return CreateFontIndirect( &logfont );
|
||||
}
|
||||
|
||||
|
|
|
@ -35,16 +35,11 @@
|
|||
#include "bitmaps/obm_dnarrowd"
|
||||
#include "bitmaps/obm_uparrowd"
|
||||
#include "bitmaps/obm_restored"
|
||||
#include "bitmaps/obm_zoomd"
|
||||
#include "bitmaps/obm_reduced"
|
||||
#include "bitmaps/obm_restore"
|
||||
#include "bitmaps/obm_zoom"
|
||||
#include "bitmaps/obm_reduce"
|
||||
#include "bitmaps/obm_lfarrow"
|
||||
#include "bitmaps/obm_rgarrow"
|
||||
#include "bitmaps/obm_dnarrow"
|
||||
#include "bitmaps/obm_uparrow"
|
||||
#include "bitmaps/obm_close"
|
||||
#include "bitmaps/obm_old_restore"
|
||||
#include "bitmaps/obm_old_zoom"
|
||||
#include "bitmaps/obm_old_reduce"
|
||||
|
@ -59,6 +54,21 @@
|
|||
#include "bitmaps/obm_size"
|
||||
#include "bitmaps/obm_old_close"
|
||||
|
||||
#ifndef WIN_95_LOOK
|
||||
#include "bitmaps/obm_zoomd"
|
||||
#include "bitmaps/obm_reduced"
|
||||
#include "bitmaps/obm_zoom"
|
||||
#include "bitmaps/obm_reduce"
|
||||
#include "bitmaps/obm_close"
|
||||
#else
|
||||
#include "bitmaps/obm_zoomd_95"
|
||||
#include "bitmaps/obm_reduced_95"
|
||||
#include "bitmaps/obm_zoom_95"
|
||||
#include "bitmaps/obm_reduce_95"
|
||||
#include "bitmaps/obm_close_95"
|
||||
#include "bitmaps/obm_closed_95"
|
||||
#endif /* WIN_95_LOOK */
|
||||
|
||||
#define OBM_FIRST OBM_CDROM /* First OEM bitmap */
|
||||
#define OBM_LAST OBM_OLD_CLOSE /* Last OEM bitmap */
|
||||
|
||||
|
@ -86,13 +96,22 @@ static const struct
|
|||
{ obm_zoomd, TRUE }, /* OBM_ZOOMD */
|
||||
{ obm_reduced, TRUE }, /* OBM_REDUCED */
|
||||
{ obm_restore, TRUE }, /* OBM_RESTORE */
|
||||
#ifdef WIN_95_LOOK
|
||||
{ obm_zoom_95, TRUE }, /* OBM_ZOOM */
|
||||
{ obm_reduce_95, TRUE }, /* OBM_REDUCE */
|
||||
#else
|
||||
{ obm_zoom, TRUE }, /* OBM_ZOOM */
|
||||
{ obm_reduce, TRUE }, /* OBM_REDUCE */
|
||||
#endif
|
||||
{ obm_lfarrow, TRUE }, /* OBM_LFARROW */
|
||||
{ obm_rgarrow, TRUE }, /* OBM_RGARROW */
|
||||
{ obm_dnarrow, TRUE }, /* OBM_DNARROW */
|
||||
{ obm_uparrow, TRUE }, /* OBM_UPARROW */
|
||||
#ifdef WIN_95_LOOK
|
||||
{ obm_close_95, TRUE }, /* OBM_CLOSE */
|
||||
#else
|
||||
{ obm_close, TRUE }, /* OBM_CLOSE */
|
||||
#endif
|
||||
{ obm_old_restore, FALSE }, /* OBM_OLD_RESTORE */
|
||||
{ obm_old_zoom, FALSE }, /* OBM_OLD_ZOOM */
|
||||
{ obm_old_reduce, FALSE }, /* OBM_OLD_REDUCE */
|
||||
|
@ -163,6 +182,7 @@ static const struct
|
|||
{ "button_face", PALETTEINDEX(COLOR_BTNFACE) },
|
||||
{ "button_shadow", PALETTEINDEX(COLOR_BTNSHADOW) },
|
||||
{ "button_highlight", PALETTEINDEX(COLOR_BTNHIGHLIGHT) },
|
||||
{ "button_edge", PALETTEINDEX(COLOR_BTNHIGHLIGHT) },
|
||||
{ "button_text", PALETTEINDEX(COLOR_BTNTEXT) },
|
||||
{ "window_frame", PALETTEINDEX(COLOR_WINDOWFRAME) }
|
||||
};
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
----------------------------------------------------------------------
|
||||
Sun Sep 25 12:00:00 PDT 1994 <martin@osiris.cs.csufresno.edu>
|
||||
|
||||
* [rc/rc.y] [rc/rc.h] [rc/rc.l] [rc/winerc.c]
|
||||
Files created
|
|
@ -34,8 +34,8 @@ rc.o: sysres.o
|
|||
$(COMPILE) -c -o $*.o $<
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ lex.yy.c sysres.tmp sysres.rct winerc y.tab.c \
|
||||
y.tab.h sysres.c sysres.h tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
rm -f lex.yy.c sysres.tmp sysres.rct winerc y.tab.c y.tab.h sysres.c sysres.h
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
|
106
rc/rc.h
106
rc/rc.h
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright Martin von Loewis, 1994
|
||||
*
|
||||
*/
|
||||
|
||||
/* resource types */
|
||||
enum rt {acc,bmp,cur,dlg,fnt,ico,men,rdt,str};
|
||||
/* generic resource
|
||||
Bytes can be inserted at arbitrary positions, the data field (res)
|
||||
grows as required. As the dialog header contains the number of
|
||||
controls, this number is generated in num_entries. If n_type if 0,
|
||||
the resource name is i_name, and s_name otherwise. Top level
|
||||
resources are linked via next. All gen_res objects are linked via
|
||||
g_prev, g_next for debugging purposes. space is the length of res,
|
||||
size is the used part of res.
|
||||
As most bison rules are right recursive, new items are usually
|
||||
inserted at the beginning
|
||||
*/
|
||||
typedef struct gen_res{
|
||||
int size,space;
|
||||
int num_entries;
|
||||
enum rt type;
|
||||
union{
|
||||
int i_name;
|
||||
char* s_name;
|
||||
}n;
|
||||
int n_type; /*0 - integer, 1 = string*/
|
||||
struct gen_res *next;
|
||||
struct gen_res *g_prev,*g_next;
|
||||
unsigned char res[0];
|
||||
} gen_res;
|
||||
|
||||
/* control/dialog style. or collects styles, and collects NOT styles */
|
||||
typedef struct rc_style{
|
||||
int and, or;
|
||||
}rc_style;
|
||||
|
||||
/* create a new resource */
|
||||
gen_res *new_res(void);
|
||||
/* double the space of the resource */
|
||||
gen_res* grow(gen_res*);
|
||||
/* insert byte array at the beginning, increase count */
|
||||
gen_res* insert_at_beginning(gen_res*,char*,int);
|
||||
/* insert byte array at offset */
|
||||
gen_res* insert_bytes(gen_res*,char*,int,int);
|
||||
/* delete bytes at offset */
|
||||
gen_res* delete_bytes(gen_res*,int,int);
|
||||
/* create a new style */
|
||||
rc_style* new_style(void);
|
||||
/* convert \t to tab etc. */
|
||||
char* parse_c_string(char*);
|
||||
/* get the resources type, convert dlg to "DIALOG" and so on */
|
||||
char* get_typename(gen_res*);
|
||||
|
||||
gen_res* add_accelerator(int,int,int,gen_res*);
|
||||
gen_res* add_string_accelerator(char*,int,int,gen_res*);
|
||||
gen_res* add_ascii_accelerator(int,int,int,gen_res*);
|
||||
gen_res* add_vk_accelerator(int,int,int,gen_res*);
|
||||
|
||||
gen_res* new_dialog(void);
|
||||
gen_res* dialog_style(rc_style*,gen_res*);
|
||||
int dialog_get_menu(gen_res*);
|
||||
int dialog_get_class(gen_res*);
|
||||
int dialog_get_caption(gen_res*);
|
||||
int dialog_get_fontsize(gen_res*);
|
||||
gen_res* dialog_caption(char*,gen_res*);
|
||||
gen_res* dialog_font(short,char*,gen_res*);
|
||||
gen_res* dialog_class(char*,gen_res*);
|
||||
gen_res* dialog_menu(char*,gen_res*);
|
||||
gen_res* create_control_desc(int,int,int,int,int,rc_style*);
|
||||
gen_res* label_control_desc(char*,gen_res*);
|
||||
gen_res* create_generic_control(char*,int,char*,rc_style*,int,int,int,int);
|
||||
gen_res* add_control(int,int,gen_res*,gen_res*);
|
||||
gen_res* add_icon(char*,int,int,int,gen_res*,gen_res*);
|
||||
gen_res* add_generic_control(gen_res*,gen_res*);
|
||||
gen_res* make_dialog(gen_res*,int,int,int,int,gen_res*);
|
||||
|
||||
gen_res *hex_to_raw(char*,gen_res*);
|
||||
gen_res *make_bitmap(gen_res*);
|
||||
gen_res *make_icon(gen_res*);
|
||||
gen_res *make_cursor(gen_res*);
|
||||
gen_res *load_file(char*);
|
||||
|
||||
gen_res *add_menuitem(char*,int,int,gen_res*);
|
||||
gen_res *add_popup(char*,short,gen_res*,gen_res*);
|
||||
gen_res *make_menu(gen_res*);
|
||||
|
||||
gen_res *add_resource(gen_res*,gen_res*);
|
||||
|
||||
void create_output(gen_res*);
|
||||
void set_out_file(char*);
|
||||
|
||||
#define CT_BUTTON 0x80
|
||||
#define CT_EDIT 0x81
|
||||
#define CT_STATIC 0x82
|
||||
#define CT_LISTBOX 0x83
|
||||
#define CT_SCROLLBAR 0x84
|
||||
#define CT_COMBOBOX 0x85
|
||||
|
||||
extern int verbose;
|
||||
|
||||
#ifdef __sun__
|
||||
#define strtoul strtol
|
||||
#endif
|
||||
|
75
rc/rc.l
75
rc/rc.l
|
@ -1,75 +0,0 @@
|
|||
%{
|
||||
/*
|
||||
*
|
||||
* Copyright Martin von Loewis, 1994
|
||||
*
|
||||
*/
|
||||
static char Copyright[] = "Copyright Martin von Loewis, 1994";
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "rc.h"
|
||||
#include "rc.tab.h"
|
||||
%}
|
||||
%%
|
||||
ACCELERATORS return ACCELERATORS;
|
||||
ALT return ALT;
|
||||
ASCII return ASCII;
|
||||
BEGIN return tBEGIN;
|
||||
BITMAP return tBITMAP;
|
||||
CAPTION return CAPTION;
|
||||
CHECKBOX return CHECKBOX;
|
||||
CHECKED return CHECKED;
|
||||
CLASS return CLASS;
|
||||
COMBOBOX return COMBOBOX;
|
||||
CONTROL return CONTROL;
|
||||
CTEXT return CTEXT;
|
||||
CURSOR return CURSOR;
|
||||
DEFPUSHBUTTON return DEFPUSHBUTTON;
|
||||
DIALOG return DIALOG;
|
||||
DISCARDABLE return DISCARDABLE;
|
||||
EDITTEXT return EDITTEXT;
|
||||
END return tEND;
|
||||
FIXED return FIXED;
|
||||
FONT return FONT;
|
||||
GRAYED return GRAYED;
|
||||
GROUPBOX return GROUPBOX;
|
||||
HELP return HELP;
|
||||
ICON return ICON;
|
||||
INACTIVE return INACTIVE;
|
||||
LISTBOX return LISTBOX;
|
||||
LTEXT return LTEXT;
|
||||
MENU return MENU;
|
||||
MENUBARBREAK return MENUBARBREAK;
|
||||
MENUBREAK return MENUBREAK;
|
||||
MENUITEM return MENUITEM;
|
||||
MOVEABLE return MOVEABLE;
|
||||
LOADONCALL return LOADONCALL;
|
||||
NOINVERT return NOINVERT;
|
||||
NOT return NOT;
|
||||
NUMBER return NUMBER;
|
||||
POPUP return POPUP;
|
||||
PRELOAD return PRELOAD;
|
||||
PUSHBUTTON return PUSHBUTTON;
|
||||
PURE return PURE;
|
||||
RADIOBUTTON return RADIOBUTTON;
|
||||
RCDATA return RCDATA;
|
||||
RTEXT return RTEXT;
|
||||
SCROLLBAR return SCROLLBAR;
|
||||
SHIFT return SHIFT;
|
||||
SEPARATOR return SEPARATOR;
|
||||
STRING return STRING;
|
||||
STRINGTABLE return STRINGTABLE;
|
||||
STYLE return STYLE;
|
||||
VERSIONINFO return VERSIONINFO;
|
||||
VIRTKEY return VIRTKEY;
|
||||
\{ return tBEGIN;
|
||||
\} return tEND;
|
||||
[+-]?[0-9]+ yylval.num=atoi(yytext);return NUMBER;
|
||||
0x[0-9A-Fa-f]+L? yylval.num=strtoul(yytext,0,16);return NUMBER;
|
||||
[A-Za-z][A-Za-z_0-9]* yylval.str=strdup(yytext);return IDENT;
|
||||
\"[^"]*\" yylval.str=parse_c_string(yytext);return STRING;
|
||||
\'[^']*\' yylval.str=strdup(yytext+1);return SINGLE_QUOTED;
|
||||
[ \t\n\r] ;
|
||||
. return yytext[0];
|
210
rc/rc.y
210
rc/rc.y
|
@ -1,210 +0,0 @@
|
|||
%{
|
||||
/*
|
||||
*
|
||||
* Copyright Martin von Loewis, 1994
|
||||
*/
|
||||
|
||||
static char Copyright[] = "Copyright Martin von Loewis, 1994";
|
||||
|
||||
#include <stdio.h>
|
||||
#include "rc.h"
|
||||
#include "windows.h"
|
||||
%}
|
||||
%union{
|
||||
gen_res *res;
|
||||
char *str;
|
||||
int num;
|
||||
struct rc_style *style;
|
||||
}
|
||||
%token <num> NUMBER
|
||||
%token <str> STRING SINGLE_QUOTED IDENT
|
||||
%token ACCELERATORS ALT ASCII tBEGIN tBITMAP CAPTION CHECKBOX CHECKED
|
||||
%token CLASS COMBOBOX CONTROL CTEXT CURSOR DEFPUSHBUTTON DIALOG
|
||||
%token DISCARDABLE EDITTEXT tEND FIXED FONT GRAYED GROUPBOX HELP ICON
|
||||
%token IDENT INACTIVE LISTBOX LTEXT MENU MENUBARBREAK MENUBREAK MENUITEM
|
||||
%token MOVEABLE LOADONCALL NOINVERT NOT NOT_SUPPORTED POPUP PRELOAD
|
||||
%token PURE PUSHBUTTON RADIOBUTTON RCDATA RTEXT SCROLLBAR SHIFT SEPARATOR
|
||||
%token SINGLE_QUOTED STRING STRINGTABLE STYLE VERSIONINFO VIRTKEY
|
||||
%type <res> resource_file resource resources resource_definition accelerators
|
||||
%type <res> events bitmap cursor dialog dlg_attributes controls
|
||||
%type <res> generic_control labeled_control control_desc font icon
|
||||
%type <res> iconinfo menu menu_body item_definitions rcdata raw_data raw_elements
|
||||
%type <res> stringtable strings versioninfo
|
||||
%type <num> acc_options item_options
|
||||
%type <style> style optional_style
|
||||
%%
|
||||
|
||||
resource_file: resources {create_output($1);}
|
||||
|
||||
/*resources are put into a linked list*/
|
||||
resources: {$$=0;}
|
||||
|resource resources {$$=add_resource($1,$2);}
|
||||
;
|
||||
|
||||
/* get the name for a single resource*/
|
||||
resource: NUMBER resource_definition
|
||||
{$$=$2;$$->n.i_name=$1;$$->n_type=0;
|
||||
if(verbose)fprintf(stderr,"Got %s %d\n",get_typename($2),$1);
|
||||
}
|
||||
| IDENT resource_definition
|
||||
{$$=$2;$$->n.s_name=$1;$$->n_type=1;
|
||||
if(verbose)fprintf(stderr,"Got %s %s\n",get_typename($2),$1);
|
||||
}
|
||||
|
||||
/* get the value for a single resource*/
|
||||
resource_definition: accelerators {$$=$1;}
|
||||
| bitmap {$$=$1;}
|
||||
| cursor {$$=$1;}
|
||||
| dialog {$$=$1;}
|
||||
| font {$$=$1;}
|
||||
| icon {$$=$1;}
|
||||
| menu {$$=$1;}
|
||||
| rcdata {$$=$1;}
|
||||
| stringtable {$$=$1;}
|
||||
| versioninfo {$$=$1;}
|
||||
|
||||
/* have to use tBEGIN because BEGIN is predefined */
|
||||
accelerators: ACCELERATORS tBEGIN events tEND {$$=$3;$$->type=acc;}
|
||||
/* the events are collected in a gen_res, as the accelerator resource is just
|
||||
an array of events */
|
||||
events: {$$=new_res();}
|
||||
| STRING ',' NUMBER acc_options events
|
||||
{$$=add_string_accelerator($1,$3,$4,$5);}
|
||||
| NUMBER ',' NUMBER ',' ASCII acc_options events
|
||||
{$$=add_ascii_accelerator($1,$3,$6,$7);}
|
||||
| NUMBER ',' NUMBER ',' VIRTKEY acc_options events
|
||||
{$$=add_vk_accelerator($1,$3,$6,$7);}
|
||||
acc_options: {$$=0;}
|
||||
| ',' NOINVERT acc_options {$$=$3|2;}
|
||||
| ',' ALT acc_options {$$=$3|16;}
|
||||
| ',' SHIFT acc_options {$$=$3|4;}
|
||||
| ',' CONTROL acc_options {$$=$3|8;}
|
||||
|
||||
bitmap: tBITMAP load_and_memoption STRING {$$=make_bitmap(load_file($3));}
|
||||
| tBITMAP load_and_memoption raw_data {$$=make_bitmap($3);}
|
||||
|
||||
/* load and memory options are ignored */
|
||||
load_and_memoption: | lamo load_and_memoption
|
||||
lamo: PRELOAD | LOADONCALL | FIXED | MOVEABLE | DISCARDABLE | PURE
|
||||
|
||||
cursor: CURSOR load_and_memoption STRING {$$=make_cursor(load_file($3));}
|
||||
|CURSOR load_and_memoption raw_data {$$=make_cursor($3);}
|
||||
|
||||
dialog: DIALOG load_and_memoption NUMBER ',' NUMBER ',' NUMBER ',' NUMBER
|
||||
dlg_attributes
|
||||
tBEGIN controls tEND
|
||||
{$$=make_dialog($10,$3,$5,$7,$9,$12);}
|
||||
|
||||
dlg_attributes: {$$=new_dialog();}
|
||||
| STYLE style dlg_attributes
|
||||
{$$=dialog_style($2,$3);}
|
||||
| CAPTION STRING dlg_attributes
|
||||
{$$=dialog_caption($2,$3);}
|
||||
| FONT NUMBER ',' STRING dlg_attributes
|
||||
{$$=dialog_font($2,$4,$5);}
|
||||
| CLASS STRING dlg_attributes
|
||||
{$$=dialog_class($2,$3);}
|
||||
| MENU STRING dlg_attributes
|
||||
{$$=dialog_menu($2,$3);}
|
||||
|
||||
/* the controls are collected into a gen_res, and finally the dialog header
|
||||
is put at the beginning */
|
||||
controls: {$$=new_res();}
|
||||
| CHECKBOX labeled_control controls
|
||||
{$$=add_control(CT_BUTTON, BS_CHECKBOX, $2, $3);}
|
||||
| COMBOBOX control_desc controls
|
||||
{$$=add_control(CT_COMBOBOX, 0, $2, $3);}
|
||||
| CONTROL generic_control controls
|
||||
{$$=add_generic_control($2, $3);}
|
||||
| CTEXT labeled_control controls
|
||||
{$$=add_control(CT_STATIC, SS_CENTER, $2, $3);}
|
||||
| DEFPUSHBUTTON labeled_control controls
|
||||
{$$=add_control(CT_BUTTON, BS_DEFPUSHBUTTON, $2, $3);}
|
||||
| EDITTEXT control_desc controls
|
||||
{$$=add_control(CT_EDIT, 0, $2, $3);}
|
||||
| GROUPBOX labeled_control controls
|
||||
{$$=add_control(CT_BUTTON, BS_GROUPBOX, $2, $3);}
|
||||
/*special treatment for icons, as the extent is optional*/
|
||||
| ICON STRING ',' NUMBER ',' NUMBER ',' NUMBER iconinfo controls
|
||||
{$$=add_icon($2, $4, $6, $8, $9, $10);}
|
||||
| LISTBOX control_desc controls
|
||||
{$$=add_control(CT_LISTBOX, 0, $2, $3);}
|
||||
| LTEXT labeled_control controls
|
||||
{$$=add_control(CT_STATIC, SS_LEFT, $2, $3);}
|
||||
| PUSHBUTTON labeled_control controls
|
||||
{$$=add_control(CT_BUTTON, BS_PUSHBUTTON, $2, $3);}
|
||||
| RADIOBUTTON labeled_control controls
|
||||
{$$=add_control(CT_BUTTON, BS_RADIOBUTTON, $2, $3);}
|
||||
| RTEXT labeled_control controls
|
||||
{$$=add_control(CT_STATIC, SS_RIGHT, $2, $3);}
|
||||
| SCROLLBAR control_desc controls
|
||||
{$$=add_control(CT_SCROLLBAR, 0, $2, $3);}
|
||||
|
||||
|
||||
labeled_control: STRING ',' control_desc {$$=label_control_desc($1,$3);}
|
||||
control_desc: NUMBER ',' NUMBER ',' NUMBER ',' NUMBER ',' NUMBER optional_style
|
||||
{$$=create_control_desc($1,$3,$5,$7,$9,$10);}
|
||||
|
||||
optional_style: {$$=0;}|
|
||||
',' style {$$=$2;}
|
||||
|
||||
iconinfo: /*set extent and style to 0 if they are not provided */
|
||||
{$$=create_control_desc(0,0,0,0,0,0);}
|
||||
/* x and y are overwritten later */
|
||||
| ',' NUMBER ',' NUMBER optional_style
|
||||
{$$=create_control_desc(0,0,0,$2,$4,$5);}
|
||||
|
||||
generic_control: STRING ',' NUMBER ',' STRING ',' style ',' NUMBER
|
||||
',' NUMBER ',' NUMBER ',' NUMBER
|
||||
{$$=create_generic_control($1,$3,$5,$7,$9,$11,$13,$15);}
|
||||
|
||||
font: FONT load_and_memoption STRING {$$=make_font(load_file($3));}
|
||||
|
||||
icon: ICON load_and_memoption STRING {$$=make_icon(load_file($3));}
|
||||
| ICON load_and_memoption raw_data {$$=make_icon($3);}
|
||||
|
||||
menu: MENU load_and_memoption menu_body {$$=make_menu($3);}
|
||||
/* menu items are collected in a gen_res and prefixed with the menu header*/
|
||||
menu_body: tBEGIN item_definitions tEND {$$=$2;}
|
||||
item_definitions: {$$=new_res();}
|
||||
| MENUITEM STRING ',' NUMBER item_options item_definitions
|
||||
{$$=add_menuitem($2,$4,$5,$6);}
|
||||
| MENUITEM SEPARATOR item_definitions
|
||||
{$$=add_menuitem("",0,0,$3);}
|
||||
| POPUP STRING item_options menu_body item_definitions
|
||||
{$$=add_popup($2,$3,$4,$5);}
|
||||
item_options: {$$=0;}
|
||||
| ',' CHECKED item_options {$$=$3|MF_CHECKED;}
|
||||
| ',' GRAYED item_options {$$=$3|MF_GRAYED;}
|
||||
| ',' HELP item_options {$$=$3|MF_HELP;}
|
||||
| ',' INACTIVE item_options {$$=$3|MF_DISABLED;}
|
||||
| ',' MENUBARBREAK item_options {$$=$3|MF_MENUBARBREAK;}
|
||||
| ',' MENUBREAK item_options {$$=$3|MF_MENUBREAK;}
|
||||
|
||||
rcdata: RCDATA load_and_memoption raw_data {$$=make_raw($3);}
|
||||
|
||||
raw_data: tBEGIN raw_elements tEND {$$=$2;}
|
||||
raw_elements: SINGLE_QUOTED {$$=hex_to_raw($1,new_res());}
|
||||
| NUMBER {$$=int_to_raw($1,new_res());}
|
||||
| SINGLE_QUOTED raw_elements {$$=hex_to_raw($1,$2);}
|
||||
| NUMBER ',' raw_elements {$$=int_to_raw($1,$3);}
|
||||
|
||||
stringtable: STRINGTABLE load_and_memoption tBEGIN strings tEND
|
||||
{$$=$4;}
|
||||
strings: {$$=0;}|
|
||||
NUMBER STRING strings {$$=0;}
|
||||
|
||||
versioninfo: VERSIONINFO NOT_SUPPORTED {$$=0;}
|
||||
|
||||
/* NOT x | NOT y | a | b means (a|b)& ~x & ~y
|
||||
NOT is used to disable default styles */
|
||||
style: NUMBER {$$=new_style();$$->or=$1;}
|
||||
| NOT NUMBER {$$=new_style();$$->and=~($2);}
|
||||
| '(' style ')' {$$=$2;}
|
||||
| style '|' style {$$=$1;$$->or|=$3->or;$$->and&=$3->and;}
|
||||
%%
|
||||
int yyerror(char *s)
|
||||
{
|
||||
puts(s);
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ END
|
|||
|
||||
SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 213, 179
|
||||
STYLE DS_LOCALEDIT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "About X"
|
||||
CAPTION "About %s"
|
||||
FONT 10, "System"
|
||||
{
|
||||
DEFPUSHBUTTON "OK", 1, 86, 160, 40, 14
|
||||
|
|
|
@ -29,7 +29,7 @@ END
|
|||
|
||||
SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 213, 179
|
||||
STYLE DS_LOCALEDIT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION ""
|
||||
CAPTION "Info über %s"
|
||||
FONT 10, "System"
|
||||
{
|
||||
DEFPUSHBUTTON "OK", 1, 86, 160, 40, 14
|
||||
|
|
|
@ -29,7 +29,7 @@ END
|
|||
|
||||
SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 213, 179
|
||||
STYLE DS_LOCALEDIT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Om X"
|
||||
CAPTION "Om %s"
|
||||
FONT 10, "System"
|
||||
{
|
||||
DEFPUSHBUTTON "OK", 1, 86, 160, 40, 14
|
||||
|
|
|
@ -19,7 +19,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ build tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak build tmp_make
|
||||
|
||||
distclean: clean
|
||||
rm Makefile
|
||||
|
|
|
@ -974,21 +974,19 @@ static void BuildCall32LargeStack(void)
|
|||
printf( "\tpushl %%ebp\n" );
|
||||
printf( "\tmovl %%esp,%%ebp\n" );
|
||||
|
||||
/* Retrieve the original 32-bit stack pointer */
|
||||
|
||||
printf( "\tmovl " PREFIX "IF1632_Original32_esp, %%eax\n" );
|
||||
printf( "\torl %%eax,%%eax\n" );
|
||||
printf( "\tje 0f\n" );
|
||||
|
||||
/* Save registers */
|
||||
|
||||
printf( "\tpushl %%ecx\n" );
|
||||
printf( "\tpushl %%esi\n" );
|
||||
printf( "\tpushl %%edi\n" );
|
||||
|
||||
/* Switch to the new stack */
|
||||
/* Retrieve the original 32-bit stack pointer and switch to it if any */
|
||||
|
||||
printf( "\tmovl " PREFIX "IF1632_Original32_esp, %%eax\n" );
|
||||
printf( "\torl %%eax,%%eax\n" );
|
||||
printf( "\tje 0f\n" );
|
||||
printf( "\tmovl %%eax,%%esp\n" );
|
||||
printf( "0:\n" );
|
||||
|
||||
/* Transfer the arguments */
|
||||
|
||||
|
@ -1016,29 +1014,8 @@ static void BuildCall32LargeStack(void)
|
|||
printf( "\tpopl %%edi\n" );
|
||||
printf( "\tpopl %%esi\n" );
|
||||
printf( "\tpopl %%ecx\n" );
|
||||
|
||||
printf( "\tpopl %%ebp\n" );
|
||||
printf( "\tret\n" );
|
||||
|
||||
/* We get here if IF1632_Original32_esp is 0, i.e. we have not */
|
||||
/* switched to another 32-bit stack yet. */
|
||||
|
||||
printf( "0:\n" );
|
||||
|
||||
/* Move the return address up the stack */
|
||||
|
||||
printf( "\tmovl 4(%%ebp),%%eax\n" );
|
||||
printf( "\tmovl %%eax,12(%%ebp)\n" );
|
||||
|
||||
/* Restore ebp and remove old return address */
|
||||
|
||||
printf( "\tpopl %%ebp\n" );
|
||||
printf( "\taddl $4,%%esp\n" );
|
||||
|
||||
/* Now jump to the routine, leaving the original return address and */
|
||||
/* the arguments on the stack. */
|
||||
|
||||
printf( "\tret\n" );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ depend:
|
|||
mv tmp_make Makefile
|
||||
|
||||
clean:
|
||||
rm -f *.o \#*\# *~ tmp_make
|
||||
rm -f *.o \#*\# *~ *.bak tmp_make
|
||||
|
||||
distclean: clean
|
||||
rm Makefile
|
||||
|
|
|
@ -34,7 +34,7 @@ HCLASS CLASS_FindClassByName( SEGPTR name, WORD hinstance, CLASS **ptr )
|
|||
HCLASS class;
|
||||
CLASS * classPtr;
|
||||
|
||||
if (!(atom = LocalFindAtom( name ))) return 0;
|
||||
if (!(atom = GlobalFindAtom( name ))) return 0;
|
||||
|
||||
/* First search task-specific classes */
|
||||
|
||||
|
@ -128,7 +128,7 @@ ATOM RegisterClass( LPWNDCLASS class )
|
|||
newClass->wc.cbWndExtra = (class->cbWndExtra < 0) ? 0 : class->cbWndExtra;
|
||||
newClass->wc.cbClsExtra = classExtra;
|
||||
|
||||
newClass->atomName = LocalAddAtom( class->lpszClassName );
|
||||
newClass->atomName = GlobalAddAtom( class->lpszClassName );
|
||||
newClass->wc.lpszClassName = 0;
|
||||
|
||||
if (newClass->wc.style & CS_CLASSDC)
|
||||
|
@ -189,8 +189,7 @@ BOOL UnregisterClass( SEGPTR className, HANDLE hinstance )
|
|||
/* Delete the class */
|
||||
if (classPtr->hdce) DCE_FreeDCE( classPtr->hdce );
|
||||
if (classPtr->wc.hbrBackground) DeleteObject( classPtr->wc.hbrBackground );
|
||||
/*if (classPtr->wc.style & CS_GLOBALCLASS)*/ LocalDeleteAtom( classPtr->atomName );
|
||||
/*else DeleteAtom( classPtr->atomName );*/
|
||||
GlobalDeleteAtom( classPtr->atomName );
|
||||
if (HIWORD(classPtr->wc.lpszMenuName))
|
||||
USER_HEAP_FREE( LOWORD(classPtr->wc.lpszMenuName) );
|
||||
USER_HEAP_FREE( class );
|
||||
|
@ -270,7 +269,7 @@ int GetClassName(HWND hwnd, LPSTR lpClassName, short maxCount)
|
|||
if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
|
||||
if (!(classPtr = CLASS_FindClassPtr(wndPtr->hClass))) return 0;
|
||||
|
||||
return LocalGetAtomName(classPtr->atomName, lpClassName, maxCount);
|
||||
return GlobalGetAtomName(classPtr->atomName, lpClassName, maxCount);
|
||||
}
|
||||
|
||||
|
||||
|
@ -315,7 +314,7 @@ BOOL ClassNext( CLASSENTRY *pClassEntry )
|
|||
|
||||
pClassEntry->hInst = classPtr->wc.hInstance;
|
||||
pClassEntry->wNext = classPtr->hNext;
|
||||
LocalGetAtomName( classPtr->atomName, pClassEntry->szClassName,
|
||||
GlobalGetAtomName( classPtr->atomName, pClassEntry->szClassName,
|
||||
sizeof(pClassEntry->szClassName) );
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright 1993 Alexandre Julliard
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "gdi.h"
|
||||
#include "metafile.h"
|
||||
#include "stddebug.h"
|
||||
|
@ -24,12 +25,12 @@ void MAPPING_FixIsotropic( DC * dc )
|
|||
(dc->w.devCaps->vertRes * dc->w.WndExtY);
|
||||
if (xdim > ydim)
|
||||
{
|
||||
dc->w.VportExtX = dc->w.VportExtX * ydim / xdim;
|
||||
dc->w.VportExtX = dc->w.VportExtX * fabs( ydim / xdim );
|
||||
if (!dc->w.VportExtX) dc->w.VportExtX = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dc->w.VportExtY = dc->w.VportExtY * xdim / ydim;
|
||||
dc->w.VportExtY = dc->w.VportExtY * fabs( xdim / ydim );
|
||||
if (!dc->w.VportExtY) dc->w.VportExtY = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,15 +28,6 @@
|
|||
#define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
|
||||
|
||||
|
||||
/* used for passing message information when sending message */
|
||||
typedef struct {
|
||||
LONG lParam;
|
||||
WORD wParam;
|
||||
WORD wMsg;
|
||||
WORD hWnd;
|
||||
} msgstruct;
|
||||
|
||||
|
||||
extern BOOL TIMER_CheckTimer( LONG *next, MSG *msg,
|
||||
HWND hwnd, BOOL remove ); /* timer.c */
|
||||
|
||||
|
@ -146,8 +137,8 @@ static int MSG_FindMsg(MESSAGEQUEUE * msgQueue, HWND hwnd, int first, int last)
|
|||
{
|
||||
int i, pos = msgQueue->nextMessage;
|
||||
|
||||
dprintf_msg(stddeb,"MSG_FindMsg: hwnd=0x%04x, proc=%d\n",
|
||||
hwnd, curr_proc_idx);
|
||||
dprintf_msg(stddeb,"MSG_FindMsg: hwnd=0x%04x\n\n", hwnd );
|
||||
|
||||
if (!msgQueue->msgCount) return -1;
|
||||
if (!hwnd && !first && !last) return pos;
|
||||
|
||||
|
@ -436,6 +427,7 @@ static BOOL MSG_PeekHardwareMsg( MSG *msg, HWND hwnd, WORD first, WORD last,
|
|||
|
||||
for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
|
||||
{
|
||||
if (pos >= sysMsgQueue->queueSize) pos = 0;
|
||||
*msg = sysMsgQueue->messages[pos].msg;
|
||||
|
||||
/* Translate message */
|
||||
|
@ -455,7 +447,8 @@ static BOOL MSG_PeekHardwareMsg( MSG *msg, HWND hwnd, WORD first, WORD last,
|
|||
if (hwnd && (msg->hwnd != hwnd)) continue;
|
||||
if ((first || last) &&
|
||||
((msg->message < first) || (msg->message > last))) continue;
|
||||
if (GetWindowTask(msg->hwnd) != GetCurrentTask())
|
||||
if ((msg->hwnd != GetDesktopWindow()) &&
|
||||
(GetWindowTask(msg->hwnd) != GetCurrentTask()))
|
||||
continue; /* Not for this task */
|
||||
if (remove) MSG_RemoveMsg( sysMsgQueue, pos );
|
||||
return TRUE;
|
||||
|
@ -734,12 +727,16 @@ BOOL MSG_WaitXEvent( LONG maxWait )
|
|||
XEvent event;
|
||||
int fd = ConnectionNumber(display);
|
||||
|
||||
if (!XPending(display))
|
||||
if (!XPending(display) && (maxWait != -1))
|
||||
{
|
||||
FD_ZERO( &read_set );
|
||||
FD_SET( fd, &read_set );
|
||||
|
||||
timeout.tv_usec = (maxWait % 1000) * 1000;
|
||||
timeout.tv_sec = maxWait / 1000;
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
sigsetjmp(env_wait_x, 1);
|
||||
|
||||
stop_wait_op= CONT;
|
||||
|
||||
if (DDE_GetRemoteMessage()) {
|
||||
|
@ -747,10 +744,6 @@ BOOL MSG_WaitXEvent( LONG maxWait )
|
|||
;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
timeout.tv_usec = (maxWait % 1000) * 1000;
|
||||
timeout.tv_sec = maxWait / 1000;
|
||||
|
||||
stop_wait_op= STOP_WAIT_X;
|
||||
/* The code up to the next "stop_wait_op= CONT" must be reentrant */
|
||||
if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
|
||||
|
@ -760,17 +753,25 @@ BOOL MSG_WaitXEvent( LONG maxWait )
|
|||
} else {
|
||||
stop_wait_op= CONT;
|
||||
}
|
||||
|
||||
#else /* CONFIG_IPC */
|
||||
if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
|
||||
return FALSE; /* Timeout or error */
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
}
|
||||
|
||||
/* Process the event (and possibly others that occurred in the meantime) */
|
||||
do
|
||||
{
|
||||
if (DDE_GetRemoteMessage()) {
|
||||
while(DDE_GetRemoteMessage())
|
||||
;
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
if (DDE_GetRemoteMessage())
|
||||
{
|
||||
while(DDE_GetRemoteMessage()) ;
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
XNextEvent( display, &event );
|
||||
EVENT_ProcessEvent( &event );
|
||||
}
|
||||
|
@ -789,8 +790,10 @@ static BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last,
|
|||
MESSAGEQUEUE *msgQueue;
|
||||
LONG nextExp; /* Next timer expiration time */
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
DDE_TestDDE(hwnd); /* do we have dde handling in the window ?*/
|
||||
DDE_GetRemoteMessage();
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
if (first || last)
|
||||
{
|
||||
|
@ -974,8 +977,10 @@ BOOL PostMessage( HWND hwnd, WORD message, WORD wParam, LONG lParam )
|
|||
msg.pt.x = 0;
|
||||
msg.pt.y = 0;
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
if (DDE_PostMessage(&msg))
|
||||
return TRUE;
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
if (hwnd == HWND_BROADCAST) {
|
||||
dprintf_msg(stddeb,"PostMessage // HWND_BROADCAST !\n");
|
||||
|
@ -1026,7 +1031,6 @@ LONG SendMessage( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
|
|||
{
|
||||
WND * wndPtr;
|
||||
LONG ret;
|
||||
MSG DDE_msg;
|
||||
struct
|
||||
{
|
||||
LONG lParam;
|
||||
|
@ -1035,11 +1039,10 @@ LONG SendMessage( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
|
|||
WORD hWnd;
|
||||
} msgstruct = { lParam, wParam, msg, hwnd };
|
||||
|
||||
DDE_msg.hwnd = hwnd;
|
||||
DDE_msg.message = msg;
|
||||
DDE_msg.wParam = wParam;
|
||||
DDE_msg.lParam = lParam;
|
||||
#ifdef CONFIG_IPC
|
||||
MSG DDE_msg = { hwnd, msg, wParam, lParam };
|
||||
if (DDE_SendMessage(&DDE_msg)) return TRUE;
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
if (hwnd == HWND_BROADCAST)
|
||||
{
|
||||
|
@ -1080,7 +1083,9 @@ void WaitMessage( void )
|
|||
MESSAGEQUEUE *queue;
|
||||
LONG nextExp = -1; /* Next timer expiration time */
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
DDE_GetRemoteMessage();
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return;
|
||||
if ((queue->wPostQMsg) ||
|
||||
|
@ -1197,7 +1202,7 @@ LONG GetMessageExtraInfo(void)
|
|||
WORD RegisterWindowMessage( SEGPTR str )
|
||||
{
|
||||
dprintf_msg(stddeb, "RegisterWindowMessage: '%08lx'\n", str );
|
||||
return LocalAddAtom( str );
|
||||
return GlobalAddAtom( str );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -189,8 +189,10 @@ static void WIN_DestroyWindow( HWND hwnd )
|
|||
WND *wndPtr = WIN_FindWndPtr( hwnd );
|
||||
CLASS *classPtr = CLASS_FindClassPtr( wndPtr->hClass );
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
if (main_block)
|
||||
DDE_DestroyWindow(hwnd);
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
if (!wndPtr || !classPtr) return;
|
||||
WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
|
||||
|
|
2
wine.ini
2
wine.ini
|
@ -14,7 +14,7 @@ Path=c:\windows;c:\windows\system;e:\;e:\test;f:\
|
|||
SymbolTableFile=./wine.sym
|
||||
|
||||
[fonts]
|
||||
system=bitstream-courier
|
||||
system=*-helvetica
|
||||
mssansserif=*-helvetica
|
||||
msserif=*-times
|
||||
fixedsys=*-fixed
|
||||
|
|
Loading…
Add table
Reference in a new issue