Commit e2991ea7 authored by Alexandre Julliard's avatar Alexandre Julliard

Release 950727

Sat Jul 22 22:39:09 IDT 1995 Michael Veksler <e1678223@tochnapc2.technion.ac.il> * [ipc/*] New directory. This directory contains the new inter-wine communications support. It enables DDE protocols between two wine instances. Currently it is limited to DDE, but can be enhanced to support OLE between 2 different wine instances. This is very important for libwine.a DDE/OLE support. * [tools/ipcl] A script to delete garbage IPC handles (shared memory, semaphores and message queues). The current inter-wine communication is not perfect, and sometimes leaves garbage behind. * [if1632/relay.c] [include/atom.h] [include/global.h] [loader/selector.c] [loader/task.c] [loader/module.c] [loader/signal.c] [memory/global.c] [misc/atom.c] [windows/class.c] [windows/message.c] [windows/win.c] [Imakefile] Hooks for inter-wine DDE support, current Global.*Atom functions renamed to Local.*Atom since Global.*Atom are used for Inter-Wine DDE communication. (The first call to these functions sets up the IPC structures - which otherwise cause unneeded overhead. Mon Jul 17 19:55:21 1995 Alexandre Julliard <julliard@sunsite.unc.edu> * [controls/menu.c] Don't crash if a NULL string is passed to menu functions. * [memory/selector.c] We now use a bit in ldt_flags_copy to indicate free LDT entries. Fixed a bug in SELECTOR_ReallocBlock that could cause it to overwrite valid LDT entries when growing a block. * [miscemu/instr.c] Emulate int xx instruction by storing the interrupt vector in CS:IP and returning directly. This allows a program to install an interrupt vector. * [windows/win.c] Added function WIN_GetTopParent to get the top-level parent of a window. Sun Jul 16 18:17:17 1995 Gregory Trubetskoy <grisha@mira.com> * [loader/resource.c] Added LoadIconHandler. It doesn't do anything yet, but now you can use borland help files with winhelp.exe. Sun Jul 16 11:58:45 1995 Anand Kumria <akumria@ozemail.com.au> * [misc/main.c] Fixed to return 386 Enhanced mode correctly. Also return the same type of CPU, for both Enhanced and Standard mode, namely a 386. Sun Jul 16 00:02:04 1995 Martin von Loewis <loewis@informatik.hu-berlin.de> * [Configure] [include/options.h] [include/wineopts.h] [misc/main.c][misc/spy.c] Removed support of spy file. Redirected spy messages to stddeb. Removed -spy option. Added -debugmsg +spy option. * [debugger/dbg.y][debugger/debug.l] Enabled segmented addresses (seg:offs) for break and x commands. * [if1632/gdi.spec] [objects/region.c] [windows/graphics.c] [include/region.h] FrameRgn, REGION_FrameRgn: New functions * [if1632/kernel.spec] IsWinOldApTask: Return false * [if1632/mouse.spec] CplApplet: Removed * [if1632/user.spec] [windows/win.c] ShowOwnedPopups: New function * [if1632/winsock.spec] [misc/winsocket.c] inet_addr, select: New prototypes in relay code Fixed memory layout for netdb functions (getXbyY). WINSOCK_ioctlsocket: Translated FIONREAD, FIONBIO, and FIOASYNC * [objects/clipping.c] RectVisible: Fixed call to LPToDP * [rc/winerc.c] main: Removed extra argument to getopt for Linux. Tue Jul 11 00:14:41 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de> * [controls/listbox.c] Yet another fix for ListBoxDirectory(). * [loader/module.c] [if1632/kernel.spec] Make GetModuleHandle() accept instance handles as parameter. * [if1632/relay.c] [loader/task.c] Put a magic cookie at the bottom of the 32 bit stack, and check on each return from a 32 bit function whether it's still there. Complain if it's not. * [if1632/user.spec] Wrong entry for CloseDriver(). * [misc/dos_fs.c] [loader/task.c] [include/dos_fs.h] [misc/file.c] [miscemu/int21.c] Large parts of dos_fs.c simplified. Changed it to use one current drive/directory per task, which is set to the module path on task creation. Prevent CorelPaint from closing stdin. open() with O_CREAT set must be passed three parameters. DOS FindFirst()/FindNext() could crash when FA_LABEL was set. Fixed, it's in DOS_readdir() now. * [misc/profile.c] Some badly written software (Lotus Freelance Graphics) passes a bogus size parameter that caused Wine to write off the end of a segment. Fixed. (It's probably too paranoid now.) * [multimedia/mmsystem.c] [multimedia/time.c] [multimedia/joystick.c] [multimedia/Imakefile] [if1632/winprocs.spec] 16 bit entry point for MMSysTimeCallback. Split off time.c and joystick.c from mmsystem.c. * [objects/dib.c] GetDIBits(): call XGetImage() via CallTo32_LargeStack. * [windows/cursor.c] DestroyCursor(): do nothing for builtin cursors. * [windows/mdi.c] Half of WM_MDISETMENU implemented. * [windows/win.c] EnumWindows() and EnumTaskWindows() never enumerated any windows. Fixed. * [windows/*.c] Fixed GetParent() to return correct values for owned windows. * [windows/message.c] Don't try to activate disabled top-level windows. * [windows/nonclient.c] Work around a bug in gcc-2.7.0. * [tools/build.c] [include/stackframe.h] [memory/global.c] [loader/task.c] [memory/selector.c] Some Visual Basic programs (and possibly others, too) expect ES to be preserved by a call to an API function, so we have to save it. In GlobalFree() and FreeSelector(), we must clear CURRENT_STACK16->es to prevent segfaults if ES contained the selector to be freed. Sun Jul 9 20:21:20 1995 Jon Tombs <jon@gtex02.us.es> * [*/*] Added missing prototypes to header files and relevant includes to reduce compile time warnings. Sun Jul 9 18:32:56 1995 Michael Patra <micky@marie.physik.tu-berlin.de> * [configure.in] [include/config.h] [*/Makefile.in] New configuration scheme based on autoconf. Sat Jul 8 14:12:45 1995 Morten Welinder <terra+@cs.cmu.edu> * [miscemu/ioports.c] Revamp to have only one in- and one out- variant, both really implemented. * [miscemu/instr.c] INSTR_EmulateInstruction: Use new ioport interface. Implement string io. Correct instruction pointer for 32-bit code. * [include/miscemu.h] Update port function prototypes. * [include/registers.h] Defined FS and GS. Sat Jul 8 13:38:54 1995 Hans de Graaff <graaff@twi72.twi.tudelft.nl> * [misc/dos_fs.c] ChopOffSlash(): A path consisting off a single slash is left intact, and multiple slashes are all removed.
parent ded3038c
This is release 950706 of Wine the MS Windows emulator. This is still a
This is release 950727 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.
WHAT'S NEW with Wine-950706: (see ChangeLog for details)
- Built-in debugger supports single-stepping (please test it on *BSD).
- Winelib should compile again.
- More OLE2 functions.
WHAT'S NEW with Wine-950727: (see ChangeLog for details)
- New configuration scheme based on autoconf (please test it).
- DDE communication between separate Wine processes.
- Lots of file handling fixes.
- Fixes to built-in WINSOCK.DLL.
- 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-950706.tar.gz
tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950706.tar.gz
ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950706.tar.gz
ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950706.tar.gz
aris.com:/pub/linux/ALPHA/Wine/development/Wine-950706.tar.gz
sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950727.tar.gz
tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950727.tar.gz
ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950727.tar.gz
ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950727.tar.gz
aris.com:/pub/linux/ALPHA/Wine/development/Wine-950727.tar.gz
It should also be available from any site that mirrors tsx-11 or sunsite.
......
----------------------------------------------------------------------
Wed Jul 5 19:06:35 1995 Alexandre Julliard <alex@numenor>
Sat Jul 22 22:39:09 IDT 1995 Michael Veksler <e1678223@tochnapc2.technion.ac.il>
* [ipc/*]
New directory. This directory contains the new inter-wine
communications support. It enables DDE protocols between two wine
instances. Currently it is limited to DDE, but can be enhanced to
support OLE between 2 different wine instances. This is very
important for libwine.a DDE/OLE support.
* [tools/ipcl]
A script to delete garbage IPC handles (shared memory, semaphores
and message queues). The current inter-wine communication is not
perfect, and sometimes leaves garbage behind.
* [if1632/relay.c] [include/atom.h] [include/global.h]
[loader/selector.c] [loader/task.c] [loader/module.c]
[loader/signal.c] [memory/global.c] [misc/atom.c]
[windows/class.c] [windows/message.c] [windows/win.c]
[Imakefile]
Hooks for inter-wine DDE support, current Global.*Atom functions
renamed to Local.*Atom since Global.*Atom are used for Inter-Wine
DDE communication. (The first call to these functions sets up the
IPC structures - which otherwise cause unneeded overhead.
Mon Jul 17 19:55:21 1995 Alexandre Julliard <julliard@sunsite.unc.edu>
* [controls/menu.c]
Don't crash if a NULL string is passed to menu functions.
* [memory/selector.c]
We now use a bit in ldt_flags_copy to indicate free LDT entries.
Fixed a bug in SELECTOR_ReallocBlock that could cause it to
overwrite valid LDT entries when growing a block.
* [miscemu/instr.c]
Emulate int xx instruction by storing the interrupt vector in
CS:IP and returning directly. This allows a program to install an
interrupt vector.
* [windows/win.c]
Added function WIN_GetTopParent to get the top-level parent of a
window.
Sun Jul 16 18:17:17 1995 Gregory Trubetskoy <grisha@mira.com>
* [loader/resource.c]
Added LoadIconHandler. It doesn't do anything yet, but now you
can use borland help files with winhelp.exe.
Sun Jul 16 11:58:45 1996 Anand Kumria <akumria@ozemail.com.au>
* [misc/main.c]
Fixed to return 386 Enhanced mode correctly. Also return the same
type of CPU, for both Enhanced and Standard mode, namely a 386.
Sun Jul 16 00:02:04 1995 Martin von Loewis <loewis@informatik.hu-berlin.de>
* [Configure] [include/options.h] [include/wineopts.h]
[misc/main.c][misc/spy.c]
Removed support of spy file. Redirected spy messages to stddeb.
Removed -spy option. Added -debugmsg +spy option.
* [debugger/dbg.y][debugger/debug.l]
Enabled segmented addresses (seg:offs) for break and x commands.
* [if1632/gdi.spec] [objects/region.c] [windows/graphics.c]
[include/region.h]
FrameRgn, REGION_FrameRgn: New functions
* [if1632/kernel.spec]
IsWinOldApTask: Return false
* [if1632/mouse.spec]
CplApplet: Removed
* [if1632/user.spec] [windows/win.c]
ShowOwnedPopups: New function
* [if1632/winsock.spec] [misc/winsocket.c]
inet_addr, select: New prototypes in relay code
Fixed memory layout for netdb functions (getXbyY).
WINSOCK_ioctlsocket: Translated FIONREAD, FIONBIO, and FIOASYNC
* [objects/clipping.c]
RectVisible: Fixed call to LPToDP
* [rc/winerc.c]
main: Removed extra argument to getopt for Linux.
Tue Jul 11 00:14:41 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* [controls/listbox.c]
Yet another fix for ListBoxDirectory().
* [loader/module.c] [if1632/kernel.spec]
Make GetModuleHandle() accept instance handles as parameter.
* [if1632/relay.c] [loader/task.c]
Put a magic cookie at the bottom of the 32 bit stack, and check on
each return from a 32 bit function whether it's still there. Complain
if it's not.
* [if1632/user.spec]
Wrong entry for CloseDriver().
* [misc/dos_fs.c] [loader/task.c] [include/dos_fs.h] [misc/file.c]
[miscemu/int21.c]
Large parts of dos_fs.c simplified. Changed it to use one
current drive/directory per task, which is set to the module path on
task creation.
Prevent CorelPaint from closing stdin.
open() with O_CREAT set must be passed three parameters.
DOS FindFirst()/FindNext() could crash when FA_LABEL was set. Fixed,
it's in DOS_readdir() now.
* [misc/profile.c]
Some badly written software (Lotus Freelance Graphics) passes a bogus
size parameter that caused Wine to write off the end of a segment.
Fixed. (It's probably too paranoid now.)
* [multimedia/mmsystem.c] [multimedia/time.c] [multimedia/joystick.c]
[multimedia/Imakefile] [if1632/winprocs.spec]
16 bit entry point for MMSysTimeCallback.
Split off time.c and joystick.c from mmsystem.c.
* [objects/dib.c]
GetDIBits(): call XGetImage() via CallTo32_LargeStack.
* [windows/cursor.c]
DestroyCursor(): do nothing for builtin cursors.
* [windows/mdi.c]
Half of WM_MDISETMENU implemented.
* [windows/win.c]
EnumWindows() and EnumTaskWindows() never enumerated any windows.
Fixed.
* [windows/*.c]
Fixed GetParent() to return correct values for owned windows.
* [windows/message.c]
Don't try to activate disabled top-level windows.
* [windows/nonclient.c]
Work around a bug in gcc-2.7.0.
* [tools/build.c] [include/stackframe.h] [memory/global.c]
[loader/task.c] [memory/selector.c]
Some Visual Basic programs (and possibly others, too) expect ES to be
preserved by a call to an API function, so we have to save it.
In GlobalFree() and FreeSelector(), we must clear CURRENT_STACK16->es
to prevent segfaults if ES contained the selector to be freed.
Sun Jul 9 20:21:20 1995 Jon Tombs <jon@gtex02.us.es>
* [*/*]
Added missing prototypes to header files and relevant includes
to reduce compile time warnings.
Sun Jul 9 18:32:56 1995 Michael Patra <micky@marie.physik.tu-berlin.de>
* [configure.in] [include/config.h] [*/Makefile.in]
New configuration scheme based on autoconf.
Sat Jul 8 14:12:45 1995 Morten Welinder <terra+@cs.cmu.edu>
* [miscemu/ioports.c]
Revamp to have only one in- and one out- variant, both really
implemented.
* [miscemu/instr.c]
INSTR_EmulateInstruction: Use new ioport interface. Implement
string io. Correct instruction pointer for 32-bit code.
* [include/miscemu.h]
Update port function prototypes.
* [include/registers.h]
Defined FS and GS.
Sat Jul 8 13:38:54 1995 Hans de Graaff <graaff@twi72.twi.tudelft.nl>
* [misc/dos_fs.c]
ChopOffSlash(): A path consisting off a single slash is left
intact, and multiple slashes are all removed.
----------------------------------------------------------------------
Wed Jul 5 19:06:35 1995 Alexandre Julliard <julliard@sunsite.unc.edu>
* [controls/scroll.c]
Fixed drawing bug that caused part of a non-client scroll bar
......
......@@ -106,7 +106,6 @@ then
prompt "Where is COM1" CF_Com1 '/dev/cua0'
prompt "Where is COM2" CF_Com2 '/dev/cua1'
prompt "Where is LPT1" CF_Lpt1 '/dev/lp0'
prompt "Log messages to which file (CON = stdout)" CF_File 'CON'
echo
sed -n -e 's/^ *\"\(WM_[A-Z0-9]*\)\".*/\1/p' < misc/spy.c | \
......@@ -147,7 +146,6 @@ Com2=$CF_Com2
Lpt1=$CF_Lpt1
[spy]
File=$CF_File
Exclude=$CF_Exclude
EOF
......
......@@ -7,13 +7,6 @@ CC = gcc -D__FreeBSD__
#endif
DEFINES = AutoDefines -DUSE_READLINE
#ifdef __ELF__
LD = /usr/i486-linuxaout/bin/ld -m i386linux
CDEBUGFLAGS = -O2 -Wall -b i486-linuxaout
ASFLAGS = -b i486-linuxaout
#else
CDEBUGFLAGS = -O2 -Wall
#endif
/*
* This is the second try at using Imakefiles. There are probably many
......@@ -33,6 +26,7 @@ CDEBUGFLAGS = -O2 -Wall
COMMONSUBDIRS = \
controls \
rc \
ipc \
loader \
misc \
multimedia \
......@@ -53,6 +47,7 @@ WINEDIR = $(LIBDIR)/wine
COMMONOBJS = \
controls/controls.o \
ipc/ipc.o \
loader/loader.o \
misc/misc.o \
multimedia/multimedia.o \
......@@ -122,4 +117,4 @@ etags::
distclean: clean
echo "/* autoconf.h generated automatically. Run Configure */" >autoconf.h
echo "#error You must run Configure before you can build the makefiles." >>autoconf.h
$(RM) `find . -name Makefile -print`
$(RM) config.* `find . -name Makefile -print`
# This Makefile understands the following targets:
#
# all (default): build wine
# clean: remove all intermediate files
# distclean: also remove all files created by configure
# countryclean: remove all files which have to be remade if
# a different LANGuage is selected
# winelibclean: remove all files which differ for the emulator
# and the library
# depend: create the dependencies
#
# Author: Michael Patra <micky@marie.physik.tu-berlin.de>
# <patra@itp1.physik.tu-berlin.de>
CC = @CC@
CFLAGS = @CFLAGS@
XINCL = @x_includes@
TOPSRC = @top_srcdir@
DIVINCL = -I$(TOPSRC)/include
XPM_LIB = -lXpm
XLIB = -lXext -lX11
XDIR = -L@x_libraries@
LDLIBS = -lm
LD = @LD@
LANG = @LANG@
LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
COMMONSUBDIRS = controls rc ipc loader misc multimedia objects windows
EMUSUBDIRS = tools debugger if1632 memory miscemu
LIBSUBDIRS = toolkit
COMMONOBJS = controls/controls.o ipc/ipc.o loader/loader.o misc/misc.o \
multimedia/multimedia.o objects/objects.o rc/rc.o \
windows/windows.o
EMUOBJS = debugger/debugger.o if1632/if1632.o memory/memory.o miscemu/miscemu.o
LIBOBJS = toolkit/toolkit.o
SUBDIRS = $(COMMONSUBDIRS) $(EMUSUBDIRS)
OBJS = $(COMMONOBJS) $(EMUOBJS)
all:
for i in $(SUBDIRS); do \
( cd $(TOPSRC)/$$i; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)' 'LANG=$(LANG)'); \
done
$(CC) -o wine $(OBJS) $(LDOPTIONS) $(XDIR) $(XPM_LIB) $(XLIB) $(LDLIBS)
nm wine | grep -v _compiled | sort >wine.sym
depend:
for i in $(SUBDIRS); do \
( cd $(TOPSRC)/$$i; $(MAKE) depend); \
done
clean:
for i in $(SUBDIRS); do \
( cd $(TOPSRC)/$$i; $(MAKE) clean); \
done
rm -f *.o \#*\# *~ wine wine.sym
distclean:
for i in $(SUBDIRS); do \
( cd $(TOPSRC)/$$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
countryclean:
for i in $(SUBDIRS); do \
( cd $(TOPSRC)/$$i; $(MAKE) countryclean); \
done
rm -f wine wine.sym
winelibclean:
for i in $(SUBDIRS); do \
( cd $(TOPSRC)/$$i; $(MAKE) winelibclean); \
done
/* @configure_input@ */
#define WINE_INI_GLOBAL @WINE_INI_GLOBAL@
#define AutoDefines @LANG@
This diff is collapsed. Click to expand it.
dnl Process this file with autoconf to produce a configure script.
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_PROG_MAKE_SET
AC_PROG_CC
AC_PATH_X
AC_PROG_YACC
AC_PROG_LEX
if test -n "$x_includes" ; then
x_includes="-I$x_includes"
fi
if test -n "$x_no" ; then
AXFILES='AXFILES='
fi
AC_SUBST(AXFILES)
AC_SUBST(x_includes)
AC_SUBST(x_libraries)
AC_SUBST(LIBOBJS)
LD=ld
LDCOMBINEFLAGS="-r"
AC_SUBST(LD)
AC_SUBST(LDCOMBINEFLAGS)
AC_CHECK_FUNCS(tcgetattr)
AC_CHECK_HEADERS(stdlib.h)
AC_HEADER_DIRENT()
AC_HEADER_STAT()
AC_C_CONST()
AC_TYPE_SIZE_T()
if test -z "${top_srcdir}"; then
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
if test `grep -c WINE_INI_GLOBAL ${TOP_SRCDIR}/autoconf.h` -ne 0; then
WINE_INI_GLOBAL=`grep WINE_INI_GLOBAL ${TOP_SRCDIR}/autoconf.h | tr ' ' '\n' | tail -1`
AC_MSG_RESULT(${WINE_INI_GLOBAL})
fi
fi
if test -z "${WINE_INI_GLOBAL}"; then
AC_MSG_RESULT(no)
fi
if test -z "${WINE_INI_GLOBAL}"; then
AC_MSG_CHECKING(for /usr/local/etc/wine.conf)
if test -f /usr/local/etc/wine.conf; then
AC_MSG_RESULT(yes)
WINE_INI_GLOBAL='"/usr/local/etc/wine.conf"'
else
AC_MSG_RESULT(no)
WINE_INI_GLOBAL="\"${TOP_SRCDIR}/wine.ini\""
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])
echo
echo "Configure finished. Do 'make depend; make' to compile Wine."
echo
dnl Local Variables:
dnl comment-start: "dnl "
dnl comment-end: ""
dnl comment-start-skip: "\\bdnl\\b\\s *"
dnl compile-command: "make configure config.h.in"
dnl End:
CC = @CC@
CFLAGS = @CFLAGS@
XINCL = @x_includes@
TOPSRC = @top_srcdir@
DIVINCL = -I$(TOPSRC)/include
LD = @LD@
LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
MODULE = controls
SRCS = button.c combo.c desktop.c edit.c listbox.c menu.c scroll.c \
static.c widgets.c
OBJS = $(SRCS:.c=.o)
.c.o:
$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
all: $(MODULE).o
$(MODULE).o: $(OBJS)
$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
depend:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
cp tmp_make Makefile
rm tmp_make
clean:
rm -f *.o \#*\# *~ tmp_make
distclean: clean
rm Makefile
countryclean:
NAMES = $(SRCS:.c=)
winelibclean:
for i in $(NAMES); do \
if test `grep -c WINELIB $$i.c` -ne 0; then \
rm $$i.o; \
fi; \
done
dummy:
### Dependencies:
......@@ -601,14 +601,12 @@ int ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPSTR filespec)
}
strcpy(temp,filespec);
tstr = strrchr(temp, '\\');
if (tstr == NULL)
DOS_SetDefaultDrive( drive );
else {
*tstr = 0;
filespec = tstr + 1;
if (tstr != NULL) {
*(tstr+1) = 0;
filespec += tstr - temp + 1;
if (!DOS_ChangeDir( drive, temp )) return 0;
DOS_SetDefaultDrive( drive );
}
DOS_SetDefaultDrive( drive );
dprintf_listbox(stddeb,"Changing directory to %c:%s, filemask is %s\n",
drive+'A', temp, filespec);
}
......
......@@ -1660,15 +1660,17 @@ BOOL InsertMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewIt
HANDLE hNewItems;
MENUITEM *lpitem, *newItems;
LPPOPUPMENU menu;
if (IS_STRING_ITEM(wFlags))
{
dprintf_menu(stddeb,"InsertMenu (%04X, %04X, %04X, %04X, '%s') !\n",
hMenu, nPos, wFlags, wItemID, lpNewItem);
}
{
dprintf_menu(stddeb,"InsertMenu (%04X, %04X, %04X, %04X, '%s') !\n",
hMenu, nPos, wFlags, wItemID,
lpNewItem ? lpNewItem : "(null)");
if (!lpNewItem) return FALSE;
}
else
dprintf_menu(stddeb,"InsertMenu (%04X, %04X, %04X, %04X, %p) !\n",
hMenu, nPos, wFlags, wItemID, lpNewItem);
dprintf_menu(stddeb,"InsertMenu (%04X, %04X, %04X, %04X, %p) !\n",
hMenu, nPos, wFlags, wItemID, lpNewItem);
/* Find where to insert new item */
......@@ -1816,8 +1818,11 @@ BOOL ModifyMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewIt
{
LPMENUITEM lpitem;
if (IS_STRING_ITEM(wFlags))
{
dprintf_menu(stddeb,"ModifyMenu (%04X, %04X, %04X, %04X, '%s') !\n",
hMenu, nPos, wFlags, wItemID, lpNewItem);
hMenu, nPos, wFlags, wItemID, lpNewItem ? lpNewItem : "(null)");
if (!lpNewItem) return FALSE;
}
else
dprintf_menu(stddeb,"ModifyMenu (%04X, %04X, %04X, %04X, %p) !\n",
hMenu, nPos, wFlags, wItemID, lpNewItem);
......
CC = @CC@
CFLAGS = @CFLAGS@
TOPSRC = @top_srcdir@
DIVINCL = -I$(TOPSRC)/include
BISON = @YACC@
FLEX = @LEX@
DIVDEFS = -DUSE_READLINE
COMPILE = $(CC) $(CFLAGS) $(DIVINCL) $(DIVDEFS)
LD = @LD@
LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
@SET_MAKE@
MODULE = debugger
SRCS = break.c db_disasm.c hash.c info.c registers.c stack.c
OBJS = $(SRCS:.c=.o) dbg.tab.o lex.yy.o
all: $(MODULE).o dbg.tab.o lex.yy.o
dbg.tab.c: dbg.y
$(BISON) -b dbg -d dbg.y
dbg.tab.h: dbg.y
$(BISON) -b dbg -d dbg.y
lex.yy.c: debug.l dbg.tab.h dbg.tab.h
$(FLEX) -8 -I debug.l
.c.o:
$(COMPILE) -c -o $*.o $<
$(MODULE).o: $(OBJS)
(cd readline; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)')
$(LD) $(LDCOMBINEFLAGS) $(OBJS) readline/readline.o -o $(MODULE).o
depend:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
cp tmp_make Makefile
rm tmp_make
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
distclean: clean
(cd readline; $(MAKE) distclean)
rm Makefile
countryclean:
NAMES = $(SRCS:.c=)
winelibclean:
for i in $(NAMES); do \
if test `grep -c WINELIB $$i.c` -ne 0; then \
rm $$i.o; \
fi; \
done
dbg.tab.o: dbg.tab.c
lex.yy.o: lex.yy.c
dummy:
### Dependencies:
......@@ -72,7 +72,8 @@ void mode_command(int);
| MODE NUM '\n' { mode_command($2); }
| ENABLE NUM '\n' { DEBUG_EnableBreakpoint( $2, TRUE ); }
| DISABLE NUM '\n' { DEBUG_EnableBreakpoint( $2, FALSE ); }
| BREAK '*' expr { DEBUG_AddBreakpoint( 0xffffffff, $3 ); }
| BREAK '*' expr '\n' { DEBUG_AddBreakpoint( 0xffffffff, $3 ); }
| BREAK '*' expr ':' expr '\n' { DEBUG_AddBreakpoint( $3, $5); }
| BREAK '\n' { DEBUG_AddBreakpoint( 0xffffffff, EIP ); }
| DELETE BREAK NUM '\n' { DEBUG_DelBreakpoint( $3 ); }
| BACKTRACE '\n' { DEBUG_BackTrace(); }
......@@ -90,6 +91,9 @@ x_command:
EXAM expr '\n' { examine_memory( 0xffffffff, $2, 1, 'x'); }
| EXAM FORMAT expr '\n' { examine_memory( 0xffffffff, $3,
$2 >> 8, $2 & 0xff ); }
| EXAM expr ':' expr '\n' { examine_memory( $2, $4, 1, 'x' ); }
| EXAM FORMAT expr ':' expr'\n' { examine_memory( $3, $5,
$2 >> 8, $2 & 0xff ); }
print_command:
PRINT expr '\n' { examine_memory( 0, ((unsigned int) &$2 ), 1,'x'); }
......
......@@ -37,7 +37,7 @@ IDENTIFIER [_a-zA-Z\.~][_a-zA-Z0-9\.~]*
\n { syntax_error = 0; return '\n'; } /*Indicate end of command*/
[-+=()*] { return *yytext; }
[-+=()*:] { return *yytext; }
"0x"{HEXDIGIT}+ { sscanf(yytext, "%x", &yylval); return NUM; }
{DIGIT}+ { sscanf(yytext, "%d", &yylval); return NUM; }
......
......@@ -10,11 +10,6 @@
extern char * find_nearest_symbol( unsigned int seg, unsigned int addr );
void application_not_running()
{
fprintf(stderr,"Application not running\n");
}
void print_address( unsigned int segment, unsigned int addr, int addrlen )
{
char *name = find_nearest_symbol( segment, addr );
......
......@@ -2,12 +2,9 @@
MODULE = readline
YACC = yacc -b dbg -d
EXTRA_DEFINES= -DANSI_ARROWS -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT -DSYS_UNIX
EXTRA_DEFINES= -DANSI_ARROWS -DHAVE_TCGETATTR -DHIDE
SRCS = \
complete.c \
editline.c \
sysunix.c
......
CC = @CC@
CFLAGS = @CFLAGS@
XINCL = @x_includes@
TOPSRC = @top_srcdir@
DIVINCL = -I$(TOPSRC)/include
LD = @LD@
LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
DIVDEFS = -DHIDE -DANSI_ARROWS
MODULE = readline
SRCS = editline.c sysunix.c
OBJS = $(SRCS:.c=.o)
.c.o:
$(CC) -c $(DIVDEFS) $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
all: $(MODULE).o
$(MODULE).o: $(OBJS)
$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
depend:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
cp tmp_make Makefile
rm tmp_make
clean:
rm -f *.o \#*\# *~ tmp_make
distclean: clean
rm Makefile
countryclean:
NAMES = $(SRCS:.c=)
winelibclean:
for i in $(NAMES); do \
if test `grep -c WINELIB $$i.c` -ne 0; then \
rm $$i.o; \
fi; \
done
dummy:
### Dependencies:
/* $Revision: 1.3 $
**
** History and file completion functions for editline library.
*/
#include <stdlib.h>
#include "editline.h"
#if defined(NEED_STRDUP)
/*
** Return an allocated copy of a string.
*/
char *
strdup(p)
char *p;
{
char *new;
if ((new = NEW(char, strlen(p) + 1)) != NULL)
(void)strcpy(new, p);
return new;
}
#endif /* defined(NEED_STRDUP) */
/*
** strcmp-like sorting predicate for qsort.
*/
STATIC int
compare(p1, p2)
CONST void *p1;
CONST void *p2;
{
CONST char **v1;
CONST char **v2;
v1 = (CONST char **)p1;
v2 = (CONST char **)p2;
return strcmp(*v1, *v2);
}
/*
** Fill in *avp with an array of names that match file, up to its length.
** Ignore . and .. .
*/
STATIC int
FindMatches(dir, file, avp)
char *dir;
char *file;
char ***avp;
{
char **av;
char **new;
char *p;
DIR *dp;
DIRENTRY *ep;
SIZE_T ac;
SIZE_T len;
if ((dp = opendir(dir)) == NULL)
return 0;
av = NULL;
ac = 0;
len = strlen(file);
while ((ep = readdir(dp)) != NULL) {
p = ep->d_name;
if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')))
continue;
if (len && strncmp(p, file, len) != 0)
continue;
if ((ac % MEM_INC) == 0) {
if ((new = NEW(char*, ac + MEM_INC)) == NULL)
break;
if (ac) {
COPYFROMTO(new, av, ac * sizeof (char **));
DISPOSE(av);
}
*avp = av = new;
}
if ((av[ac] = strdup(p)) == NULL) {
if (ac == 0)
DISPOSE(av);
break;
}
ac++;
}
/* Clean up and return. */
(void)closedir(dp);
if (ac)
qsort(av, ac, sizeof (char **), compare);
return ac;
}
/*
** Split a pathname into allocated directory and trailing filename parts.
*/
STATIC int
SplitPath(path, dirpart, filepart)
char *path;
char **dirpart;
char **filepart;
{
static char DOT[] = ".";
char *dpart;
char *fpart;
if ((fpart = strrchr(path, '/')) == NULL) {
if ((dpart = strdup(DOT)) == NULL)
return -1;
if ((fpart = strdup(path)) == NULL) {
DISPOSE(dpart);
return -1;
}
}
else {
if ((dpart = strdup(path)) == NULL)
return -1;
dpart[fpart - path] = '\0';
if ((fpart = strdup(++fpart)) == NULL) {
DISPOSE(dpart);
return -1;
}
}
*dirpart = dpart;
*filepart = fpart;
return 0;
}
/*
** Attempt to complete the pathname, returning an allocated copy.
** Fill in *unique if we completed it, or set it to 0 if ambiguous.
*/
char *
rl_complete(pathname, unique)
char *pathname;
int *unique;
{
char **av;
char *dir;
char *file;
char *new;
char *p;
SIZE_T ac;
SIZE_T end;
SIZE_T i;
SIZE_T j;
SIZE_T len;
if (SplitPath(pathname, &dir, &file) < 0)
return NULL;
if ((ac = FindMatches(dir, file, &av)) == 0) {
DISPOSE(dir);
DISPOSE(file);
return NULL;
}
p = NULL;
len = strlen(file);
if (ac == 1) {
/* Exactly one match -- finish it off. */
*unique = 1;
j = strlen(av[0]) - len + 2;
if ((p = NEW(char, j + 1)) != NULL) {
COPYFROMTO(p, av[0] + len, j);
if ((new = NEW(char, strlen(dir) + strlen(av[0]) + 2)) != NULL) {
(void)strcpy(new, dir);
(void)strcat(new, "/");
(void)strcat(new, av[0]);
rl_add_slash(new, p);
DISPOSE(new);
}
}
}
else {
*unique = 0;
if (len) {
/* Find largest matching substring. */
for (i = len, end = strlen(av[0]); i < end; i++)
for (j = 1; j < ac; j++)
if (av[0][i] != av[j][i])
goto breakout;
breakout:
if (i > len) {
j = i - len + 1;
if ((p = NEW(char, j)) != NULL) {
COPYFROMTO(p, av[0] + len, j);
p[j - 1] = '\0';
}
}
}
}
/* Clean up and return. */
DISPOSE(dir);
DISPOSE(file);
for (i = 0; i < ac; i++)
DISPOSE(av[i]);
DISPOSE(av);
return p;
}
/*
** Return all possible completions.
*/
int
rl_list_possib(pathname, avp)
char *pathname;
char ***avp;
{
char *dir;
char *file;
int ac;
if (SplitPath(pathname, &dir, &file) < 0)
return 0;
ac = FindMatches(dir, file, avp);
DISPOSE(dir);
DISPOSE(file);
return ac;
}
......@@ -78,8 +78,8 @@ STATIC int OldPoint;
STATIC int Point;
STATIC int PushBack;
STATIC int Pushed;
FORWARD KEYMAP Map[33];
FORWARD KEYMAP MetaMap[16];
STATIC KEYMAP Map[33];
STATIC KEYMAP MetaMap[16];
STATIC SIZE_T Length;
STATIC SIZE_T ScreenCount;
STATIC SIZE_T ScreenSize;
......@@ -243,41 +243,6 @@ TTYinfo()
}
/*
** Print an array of words in columns.
*/
STATIC void
columns(ac, av)
int ac;
CHAR **av;
{
CHAR *p;
int i;
int j;
int k;
int len;
int skip;
int longest;
int cols;
/* Find longest name, determine column count from that. */
for (longest = 0, i = 0; i < ac; i++)
if ((j = strlen((char *)av[i])) > longest)
longest = j;
cols = TTYwidth / (longest + 3);
TTYputs((CHAR *)NEWLINE);
for (skip = ac / cols + 1, i = 0; i < skip; i++) {
for (j = i; j < ac; j += skip) {
for (p = av[j], len = strlen((char *)p), k = len; --k >= 0; p++)
TTYput(*p);
if (j + skip < ac)
while (++len < longest + 3)
TTYput(' ');
}
TTYputs((CHAR *)NEWLINE);
}
}
STATIC void
reposition()
......@@ -1026,71 +991,6 @@ end_line()
return CSstay;
}
/*
** Move back to the beginning of the current word and return an
** allocated copy of it.
*/
STATIC CHAR *
find_word()
{
static char SEPS[] = "#;&|^$=`'{}()<>\n\t ";
CHAR *p;
CHAR *new;
SIZE_T len;
for (p = &Line[Point]; p > Line && strchr(SEPS, (char)p[-1]) == NULL; p--)
continue;
len = Point - (p - Line) + 1;
if ((new = NEW(CHAR, len)) == NULL)
return NULL;
COPYFROMTO(new, p, len);
new[len - 1] = '\0';
return new;
}
STATIC STATUS
c_complete()
{
CHAR *p;
CHAR *word;
int unique;
STATUS s;
word = find_word();
p = (CHAR *)rl_complete((char *)word, &unique);
if (word)
DISPOSE(word);
if (p && *p) {
s = insert_string(p);
if (!unique)
(void)ring_bell();
DISPOSE(p);
return s;
}
return ring_bell();
}
STATIC STATUS
c_possible()
{
CHAR **av;
CHAR *word;
int ac;
word = find_word();
ac = rl_list_possib((char *)word, (char ***)&av);
if (word)
DISPOSE(word);
if (ac) {
columns(ac, av);
while (--ac >= 0)
DISPOSE(av[ac]);
DISPOSE(av);
return CSmove;
}
return ring_bell();
}
STATIC STATUS
accept_line()
{
......@@ -1335,7 +1235,7 @@ STATIC KEYMAP Map[33] = {
{ CTL('F'), fd_char },
{ CTL('G'), ring_bell },
{ CTL('H'), bk_del_char },
{ CTL('I'), c_complete },
{ CTL('I'), ring_bell },
{ CTL('J'), accept_line },
{ CTL('K'), kill_line },
{ CTL('L'), redisplay },
......@@ -1367,7 +1267,7 @@ STATIC KEYMAP MetaMap[16]= {
{ '.', last_argument },
{ '<', h_first },
{ '>', h_last },
{ '?', c_possible },
{ '?', ring_bell },
{ 'b', bk_word },
{ 'd', fd_kill_word },
{ 'f', fd_word },
......
......@@ -3,20 +3,17 @@
** Internal header file for editline library.
*/
#include <stdio.h>
#if defined(HAVE_STDLIB)
#include <stdlib.h>
#include <string.h>
#endif /* defined(HAVE_STDLIB) */
#if defined(SYS_UNIX)
#include "unix.h"
#endif /* defined(SYS_UNIX) */
#if defined(SYS_OS9)
#include "os9.h"
#endif /* defined(SYS_OS9) */
#include <sys/types.h>
#include <sys/stat.h>
#if !defined(SIZE_T)
#define SIZE_T unsigned int
#endif /* !defined(SIZE_T) */
#define CRLF "\r\n"
#define SIZE_T size_t
#define CONST const
typedef unsigned char CHAR;
......@@ -26,15 +23,6 @@ typedef unsigned char CHAR;
#define STATIC /* NULL */
#endif /* !defined(HIDE) */
#if !defined(CONST)
#if defined(__STDC__)
#define CONST const
#else
#define CONST
#endif /* defined(__STDC__) */
#endif /* !defined(CONST) */
#define MEM_INC 64
#define SCREEN_INC 256
......@@ -59,18 +47,3 @@ extern char *rl_complete();
extern int rl_list_possib();
extern void rl_ttyset();
extern void rl_add_slash();
#if !defined(HAVE_STDLIB)
extern char *getenv();
extern char *malloc();
extern char *realloc();
extern char *memcpy();
extern char *strcat();
extern char *strchr();
extern char *strrchr();
extern char *strcpy();
extern char *strdup();
extern int strcmp();
extern int strlen();
extern int strncmp();
#endif /* !defined(HAVE_STDLIB) */
......@@ -3,6 +3,7 @@
** Unix system-dependant routines for editline library.
*/
#include "editline.h"
#include "config.h"
#if defined(HAVE_TCGETATTR)
#include <termios.h>
......
/* $Revision: 1.2 $
**
** A "micro-shell" to test editline library.
** If given any arguments, commands aren't executed.
*/
#include <stdio.h>
#if defined(HAVE_STDLIB)
#include <stdlib.h>
#endif /* defined(HAVE_STDLIB) */
const char version_string[] = "4.321";
extern char *readline();
extern void add_history();
#if !defined(HAVE_STDLIB)
extern int chdir();
extern int free();
extern int strncmp();
extern int system();
extern void exit();
#endif /* !defined(HAVE_STDLIB) */
#if defined(NEED_PERROR)
void
perror(s)
char *s;
{
extern int errno;
(voidf)printf(stderr, "%s: error %d\n", s, errno);
}
#endif /* defined(NEED_PERROR) */
/* ARGSUSED1 */
int
main(ac, av)
int ac;
char *av[];
{
char *p;
int doit;
doit = ac == 1;
while ((p = readline("testit> ")) != NULL) {
(void)printf("\t\t\t|%s|\n", p);
if (doit)
if (strncmp(p, "cd ", 3) == 0) {
if (chdir(&p[3]) < 0)
perror(&p[3]);
}
else if (system(p) != 0)
perror(p);
add_history(p);
free(p);
}
exit(0);
/* NOTREACHED */
}
/* $Revision: 1.1 $
**
** Editline system header file for Unix.
*/
#define CRLF "\r\n"
#define FORWARD STATIC
#include <sys/types.h>
#include <sys/stat.h>
#if defined(USE_DIRENT)
#include <dirent.h>
typedef struct dirent DIRENTRY;
#else
#include <sys/dir.h>
typedef struct direct DIRENTRY;
#endif /* defined(USE_DIRENT) */
#if !defined(S_ISDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif /* !defined(S_ISDIR) */
CC = @CC@
CFLAGS = @CFLAGS@
XINCL = @x_includes@
TOPSRC = @top_srcdir@
DIVINCL = -I$(TOPSRC)/include
LD = @LD@
LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
BUILD = $(TOPSRC)/tools/build
@SET_MAKE@
MODULE = if1632
SRCS = callback.c relay.c relay32.c
DLLS16 = commdlg.spec compobj.spec ddeml.spec gdi.spec kernel.spec \
keyboard.spec mmsystem.spec mouse.spec ole2.spec ole2conv.spec \
ole2disp.spec ole2nls.spec ole2prox.spec olecli.spec olesvr.spec \
shell.spec sound.spec storage.spec stress.spec system.spec \
toolhelp.spec user.spec win87em.spec winprocs.spec winsock.spec
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)
.SUFFIXES: .spec
.c.o:
$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
.spec.S:
$(BUILD) -spec16 $< > $*.S
.S.o:
$(CC) -c -o $*.o $<
all: checkbuild $(MODULE).o
gdi32.c: gdi32.spec
$(BUILD) -spec32 gdi32.spec > gdi32.c
kernel32.c: kernel32.spec
$(BUILD) -spec32 kernel32.spec > kernel32.c
shell32.c: shell32.spec
$(BUILD) -spec32 shell32.spec > shell32.c
user32.c: user32.spec
$(BUILD) -spec32 user32.spec > user32.c
winprocs32.c: winprocs32.spec
$(BUILD) -spec32 winprocs32.spec > winprocs32.c
checkbuild:
(cd $(TOPSRC)/tools; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)')
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
call32.S: $(SFILES)
$(BUILD) -call32 `cat $(SFILES) | grep CallTo32_ | sed 's/.*CallTo32_\(.*\)/\1/' | sort | uniq` > call32.S
$(MODULE).o: $(OBJS)
$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
depend:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
$(CC) $(DIVINCL) $(XINCL) -MM callback.c relay32.c relay.c >> tmp_make
cp tmp_make Makefile
rm tmp_make
clean:
rm -f *.o \#*\# *~ *.S gdi32.c kernel32.c shell32.c user32.c winprocs32.c tmp_make
distclean: clean
rm Makefile
countryclean:
winelibclean:
dummy:
### Dependencies:
......@@ -47,7 +47,7 @@ id 3
38 pascal Escape(word word word ptr ptr) Escape
39 pascal16 RestoreDC(word s_word) RestoreDC
40 pascal16 FillRgn(word word word) FillRgn
41 stub FrameRgn
41 pascal16 FrameRgn(word word word word word) FrameRgn
42 pascal16 InvertRgn(word word) InvertRgn
43 pascal16 PaintRgn(word word) PaintRgn
44 pascal16 SelectClipRgn(word word) SelectClipRgn
......
......@@ -42,7 +42,7 @@ id 1
42 return DisableDos 0 0
45 pascal16 LoadModule(ptr ptr) LoadModule
46 pascal16 FreeModule(word) FreeModule
47 pascal16 GetModuleHandle(ptr) GetModuleHandle
47 pascal16 GetModuleHandle(segptr) WIN16_GetModuleHandle
48 pascal16 GetModuleUsage(word) GetModuleUsage
49 pascal16 GetModuleFileName(word ptr s_word) GetModuleFileName
50 pascal GetProcAddress(word segptr) GetProcAddress
......@@ -82,7 +82,7 @@ id 1
84 pascal _llseek(word long word) _llseek
85 pascal16 _lopen(ptr word) _lopen
86 pascal16 _lwrite(word ptr word) _lwrite
87 stub RESERVED5
87 pascal16 RESERVED5(ptr ptr) lstrcmp
88 pascal lstrcpy(segptr segptr) lstrcpy
89 pascal lstrcat(segptr segptr) lstrcat
90 pascal16 lstrlen(ptr) lstrlen
......@@ -146,7 +146,7 @@ id 1
155 pascal16 GetTaskDS() GetTaskDS
156 stub LimitEMSPages
157 return GetCurPID 4 0
158 stub IsWinOldApTask
158 return IsWinOldApTask 2 0
159 stub GlobalHandleNoRIP
160 stub EMSCopy
161 pascal16 LocalCountFree() LocalCountFree
......
......@@ -4,21 +4,21 @@ id 7
#1 pascal Inquire
#2 pascal Enable
#3 pascal Disable
4 pascal ToAscii(word word ptr ptr word) ToAscii
5 pascal AnsiToOem(ptr ptr) AnsiToOem
6 pascal OemToAnsi(ptr ptr) OemToAnsi
4 pascal16 ToAscii(word word ptr ptr word) ToAscii
5 pascal16 AnsiToOem(ptr ptr) AnsiToOem
6 pascal16 OemToAnsi(ptr ptr) OemToAnsi
#7 pascal SetSpeed
#100 pascal ScreenSwitchEnable
#126 pascal GetTableSeg
#127 pascal NewTable
128 pascal OemKeyScan(word) OemKeyScan
129 pascal VkKeyScan(byte) VkKeyScan
130 pascal GetKeyboardType(byte) GetKeyboardType
131 pascal MapVirtualKey(word word) MapVirtualKey
132 pascal GetKbCodePage() GetKbCodePage
133 pascal GetKeyNameText(long ptr word) GetKeyNameText
134 pascal AnsiToOemBuff(ptr ptr word) AnsiToOemBuff
135 pascal OemToAnsiBuff(ptr ptr word) OemToAnsiBuff
128 pascal OemKeyScan(word) OemKeyScan
129 pascal16 VkKeyScan(byte) VkKeyScan
130 pascal16 GetKeyboardType(byte) GetKeyboardType
131 pascal16 MapVirtualKey(word word) MapVirtualKey
132 pascal16 GetKbCodePage() GetKbCodePage
133 pascal16 GetKeyNameText(long ptr word) GetKeyNameText
134 pascal16 AnsiToOemBuff(ptr ptr word) AnsiToOemBuff
135 pascal16 OemToAnsiBuff(ptr ptr word) OemToAnsiBuff
#136 pascal EnableKbSysReq
#137 pascal GetBiosKeyProc
......@@ -6,5 +6,6 @@ id 13
3 stub DISABLE
4 stub MOUSEGETINTVECT
5 stub GETSETMOUSEDATA
6 stub CPLAPPLET
#Control Panel thinks this is implemented if it is available
#6 stub CPLAPPLET
7 stub POWEREVENTPROC
......@@ -8,6 +8,7 @@
#include "dlls.h"
#include "global.h"
#include "module.h"
#include "registers.h"
#include "stackframe.h"
#include "stddebug.h"
/* #define DEBUG_RELAY */
......@@ -80,7 +81,7 @@ BOOL RELAY_Init(void)
codesel = GLOBAL_CreateBlock( GMEM_FIXED, (void *)CALL16_Start,
(int)CALL16_End - (int)CALL16_Start,
0, TRUE, TRUE, FALSE );
0, TRUE, TRUE, FALSE, NULL );
if (!codesel) return FALSE;
/* Patch the return addresses for CallTo16 routines */
......@@ -97,7 +98,7 @@ BOOL RELAY_Init(void)
/***********************************************************************
* RELAY_DebugCall32
*/
void RELAY_DebugCall32( char *args )
void RELAY_DebugCall32( int func_type, char *args )
{
STACK16FRAME *frame;
struct dll_table_s *table;
......@@ -150,6 +151,13 @@ void RELAY_DebugCall32( char *args )
if (*args) printf( "," );
}
printf( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds );
if (func_type == 2) /* register function */
{
struct sigcontext_struct *context = (struct sigcontext_struct *)args16;
printf( " AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
AX, BX, CX, DX, SI, DI, ES, EFL );
}
}
......@@ -162,6 +170,9 @@ void RELAY_DebugReturn( int func_type, int ret_val )
struct dll_table_s *table;
char *name;
if (*(DWORD *)PTR_SEG_TO_LIN(IF1632_Stack32_base) != 0xDEADBEEF) {
fprintf(stderr, "Wine wrote past the end of the 32 bit stack. Please report this.\n");
}
if (!debugging_relay) return;
frame = CURRENT_STACK16;
......
......@@ -253,7 +253,7 @@ id 2
250 pascal16 GetMenuState(word word word) GetMenuState
251 pascal SendDriverMessage(word word long long) SendDriverMessage
252 pascal16 OpenDriver(ptr ptr long) OpenDriver
253 pascal CloseDriver(word word long) CloseDriver
253 pascal CloseDriver(word long long) CloseDriver
254 pascal16 GetDriverModuleHandle(word) GetDriverModuleHandle
255 pascal DefDriverProc(long word word long long) DefDriverProc
256 pascal16 GetDriverInfo(word ptr) GetDriverInfo
......@@ -266,7 +266,7 @@ id 2
262 pascal16 GetWindow(word word) GetWindow
263 pascal16 GetMenuItemCount(word) GetMenuItemCount
264 pascal16 GetMenuItemID(word word) GetMenuItemID
265 stub ShowOwnedPopups
265 pascal16 ShowOwnedPopups(word word) ShowOwnedPopups
266 pascal16 SetMessageQueue(word) SetMessageQueue
267 pascal16 ShowScrollBar(word word word) ShowScrollBar
268 pascal16 GlobalAddAtom(ptr) GlobalAddAtom
......@@ -371,7 +371,7 @@ id 2
word word word segptr) CreateWindowEx
454 pascal16 AdjustWindowRectEx(ptr long word long) AdjustWindowRectEx
455 stub GetIconId
456 stub LoadIconHandler
456 pascal16 LoadIconHandler(word word) LoadIconHandler
457 pascal16 DestroyIcon(word) DestroyIcon
458 pascal16 DestroyCursor(word) DestroyCursor
459 pascal DumpIcon(ptr ptr ptr ptr) DumpIcon
......
......@@ -15,7 +15,7 @@ id 8
7 pascal16 getsockopt(word word word ptr ptr) WINSOCK_getsockopt
8 pascal htonl(long) WINSOCK_htonl
9 pascal16 htons(word) WINSOCK_htons
10 pascal inet_addr(long) WINSOCK_inet_addr
10 pascal inet_addr(ptr) WINSOCK_inet_addr
11 pascal inet_ntoa(long) WINSOCK_inet_ntoa
12 pascal16 ioctlsocket(word long ptr) WINSOCK_ioctlsocket
13 pascal16 listen(word word) WINSOCK_listen
......@@ -23,7 +23,7 @@ id 8
15 pascal16 ntohs(word) WINSOCK_ntohs
16 pascal16 recv(word ptr word word) WINSOCK_recv
17 pascal16 recvfrom(word ptr word word ptr ptr) WINSOCK_recvfrom
18 pascal16 select(word ptr ptr ptr ptr word) WINSOCK_select
18 pascal16 select(word ptr ptr ptr ptr ptr) WINSOCK_select
19 pascal16 send(word ptr word word) WINSOCK_send
20 pascal16 sendto(word ptr word word ptr ptr) WINSOCK_sendto
21 pascal16 setsockopt(word word word ptr word) WINSOCK_setsockopt
......
......@@ -31,4 +31,14 @@ typedef struct
#define LocalAlign(flags,bytes) LocalAlloc((flags),(bytes))
#endif
ATOM LocalAddAtom( LPCSTR str );
ATOM LocalDeleteAtom( ATOM atom );
ATOM LocalFindAtom( LPCSTR str );
WORD LocalGetAtomName( ATOM atom, LPSTR buffer, short count );
ATOM LocalAddAtom( LPCSTR str );
ATOM LocalDeleteAtom( ATOM atom );
ATOM LocalFindAtom( LPCSTR str );
WORD LocalGetAtomName( ATOM atom, LPSTR buffer, short count );
#endif /* ATOM_H */
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: bit_array.h
* Purpose : manipulate array of bits,
* Important: operations may be considered atomic.
*
***************************************************************************
*/
#ifndef __WINE_BIT_ARRAY_H
#define __WINE_BIT_ARRAY_H
#define BITS_PER_BYTE (8)
#define BITS_PER_INT (sizeof(int)*BITS_PER_BYTE) /* must be power of 2 */
#define BYTE_LOG2 (3)
#if defined(INT_LOG2)
/* nothing to do, IN_LOG2 is ok */
#elif defined(__i386__)
# define INT_LOG2 (5)
#else
# error "Can't find log2 of BITS_PER_INT, please code it manualy"
#endif
typedef struct bit_array {
int bits; /* number of bits in the array */
unsigned int *array; /* Actual array data (Never NULL) */
} bit_array ;
bit_array *AssembleArray(bit_array *new_array, unsigned int *buff, int bits);
int ResetArray(bit_array *bits);
/* Return index of first free bit, or -1 on failure */
int VacantBit(bit_array *bits);
/* Return the value of bit 'i' */
int SampleBit(bit_array *bits, int i);
/* Assign 'val' to a bit no. 'i'. Return: old bit's value */
int AssignBit(bit_array *bits, int i, int val);
/*
** Allocate a free bit (==0) and make it used (==1).
** Return: allocated bit index, or -1 on failure.
*/
int AllocateBit(bit_array *bits);
#endif /* __WINE_BIT_ARRAY_H */
#undef HAVE_STDLIB_H
#undef HAVE_TCGETATTR
#undef HAVE_DIRENT_H
#undef HAVE_SYS_NDIR_H
#undef HAVE_NDIR_H
#undef STAT_MACROS_BROKEN
/*****************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: dde.h
* Purpose: dde declarations
*
*****************************************************************************
*/
#ifndef __WINE_DDE_H
#define __WINE_DDE_H
#include "wintypes.h"
#include "dde_proc.h"
#define WM_DDE_INITIATE 0x3E0
#define WM_DDE_TERMINATE 0x3E1
#define WM_DDE_ADVISE 0x3E2
#define WM_DDE_UNADVISE 0x3E3
#define WM_DDE_ACK 0x3E4
#define WM_DDE_DATA 0x3E5
#define WM_DDE_REQUEST 0x3E6
#define WM_DDE_POKE 0x3E7
#define WM_DDE_EXECUTE 0x3E8
#define WM_DDE_LAST WM_DDE_EXECUTE
#define WM_DDE_FIRST WM_DDE_INITIATE
/* DDEACK: wStatus in WM_DDE_ACK message */
struct tagDDEACK
{
WORD bAppReturnCode:8, reserved:6, fBusy:1, fAck:1;
};
typedef struct tagDDEACK DDEACK;
/* DDEDATA: hData in WM_DDE_DATA message */
struct tagDDEDATA
{
WORD unused:12, fResponse:1, fRelease:1, reserved:1, fAckReq:1,
cfFormat:16;
BYTE Value[1]; /* undetermined array */
};
typedef struct tagDDEDATA DDEDATA;
/* DDEADVISE: hOptions in WM_DDE_ADVISE message */
struct tagDDEADVISE
{
WORD reserved:14, fDeferUpd:1, fAckReq:1, cfFormat:16;
};
typedef struct tagDDEADVISE DDEADVISE;
/* DDEPOKE: hData in WM_DDE_POKE message. */
struct tagDDEPOKE
{
WORD unused:13, fRelease:1, fReserved:2, cfFormat:16;
BYTE Value[1]; /* undetermined array */
};
typedef struct tagDDEPOKE DDEPOKE;
#endif /* __WINE_DDE_H */
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: dde_atom.h
* Purpose : atom functionality for DDE
***************************************************************************
*/
#ifndef __WINE_DDE_ATOM_H
#define __WINE_DDE_ATOM_H
#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 )
*/
#endif __WINE_DDE_ATOM_H
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: dde_mem.h
* Purpose : shared DDE memory functionality for DDE
***************************************************************************
*/
#ifndef __WINE_DDE_MEM_H
#define __WINE_DDE_MEM_H
#include "wintypes.h"
#include "global.h"
#include "shm_block.h"
#define DDE_HANDLES 0x0400
#define is_dde_handle(block) ( (block) >= (1<<15) && (block) < (1<<15)+DDE_HANDLES )
typedef struct {
int shmid;
REL_PTR rel;
}DDE_HWND;
WORD DDE_SyncHandle(HGLOBAL handle, WORD sel);
void *DDE_malloc(unsigned int flags,unsigned long size, SHMDATA *shmdata);
HANDLE DDE_GlobalReAlloc(WORD,long,WORD);
HANDLE DDE_GlobalFree(WORD block);
void *DDE_AttachHandle(HGLOBAL handle, SEGPTR *segptr);
WORD DDE_GlobalHandleToSel( HGLOBAL handle );
int DDE_GlobalUnlock(int);
HANDLE DDE_GlobalSize(WORD);
HANDLE DDE_GlobalHandle(WORD);
HANDLE DDE_GlobalFlags(WORD);
#endif /* __WINE_DDE_MEM_H */
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: dde_proc.h
* Purpose : DDE signals and processes functionality for DDE
***************************************************************************
*/
#ifndef __WINE_DDE_PROC_H
#define __WINE_DDE_PROC_H
#include <setjmp.h>
#include "wintypes.h"
#include "windows.h"
#define DDE_PROCS 64
#define DDE_WINDOWS 64
struct _dde_proc {
int msg; /* message queue for this process */
int shmid; /* first shared memory block id. */
int sem; /* semaphore for fragment allocation */
int pid;
} ;
typedef struct _dde_proc *dde_proc;
extern sigjmp_buf env_wait_x;
enum stop_wait_op { /* The action to be taken upon SIGUSR2 */
CONT, /* Don't do anything */
STOP_WAIT_ACK, /* Use siglongjmp to stop wait_ack() */
STOP_WAIT_X /* siglongjmp to stop MSG_WaitXEvent() */
};
typedef struct {
WORD proc_idx; /* index into wine's process table */
HWND wnd; /* Window on the local proccess */
} WND_DATA;
extern enum stop_wait_op stop_wait_op;
extern int had_SIGUSR2;
extern int curr_proc_idx;
void stop_wait(int a); /* signal handler for SIGUSR2
(interrupts "select" system call) */
void dde_proc_init(dde_proc proc); /* init proc array */
void dde_proc_done(dde_proc proc); /* delete a proc entry */
void dde_proc_refresh(dde_proc proc); /* delete entry, if old junk */
void dde_proc_add(dde_proc proc); /* Add current proc to proc array */
void dde_msg_setup(int *msg_ptr);
int dde_reschedule();
void dde_wnd_setup(); /* setup Data structure of DDE windows */
/* Send ack. to hnd indicating that posted/sent msg. got to destination*/
void dde_proc_send_ack(HWND wnd, BOOL val);
BOOL DDE_PostMessage( MSG *msg);
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 /* __WINE_DDE_PROC_H */
......@@ -10,10 +10,9 @@ extern int DOS_GetDefaultDrive(void);
extern void DOS_SetDefaultDrive(int drive);
extern void ToUnix(char *s);
extern void ToDos(char *s);
extern void ChopOffSlash(char *string);
extern int DOS_DisableDrive(int drive);
extern int DOS_EnableDrive(int drive);
extern char *DOS_GetUnixFileName(char *dosfilename);
extern char *DOS_GetUnixFileName(const char *dosfilename);
extern char *DOS_GetDosFileName(char *unixfilename);
extern char *DOS_GetCurrentDir(int drive);
extern int DOS_ChangeDir(int drive, char *dirname);
......@@ -29,8 +28,6 @@ extern char *WinIniFileName(void);
extern struct dosdirent *DOS_opendir(char *dosdirname);
extern struct dosdirent *DOS_readdir(struct dosdirent *de);
extern void DOS_closedir(struct dosdirent *de);
extern void DOS_ExpandToFullPath(char *filename, int drive);
extern void DOS_ExpandToFullUnixPath(char *filename);
extern char *DOS_GetRedirectedDir(int drive);
extern void errno_to_doserr(void);
......
......@@ -9,9 +9,17 @@
#include "wintypes.h"
typedef struct
{
HGLOBAL handle;
WORD sel;
int shmid;
} SHMDATA;
extern HGLOBAL GLOBAL_CreateBlock( WORD flags, void *ptr, DWORD size,
HGLOBAL hOwner, BOOL isCode,
BOOL is32Bit, BOOL isReadOnly );
BOOL is32Bit, BOOL isReadOnly,
SHMDATA *shmdata);
extern BOOL GLOBAL_FreeBlock( HGLOBAL handle );
extern HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
BOOL isCode, BOOL is32Bit, BOOL isReadOnly );
......
......@@ -44,13 +44,13 @@ typedef struct
extern ldt_copy_entry ldt_copy[LDT_SIZE];
#define __AHSHIFT 3
#define __AHSHIFT 3 /* don't change! */
#define __AHINCR (1 << __AHSHIFT)
#ifndef WINELIB
#define SELECTOR_TO_ENTRY(sel) (((int)(sel) & 0xffff) >> __AHSHIFT)
#define ENTRY_TO_SELECTOR(i) ((i) ? (((int)(i) << __AHSHIFT) | 7) : 0)
#define IS_LDT_ENTRY_FREE(i) (!(ldt_copy[(i)].base || ldt_copy[(i)].limit))
#define IS_LDT_ENTRY_FREE(i) (!(ldt_flags_copy[(i)] & LDT_FLAGS_ALLOCATED))
#define IS_SELECTOR_FREE(sel) (IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel)))
#define GET_SEL_BASE(sel) (ldt_copy[SELECTOR_TO_ENTRY(sel)].base)
#define GET_SEL_LIMIT(sel) (ldt_copy[SELECTOR_TO_ENTRY(sel)].limit)
......@@ -59,6 +59,7 @@ extern ldt_copy_entry ldt_copy[LDT_SIZE];
#define SELECTOR_TO_ENTRY(sel) error.error
#define ENTRY_TO_SELECTOR(i) error.error
#define IS_LDT_ENTRY_FREE(i) error.error
#define IS_SELECTOR_FREE(sel) error.error
#define GET_SEL_BASE(sel) error.error
#define GET_SEL_LIMIT(sel) error.error
#endif
......@@ -83,6 +84,7 @@ extern unsigned char ldt_flags_copy[LDT_SIZE];
#define LDT_FLAGS_EXECONLY 0x04 /* Segment is execute-only (code) */
#define LDT_FLAGS_32BIT 0x08 /* Segment is 32-bit (code or stack) */
#define LDT_FLAGS_BIG 0x10 /* Segment is big (limit is in pages) */
#define LDT_FLAGS_ALLOCATED 0x80 /* Segment is allocated (no longer free) */
#define GET_SEL_FLAGS(sel) (ldt_flags_copy[SELECTOR_TO_ENTRY(sel)])
......
......@@ -4,31 +4,10 @@
#include "wintypes.h"
#include "wine.h"
extern BOOL INSTR_HandleInstruction( struct sigcontext_struct *context );
extern int do_int10(struct sigcontext_struct *);
extern int do_int13(struct sigcontext_struct *);
extern int do_int15(struct sigcontext_struct *);
extern int do_int16(struct sigcontext_struct *);
extern int do_int1a(struct sigcontext_struct *);
extern int do_int21(struct sigcontext_struct *);
extern int do_int25(struct sigcontext_struct *);
extern int do_int26(struct sigcontext_struct *);
extern int do_int2a(struct sigcontext_struct *);
extern int do_int2f(struct sigcontext_struct *);
extern int do_int31(struct sigcontext_struct *);
extern int do_int5c(struct sigcontext_struct *);
extern void inportb( struct sigcontext_struct *context );
extern void inport( struct sigcontext_struct *context, int long_op );
extern void outportb( struct sigcontext_struct *context );
extern void outport( struct sigcontext_struct *context, int long_op );
extern void inportb_abs( struct sigcontext_struct *context);
extern void inport_abs( struct sigcontext_struct *context, int long_op );
extern void outportb_abs( struct sigcontext_struct *context );
extern void outport_abs( struct sigcontext_struct *context, int long_op );
extern void IntBarf(int i, struct sigcontext_struct *context);
extern BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context );
extern DWORD inport( int port, int count );
extern void outport( int port, int count, DWORD value );
extern BOOL INT_Init(void);
extern SEGPTR INT_GetHandler( BYTE intnum );
......@@ -36,4 +15,11 @@ extern void INT_SetHandler( BYTE intnum, SEGPTR handler );
extern void INT21_Init(void);
#define INT_BARF(num) \
fprintf( stderr, "int%x: unknown/not implemented parameters:\n" \
"int%x: AX %04x, BX %04x, CX %04x, DX %04x, " \
"SI %04x, DI %04x, DS %04x, ES %04x\n", \
(num), (num), AX, BX, CX, DX, SI, DI, DS, ES )
#endif /* __WINE_MISCEMU_H */
......@@ -40,21 +40,23 @@ extern WORD ExtendedError;
extern struct DosDeviceStruct COM[MAX_PORTS];
extern struct DosDeviceStruct LPT[MAX_PORTS];
#define setword(a,b) *(BYTE*)(a) = (b) & 0xff; \
*((BYTE*)((a)+1)) = ((b)>>8) & 0xff;
#define setword(a,b) do { *(BYTE*)(a) = (b) & 0xff; \
*((BYTE*)((a)+1)) = ((b)>>8) & 0xff;\
} while(0)
#define setdword(a,b) *(BYTE*)(a) = (b) & 0xff; \
*((BYTE*)(a)+1) = ((b)>>8) & 0xff; \
*((BYTE*)(a)+2) = ((b)>>16) & 0xff; \
*((BYTE*)(a)+3) = ((b)>>24) & 0xff;
#define getword(a) (WORD) *(BYTE*)(a) + \
(*((BYTE*)(a) + 1) << 8)
#define getdword(a) (DWORD) (*(BYTE*)(a) + \
(*((BYTE*)(a) + 1) << 8) + \
(*((BYTE*)(a) + 2) << 16) + \
(*((BYTE*)(a) + 3) << 24))
#define setdword(a,b) do { *(BYTE*)(a) = (b) & 0xff; \
*((BYTE*)(a)+1) = ((b)>>8) & 0xff; \
*((BYTE*)(a)+2) = ((b)>>16) & 0xff; \
*((BYTE*)(a)+3) = ((b)>>24) & 0xff; \
} while(0)
#define getword(a) ( (WORD)*(BYTE*)(a) + \
((WORD)*((BYTE*)(a) + 1) << 8))
#define getdword(a) ( (DWORD)*(BYTE*)(a) + \
(DWORD)(*((BYTE*)(a) + 1) << 8) + \
(DWORD)(*((BYTE*)(a) + 2) << 16) + \
(DWORD)(*((BYTE*)(a) + 3) << 24))
/* dos file attributes */
......
......@@ -9,7 +9,6 @@
struct options
{
char * spyFilename;
char * desktopGeometry; /* NULL when no desktop */
char * programName; /* To use when loading resources */
int usePrivateMap;
......
#ifndef __WINE_PE_IMAGE_H
#define __WINE_PE_IMAGE_H
extern void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint);
extern int PE_unloadImage(struct w_files *wpnt);
extern int PE_StartProgram(struct w_files *wpnt);
extern void PE_InitDLL(struct w_files *wpnt);
......
/* $Id: prototypes.h,v 1.3 1993/07/04 04:04:21 root Exp root $
*/
/*
* Copyright Robert J. Amstadt, 1993
*/
#ifndef _WINE_PROTOTYPES_H
#define _WINE_PROTOTYPES_H
#include <sys/types.h>
#include "windows.h"
#ifndef WINELIB
/* loader/resource.c */
extern HBITMAP ConvertCoreBitmap( HDC hdc, BITMAPCOREHEADER * image );
extern HBITMAP ConvertInfoBitmap( HDC hdc, BITMAPINFO * image );
/* loader/signal.c */
extern void init_wine_signals(void);
/* loader/wine.c */
extern int _WinMain(int argc, char **argv);
/* misc/spy.c */
extern void SpyInit(void);
#endif /* WINELIB */
#endif /* _WINE_PROTOTYPES_H */
......@@ -18,5 +18,6 @@ typedef struct
extern BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj );
extern BOOL REGION_FrameRgn(HRGN dest,HRGN src,int x,int y);
#endif /* __WINE_REGION_H */
......@@ -37,6 +37,14 @@
#define ES (context->sc_es)
#define SS (context->sc_ss)
#ifdef linux
#define FS (context->sc_fs)
#define GS (context->sc_gs)
#else /* FIXME: are fs and gs supported under *BSD? */
#define FS 0
#define GS 0
#endif
#ifndef __FreeBSD__
#define EFL (context->sc_eflags)
#define FL (*(WORD*)&context->sc_eflags)
......
......@@ -17,6 +17,9 @@ extern SEGPTR NE_LockResource( HMODULE hModule, HGLOBAL handle );
extern HGLOBAL NE_AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size );
extern HGLOBAL NE_LoadResource( HMODULE hModule, HRSRC hRsrc );
extern HBITMAP ConvertCoreBitmap( HDC hdc, BITMAPCOREHEADER * image );
extern HBITMAP ConvertInfoBitmap( HDC hdc, BITMAPINFO * image );
struct ResourceTable
{
int id,type;
......
......@@ -2,6 +2,8 @@
* Shell Library definitions
*/
extern INT ShellAbout(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon);
#define ERROR_SUCCESS 0L
#define ERROR_BADDB 1L
#define ERROR_BADKEY 2L
......
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: shm_block.ch
* Purpose: treat a shared memory block.
***************************************************************************
*/
#ifndef __WINE_SHM_BLOCK_H
#define __WINE_SHM_BLOCK_H
#include <sys/shm.h>
#include "wintypes.h"
#define SEGSIZE 0x10000 /* 64 */
#define SHM_GRANULARITY SEGSIZE
#define SHM_MINBLOCK SHM_GRANULARITY
#define SHM_MAXBLOCK (((int)SHMMAX/(int)SHM_GRANULARITY)* \
SHM_GRANULARITY)
#define PTR2REL(block,ptr) (REL_PTR) ( (char *) (ptr) - (char *) (block) )
#define REL2PTR(block,rel) (void *) ( (char *) (block) + (rel) )
typedef int REL_PTR;
/* full info for each shm block. */
struct shm_block {
/* private */
int next_shm_id; /* IPC shm ID (for initial linking) */
/* public (read only) */
int size; /* size of the shm block */
int free; /* how much of the block is free */
int proc_idx; /* The index of the owner */
/* public - writable for shm_fragment */
REL_PTR free_list; /* first item in the free list */
};
/* used for mapping local attachments */
struct local_shm_map {
struct local_shm_map *next;
int shm_id;
int proc_idx;
/* 32 bit pointer to the beginning of the block */
struct shm_block *ptr;
};
extern struct local_shm_map *shm_map;
void shm_setup_block(struct shm_block *block, REL_PTR first, int size);
/* shm_create_block:
* allocate and setup a new block:
* first - first non header byte.
* size - block size (in bytes).
* shm_id- IPC shared memory ID.
*/
struct shm_block *shm_create_block(REL_PTR first, int size, int *shm_id);
/* shm_locate_block:
* locate existing block according to shm_id,
* Attach the block if needed. Assume the shm_id is wine's
* Set selectors also.
*/
struct shm_block *shm_locate_block(int shm_id, struct local_shm_map *map);
/* shm_locate_attached_block:
* locate existing block according to shm_id,
* Blocks are never attached.
* if proc_idx is not NULL, it will be set to owner's index.
* map - localy mapped info about block may be NULL;
*/
struct shm_block *shm_locate_attached_block(int shm_id,
struct local_shm_map *map);
/* shm_attach_block: attach existing shm block, setup selectors
* shm_id - id of the block to attach.
* proc_idx - if not -1, puts this data into local mapping
* map - localy mapped info about this block. (may be NULL)
* NOTE: same block can be attached many times
*/
struct shm_block *shm_attach_block(int shm_id, int proc_idx,
struct local_shm_map *map);
/* delete chain of shm blocks (pointing to each other */
void shm_delete_chain(int *shmid);
#endif /* __WINE_SHM_BLOCK_H */
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: shm_fragment.h
* Purpose: Data fragments and free list items. Allocate and free blocks.
***************************************************************************
*/
#ifndef __WINE_SHM_FRAGMENT_H
#define __WINE_SHM_FRAGMENT_H
#include "shm_block.h"
#define NIL ((int) 0)
/* memory fragment: used or free (when free - it's an item of "free list",
* when allocated it contains the data, and it's size)
*/
struct shm_fragment {
int size; /* fragment's size */
/* The type of info depends on fragment's status (free/allocated) */
union info {
int next; /* next free fragment */
char data[1]; /* the data */
} info;
};
/* setup first item in the free list */
void shm_FragmentInit(struct shm_block *block,REL_PTR first,int size);
/* allocate shm fragment. return: offset to data in fragment, or NULL */
REL_PTR shm_FragmentAlloc(struct shm_block *block, int size);
/* like shm_FragmentAlloc, returns pointer instead of offset */
char *shm_FragPtrAlloc(struct shm_block *block, int size);
/* free shm fragment - according to offset */
void shm_FragmentFree(struct shm_block *block, int ofs);
/* free shm fragment - according to pointer */
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 /* __WINE_SHM_FRAGMENT_H */
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: shm_main_blk.h
* Purpose: Main Wine's shared memory block
***************************************************************************
*/
#ifndef __WINE_SHM_MAIN_BLK_H
#define __WINE_SHM_MAIN_BLK_H
#include <sys/shm.h>
#include "shm_block.h"
#include "shm_semaph.h"
#include "dde_proc.h"
#include "dde_atom.h"
#include "dde_mem.h"
/*****************************************************************************
*
* main block object
*
*****************************************************************************
*/
#ifndef __inline__
#ifndef __GNUC__
#define __inline__
#endif /* __GNUC__ */
#endif /* __inline__ */
#define DDE_HANDLES_BIT_ARRAY_SIZE (DDE_HANDLES/sizeof(int)/8)
#define SHM_MAXID SHMSEG /* maximum shm blocks (Wine's limit) */
struct shm_main_block {
/* NOTE: "block" declaration must be the first */
struct shm_block block;
char magic[64]; /* magic string to identify the block */
int build_lock; /* =1 when data structure not stable yet */
shm_sem sem; /* semaphores for main_block integrity */
struct _dde_proc proc[DDE_PROCS]; /* information about processes */
REL_PTR atoms[DDE_ATOMS]; /* relative reference to global atoms */
/* Translation from global window handles to local handles */
WND_DATA windows[DDE_WINDOWS];
DDE_HWND handles[DDE_HANDLES];
/* bit array stating if a handle is free (bit=0), LSB in */
/* free_handles[0] refers handle 0x8000, the MSB refers 0x801F */
unsigned free_handles[DDE_HANDLES_BIT_ARRAY_SIZE];
};
extern struct shm_main_block *main_block;
int shm_init(void);
void shm_delete_all(int shm_id);
void DDE_mem_init();
int DDE_no_of_attached();
#define DDE_IPC_init() ( (main_block==NULL) ? (DDE_mem_init()) : 0 )
#endif /* __WINE_SHM_MAIN_BLK_H */
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: shm_semaph.h
* Purpose: Handle semaphores for shared memory operations.
***************************************************************************
*/
#ifndef __WINE_SHM_SEMAPH_H
#define __WINE_SHM_SEMAPH_H
/* IMPORTANT: If possible, restrict usage of these functions. */
typedef int shm_sem;
void shm_read_wait(shm_sem semid);
void shm_write_wait(shm_sem semid);
void shm_write_signal(shm_sem semid);
void shm_read_signal(shm_sem semid);
void shm_sem_init(shm_sem *semptr);
void shm_sem_done(shm_sem *semptr);
#endif /* __WINE_SHM_SEMAPH_H */
......@@ -19,6 +19,7 @@ typedef struct
{
WORD saved_ss; /* saved previous 16-bit stack */
WORD saved_sp;
WORD es;
WORD ds; /* 16-bit ds */
DWORD entry_point WINE_PACKED; /* entry point to call */
WORD ordinal_number; /* ordinal number of entry point */
......
......@@ -77,6 +77,7 @@
#ifdef DEBUG_NONE
#undef DEBUG_ACCEL
#undef DEBUG_ATOM
#undef DEBUG_BITBLT
#undef DEBUG_BITMAP
#undef DEBUG_CARET
......@@ -89,6 +90,7 @@
#undef DEBUG_COMM
#undef DEBUG_CURSOR
#undef DEBUG_DC
#undef DEBUG_DDE
#undef DEBUG_DIALOG
#undef DEBUG_DLL
#undef DEBUG_DOSFS
......@@ -137,6 +139,9 @@
#undef DEBUG_SCROLL
#undef DEBUG_SELECTOR
#undef DEBUG_SELECTORS
#undef DEBUG_SEM
#undef DEBUG_SHM
#undef DEBUG_SPY
#undef DEBUG_STRESS
#undef DEBUG_SYSCOLOR
#undef DEBUG_TASK
......@@ -150,6 +155,7 @@
#ifdef DEBUG_ALL
#define DEBUG_ACCEL
#define DEBUG_ATOM
#define DEBUG_BITBLT
#define DEBUG_BITMAP
#define DEBUG_CARET
......@@ -162,6 +168,7 @@
#define DEBUG_COMM
#define DEBUG_CURSOR
#define DEBUG_DC
#define DEBUG_DDE
#define DEBUG_DIALOG
#define DEBUG_DLL
#define DEBUG_DOSFS
......@@ -210,6 +217,9 @@
#define DEBUG_SCROLL
#define DEBUG_SELECTOR
#define DEBUG_SELECTORS
#define DEBUG_SEM
#define DEBUG_SHM
#define DEBUG_SPY
#define DEBUG_STRESS
#define DEBUG_SYSCOLOR
#define DEBUG_TASK
......
......@@ -13,6 +13,10 @@
#pragma pack(1)
#endif
extern BOOL TASK_Init(void);
extern void TASK_KillCurrentTask( int exitCode );
/* Process database (i.e. a normal DOS PSP) */
typedef struct
......
......@@ -10,6 +10,7 @@
#include "ldt.h"
#include "local.h"
extern BOOL USER_HeapInit(void);
/* USER local heap */
#ifdef WINELIB
......
......@@ -74,6 +74,7 @@ extern BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter );
extern HWND WIN_FindWinToRepaint( HWND hwnd );
extern void WIN_SendParentNotify( HWND hwnd, WORD event, LONG lParam );
extern BOOL WIN_CreateDesktopWindow(void);
extern HWND WIN_GetTopParent( HWND hwnd );
extern Display * display;
extern Screen * screen;
......
......@@ -2455,6 +2455,8 @@ Fa(DWORD,GetCurrentPosition,HDC,a)
Fa(DWORD,GetDCOrg,HDC,a)
Fa(DWORD,GetFreeSpace,WORD,a)
Fa(DWORD,GetHeapSpaces,HMODULE,a)
Fa(DWORD,GetSelectorBase,WORD,a)
Fa(DWORD,GetSelectorLimit,WORD,a)
Fa(DWORD,GetViewportExt,HDC,a)
Fa(DWORD,GetViewportOrg,HDC,a)
Fa(DWORD,GetWindowExt,HDC,a)
......@@ -2524,10 +2526,11 @@ Fa(LPSTR,GlobalLock,HGLOBAL,a)
Fa(LPSTR,LockResource,HANDLE,a)
Fa(SEGPTR,AnsiNext,SEGPTR,a)
Fa(SEGPTR,GlobalWire,HGLOBAL,a)
Fa(SEGPTR,WIN16_LockResource,HANDLE,a)
Fa(SEGPTR,WIN16_GlobalLock,HGLOBAL,a)
Fa(SEGPTR,WIN16_LockResource,HANDLE,a)
Fa(UINT,GDIRealizePalette,HDC,a)
Fa(UINT,RealizePalette,HDC,a)
Fa(WORD,AllocCStoDSAlias,WORD,a)
Fa(WORD,AllocDStoCSAlias,WORD,a)
Fa(WORD,AllocSelector,WORD,a)
Fa(WORD,AllocSelectorArray,WORD,a)
......@@ -2716,6 +2719,8 @@ Fb(WORD,SetMapMode,HDC,a,WORD,b)
Fb(WORD,SetPolyFillMode,HDC,a,WORD,b)
Fb(WORD,SetROP2,HDC,a,WORD,b)
Fb(WORD,SetRelAbs,HDC,a,WORD,b)
Fb(WORD,SetSelectorBase,WORD,a,DWORD,b)
Fb(WORD,SetSelectorLimit,WORD,a,DWORD,b)
Fb(WORD,SetStretchBltMode,HDC,a,WORD,b)
Fb(WORD,SetSystemPaletteUse,HDC,a,WORD,b)
Fb(WORD,SetTextAlign,HDC,a,WORD,b)
......@@ -2818,12 +2823,12 @@ Fc(INT,GetTextFace,HDC,a,INT,b,LPSTR,c)
Fc(INT,OpenFile,LPSTR,a,LPOFSTRUCT,b,WORD,c)
Fc(INT,_lread,INT,a,LPSTR,b,WORD,c)
Fc(INT,_lwrite,INT,a,LPCSTR,b,WORD,c)
Fc(LONG,_hread,INT,a,LPSTR,b,LONG,c)
Fc(LONG,_hwrite,INT,a,LPCSTR,b,LONG,c)
Fc(LONG,GetBitmapBits,HBITMAP,a,LONG,b,LPSTR,c)
Fc(LONG,SetBitmapBits,HBITMAP,a,LONG,b,LPSTR,c)
Fc(LONG,SetClassLong,HWND,a,short,b,LONG,c)
Fc(LONG,SetWindowLong,HWND,a,short,b,LONG,c)
Fc(LONG,_hread,INT,a,LPSTR,b,LONG,c)
Fc(LONG,_hwrite,INT,a,LPCSTR,b,LONG,c)
Fc(LONG,_llseek,INT,a,LONG,b,INT,c)
Fc(SEGPTR,lstrcpyn,SEGPTR,a,SEGPTR,b,WORD,c)
Fc(WORD,GetAtomName,ATOM,a,LPSTR,b,short,c)
......@@ -2831,6 +2836,7 @@ Fc(WORD,GetInternalWindowPos,HWND,a,LPRECT,b,LPPOINT,c)
Fc(WORD,GetMenuState,HMENU,a,WORD,b,WORD,c)
Fc(WORD,GetProfileInt,LPSTR,a,LPSTR,b,int,c)
Fc(WORD,GlobalGetAtomName,ATOM,a,LPSTR,b,short,c)
Fc(WORD,SelectorAccessRights,WORD,a,WORD,b,WORD,c)
Fc(WORD,SetClassWord,HWND,a,short,b,WORD,c)
Fc(WORD,SetWindowWord,HWND,a,short,b,WORD,c)
Fc(int,FillRect,HDC,a,LPRECT,b,HBRUSH,c)
......
/* WINEOPTS.H
*/
#ifndef WINEOPTS_H
#define WINEOPTS_H
#include <stdio.h>
FILE *SpyFp;
#endif /* WINEOPTS_H */
......@@ -7,13 +7,13 @@
#ifndef _WINSOCKAPI_
#define _WINSOCKAPI_
#include <windows.h>
#include <sys/types.h>
#include <sys/time.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "windows.h"
/*
* The new type to be used in all
......
#include "../Wine.tmpl"
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
OBJS = $(SRCS:.c=.o)
TEST_OBJS = $(TEST_SRCS:.c=.o)
WineRelocatableTarget($(MODULE),,$(OBJS))
DependTarget()
includes::
install::
CC = @CC@
CFLAGS = @CFLAGS@
XINCL = @x_includes@
TOPSRC = @top_srcdir@
DIVINCL = -I$(TOPSRC)/include
LD = @LD@
LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
MODULE = ipc
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
OBJS = $(SRCS:.c=.o)
.c.o:
$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
all: $(MODULE).o
$(MODULE).o: $(OBJS)
$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
depend:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
cp tmp_make Makefile
rm tmp_make
clean:
rm -f *.o \#*\# *~ tmp_make
distclean: clean
rm Makefile
countryclean:
NAMES = $(SRCS:.c=)
winelibclean:
for i in $(NAMES); do \
if test `grep -c WINELIB $$i.c` -ne 0; then \
rm $$i.o; \
fi; \
done
dummy:
### Dependencies:
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.
You can use "ipcl" perl script to remove junk IPC stuff.
You can use "ipcs" system program to find junk IPC stuff.
Michael
After shm_FragmentInit
{0x0020,0xffe0} [total free=ffe0]
0: After shm_FragmentAlloc(block, 0x010000) == NULL
{0x0020,0xffe0} [total free=ffe0]
1: After shm_FragmentAlloc(block, 0x003fdc) == 0x00c024
{0x0020,0xc000} [total free=c000]
2: After shm_FragmentAlloc(block, 0x003ffc) == 0x008024
{0x0020,0x8000} [total free=8000]
3: After shm_FragmentAlloc(block, 0x003ffc) == 0x004024
{0x0020,0x4000} [total free=4000]
4: After shm_FragmentAlloc(block, 0x003ffd) == NULL
{0x0020,0x4000} [total free=4000]
5: After shm_FragmentAlloc(block, 0x003ffc) == 0x000024
no free fragments [total free=0000]
6: Doing shm_FragmentFree(block, 0x000024)
{0x0020,0x4000} [total free=4000]
7: After shm_FragmentAlloc(block, 0x001bfc) == 0x002424
{0x0020,0x2400} [total free=2400]
8: After shm_FragmentAlloc(block, 0x0013fc) == 0x001024
{0x0020,0x1000} [total free=1000]
9: After shm_FragmentAlloc(block, 0x000ffc) == 0x000024
no free fragments [total free=0000]
10: Doing shm_FragmentFree(block, 0x000024)
{0x0020,0x1000} [total free=1000]
11: Doing shm_FragmentFree(block, 0x004024)
{0x0020,0x1000} {0x4020,0x4000} [total free=5000]
12: Doing shm_FragmentFree(block, 0x00c024)
{0x0020,0x1000} {0x4020,0x4000} {0xc020,0x3fe0} [total free=8fe0]
13: After shm_FragmentAlloc(block, 0x000ffc) == 0x000024
{0x4020,0x4000} {0xc020,0x3fe0} [total free=7fe0]
14: Doing shm_FragmentFree(block, 0x000024)
{0x0020,0x1000} {0x4020,0x4000} {0xc020,0x3fe0} [total free=8fe0]
15: After shm_FragmentAlloc(block, 0x000ffd) == 0x007014
{0x0020,0x1000} {0x4020,0x2ff0} {0xc020,0x3fe0} [total free=7fd0]
16: Doing shm_FragmentFree(block, 0x008024)
{0x0020,0x1000} {0x4020,0x2ff0} {0x8020,0x7fe0} [total free=bfd0]
17: Doing shm_FragmentFree(block, 0x001024)
{0x0020,0x2400} {0x4020,0x2ff0} {0x8020,0x7fe0} [total free=d3d0]
18: Doing shm_FragmentFree(block, 0x002424)
{0x0020,0x6ff0} {0x8020,0x7fe0} [total free=efd0]
19: Doing shm_FragmentFree(block, 0x007014)
{0x0020,0xffe0} [total free=ffe0]
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: bit_array.c
* Purpose : manipulate array of bits
* Portability: This is not completely portable, non CISC arcitectures
* Might not have atomic Clear/Set/Toggle bit. On those
* architectures semaphores should be used.
* Big Endian Concerns: This code is big endian compatible,
* but the byte order will be different (i.e. bit 0 will be
* located in byte 3).
***************************************************************************
*/
/*
** uncoment the following line to disable assertions,
** this may boost performance by up to 50%
*/
/* #define NDEBUG */
#ifndef NO_ASM
#define HAS_BITOPS
#endif
#include <stdio.h>
#include <assert.h>
#include "bit_array.h"
#if defined(HAS_BITOPS)
# include <asm/bitops.h>
#else
static __inline__ int clear_bit(int bit, int *mem);
static __inline__ int set_bit(int bit, int *mem);
#endif /* HAS_BITOPS */
#define INT_NR(bit_nr) ((bit_nr) >> INT_LOG2)
#define INT_COUNT(bit_count) INT_NR( bit_count + BITS_PER_INT - 1 )
#define BIT_IN_INT(bit_nr) ((bit_nr) & (BITS_PER_INT - 1))
#if !defined(HAS_BITOPS)
/* first_zero maps bytes value to the index of first zero bit */
static char first_zero[256];
static int arrays_initialized=0;
/*
** initialize static arrays used for bit operations speedup.
** Currently initialized: first_zero[256]
** set "arrays_initialized" to inidate that arrays where initialized
*/
static void initialize_arrays()
{
int i;
int bit;
for (i=0 ; i<256 ; i++) {
/* find the first zero bit in `i' */
for (bit=0 ; bit < BITS_PER_BYTE ; bit++)
/* break if the bit is zero */
if ( ( (1 << bit) & i )
== 0)
break;
first_zero[i]= bit;
}
arrays_initialized=1;
}
/*
** Find first zero bit in the integer.
** Assume there is at least one zero.
*/
static __inline__ int find_zbit_in_integer(unsigned int integer)
{
int i;
/* find the zero bit */
for (i=0 ; i < sizeof(int) ; i++, integer>>=8) {
int byte= integer & 0xff;
if (byte != 0xff)
return ( first_zero[ byte ]
+ (i << BYTE_LOG2) );
}
assert(0); /* never reached */
return 0;
}
/* return -1 on failure */
static __inline__ int find_first_zero_bit(unsigned *array, int bits)
{
unsigned int integer;
int i;
int bytes=INT_COUNT(bits);
if (!arrays_initialized)
initialize_arrays();
for ( i=bytes ; i ; i--, array++) {
integer= *array;
/* test if integer contains a zero bit */
if (integer != ~0U)
return ( find_zbit_in_integer(integer)
+ ((bytes-i) << INT_LOG2) );
}
/* indicate failure */
return -1;
}
static __inline__ int test_bit(int pos, unsigned *array)
{
unsigned int integer;
int bit = BIT_IN_INT(pos);
integer= array[ pos >> INT_LOG2 ];
return ( (integer & (1 << bit)) != 0
? 1
: 0 ) ;
}
/*
** The following two functions are x86 specific ,
** other processors will need porting
*/
/* inputs: bit number and memory address (32 bit) */
/* output: Value of the bit before modification */
static __inline__ int clear_bit(int bit, int *mem)
{
int ret;
__asm__("xor %1,%1
btrl %2,%0
adcl %1,%1"
:"=m" (*mem), "=&r" (ret)
:"r" (bit));
return (ret);
}
static __inline__ int set_bit(int bit, int *mem)
{
int ret;
__asm__("xor %1,%1
btsl %2,%0
adcl %1,%1"
:"=m" (*mem), "=&r" (ret)
:"r" (bit));
return (ret);
}
#endif /* !deined(HAS_BITOPS) */
/* AssembleArray: assemble an array object using existing data */
bit_array *AssembleArray(bit_array *new_array, unsigned int *buff, int bits)
{
assert(new_array!=NULL);
assert(buff!=NULL);
assert(bits>0);
assert((1 << INT_LOG2) == BITS_PER_INT); /* if fails, redefine INT_LOG2 */
new_array->bits=bits;
new_array->array=buff;
return new_array;
}
/* ResetArray: reset the bit array to zeros */
int ResetArray(bit_array *bits)
{
int i;
int *p;
assert(bits!=NULL);
assert(bits->array!=NULL);
for(i= INT_COUNT(bits->bits), p=bits->array; i ; p++, i--)
*p=0;
return 1;
}
/* VacantBit: find a vacant (zero) bit in the array,
* Return: Bit index on success, -1 on failure.
*/
int VacantBit(bit_array *bits)
{
int bit;
assert(bits!=NULL);
assert(bits->array!=NULL);
bit= find_first_zero_bit(bits->array, bits->bits);
if (bit >= bits->bits) /* failed? */
return -1;
return bit;
}
int SampleBit(bit_array *bits, int i)
{
assert(bits != NULL);
assert(bits->array != NULL);
assert(i >= 0 && i < bits->bits);
return ( test_bit(i,bits->array) != 0
? 1
: 0
);
}
/*
** Use "compare and exchange" mechanism to make sure
** that bits are not modified while "integer" value
** is calculated.
**
** This may be the slowest technique, but it is the most portable
** (Since most architectures have compare and exchange command)
*/
int AssignBit(bit_array *bits, int bit_nr, int val)
{
int ret;
assert(bits != NULL);
assert(bits->array != NULL);
assert(val==0 || val==1);
assert(bit_nr >= 0 && bit_nr < bits->bits);
if (val==0)
ret= clear_bit(BIT_IN_INT(bit_nr), &bits->array[ INT_NR(bit_nr) ]);
else
ret= set_bit(BIT_IN_INT(bit_nr), &bits->array[ INT_NR(bit_nr) ]);
return ( (ret!=0) ? 1 : 0);
}
/*
** Allocate a free bit (==0) and make it used (==1).
** This operation is guaranteed to resemble an atomic instruction.
**
** Return: allocated bit index, or -1 on failure.
**
** There is a crack between locating free bit, and allocating it.
** We assign 1 to the bit, test it was not '1' before the assignment.
** If it was, restart the seek and assign cycle.
**
*/
int AllocateBit(bit_array *bits)
{
int bit_nr;
int orig_bit;
assert(bits != NULL);
assert(bits->array != NULL);
do {
bit_nr= VacantBit(bits);
if (bit_nr == -1) /* No vacant bit ? */
return -1;
orig_bit = AssignBit(bits, bit_nr, 1);
} while (orig_bit != 0); /* it got assigned before we tried */
return bit_nr;
}
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "bit_array.h"
#define SIZE (8*sizeof(int)*3)
static bit_array array;
static int simple_array[SIZE];
static int bits;
int are_equal()
{
int i;
for (i=0 ; i < SIZE ; i++)
if (SampleBit(&array,i) != simple_array[i]){
printf("failed bit %d (packed=%d, simple=%d)\n", i,
SampleBit(&array,i), simple_array[i]);
return 0;
}
return 1;
}
int is_same_vacant()
{
int vacant;
for (vacant =0 ; simple_array[vacant]!=0 ; vacant++)
if ( vacant >= SIZE) {
vacant=-1;
break;
}
if ( VacantBit(&array) == vacant )
return 1;
else
return 0;
}
void assign_both(int bit_nr, int bit_val)
{
int old_bit= simple_array[bit_nr];
simple_array[bit_nr]= bit_val;
bits+=bit_val - old_bit;
assert(AssignBit(&array, bit_nr, bit_val) == old_bit);
assert(are_equal());
assert(is_same_vacant());
}
int main()
{
unsigned int integers[SIZE >> 5];
int i,j;
assert( AssembleArray(&array, integers, SIZE)
== &array);
ResetArray(&array);
for (i=0 ; i<SIZE ; i++)
simple_array[i]=0;
for (j=5 ; j ; j--) {
printf("\rleft %d\r",j);
for (i=0 ; VacantBit(&array) != -1 ; i++ ) {
if (i % 256 == 0) {
printf("left %d ",j);
printf("%3d up \r", bits);
fflush(stdout);
}
assign_both(rand() % SIZE,
(rand()% SIZE > bits ) ? 0 : 1 );
}
assign_both(rand() % SIZE, 1);
for (i=0 ; bits ; i++ ) {
if (i % 256 == 0) {
printf("left %d ",j);
printf("%3d down\r", bits);
fflush(stdout);
}
assign_both(rand() % SIZE,
(rand()% SIZE <= (SIZE-bits) ) ? 0 : 1 );
}
assign_both(rand() % SIZE, 0);
}
putchar('\n');
return 0;
}
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: dde_atom.c
* Purpose : atom functionality for DDE
*/
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "dde_atom.h"
#include "shm_main_blk.h"
#include "shm_fragment.h"
#include "stddebug.h"
#include "debug.h"
typedef struct
{
WORD count;
BYTE str[1];
} AtomData, *AtomData_ptr;
#define EMPTY 0 /* empty hash entry */
#define DELETED -1 /* deleted hash entry */
#define MIN_STR_ATOM 0xfc00
/* OFS2AtomData_ptr: extract AtomData_ptr from ofs */
#define OFS2AtomData_ptr(ofs) ((AtomData*)((int)&main_block->block+(ofs)))
/* OFS2AtomStr: find the string of the atom */
#define OFS2AtomStr(ofs) (OFS2AtomData_ptr(atom_ofs)->str)
/* offset of an atom according to index */
#define ATOM_OFS(idx) (main_block->atoms[idx])
/* rot_left: rotate (with wrap-around) */
static __inline__ int rot_left(unsigned var,int count)
{
return (var<<count) | (var>> (sizeof(var)-count));
}
/* find the entry in the atom table for this string */
static int FindHash(LPCSTR str) /* ignore str case */
{
int i,j;
unsigned hash1,hash2;
int deleted=-1; /* hash for deleted entry */
int atom_ofs;
/* get basic hash parameters */
for (i= hash1= hash2= 0; str[i] ; i++) {
hash1= rot_left(hash1,5) ^ toupper(str[i]);
hash2= rot_left(hash2,4) ^ toupper(str[i]);
}
hash1%= DDE_ATOMS;
atom_ofs=ATOM_OFS(hash1);
switch (atom_ofs) {
case EMPTY: /* empty atom entry */
return hash1;
case DELETED: /* deleted atom entry */
deleted=hash1;
break;
default : /* non empty atom entry */
if ( strcasecmp( OFS2AtomStr(atom_ofs) , str) == 0)
return hash1; /* found string in atom table */
}
hash2%= DDE_ATOMS-1 ; /* hash2=0..(DDE_ATOMS-2) */
hash2++; /* hash2=1..(DDE_ATOMS-1) */
/* make jumps in the hash table by hash2 steps */
for (i=hash1+hash2 ; ; i+=hash2) {
/* i wraps around into j */
j=i-DDE_ATOMS;
if (j >= 0)
i=j; /* i wraps around */
if (i==hash1)
/* here if covered all hash locations, and got back to beginning */
return deleted; /* return first empty entry - if any */
atom_ofs=ATOM_OFS(i);
switch (atom_ofs) {
case EMPTY: /* empty atom entry */
return i;
case DELETED: /* deleted atom entry */
if (deleted < 0)
/* consider only the first deleted entry */
deleted= i;
break;
default : /* nonempty atom entry */
if ( strcasecmp( OFS2AtomStr(atom_ofs) , str) == 0)
return i; /* found string in atom table */
}
}
}
void ATOM_GlobalInit(void)
{
int i;
for (i=0 ; i < DDE_ATOMS ; i++)
ATOM_OFS(i)=EMPTY;
}
/***********************************************************************
* GlobalAddAtom (USER.268)
*/
/* important! don't forget to unlock semaphores before return */
ATOM GlobalAddAtom( LPCSTR str )
{
int atom_idx;
int atom_ofs;
AtomData_ptr ptr;
ATOM atom;
dprintf_atom(stddeb,"GlobalAddAtom(%p)\n", str);
if ((unsigned) str < MIN_STR_ATOM) /* MS-windows convention */
return (ATOM) (unsigned) str;
if (str[0] == '#') { /* wine convention */
atom= (ATOM) atoi(&str[1]);
return (atom<MIN_STR_ATOM) ? atom : 0;
}
dprintf_atom(stddeb,"GlobalAddAtom(\"%s\")\n",str);
DDE_IPC_init(); /* will initialize only if needed */
shm_write_wait(main_block->sem);
atom_idx=FindHash(str);
atom=(ATOM)0;
/* use "return" only at the end so semaphore handling is done only once */
if (atom_idx>=0) {
/* unless table full and item not found */
switch (atom_ofs= ATOM_OFS(atom_idx)) {
case DELETED:
case EMPTY: /* need to allocate new atom */
atom_ofs= shm_FragmentAlloc(&main_block->block,
strlen(str)+sizeof(AtomData));
if (atom_ofs==NIL)
break; /* no more memory (atom==0) */
ATOM_OFS(atom_idx)=atom_ofs;
ptr=OFS2AtomData_ptr(atom_ofs);
strcpy(ptr->str,str);
ptr->count=1;
atom=(ATOM)(atom_idx+MIN_STR_ATOM);
break;
default : /* has to update existing atom */
OFS2AtomData_ptr(atom_ofs)->count++;
atom=(ATOM)(atom_idx+MIN_STR_ATOM);
} /* end of switch */
} /* end of if */
shm_write_signal(main_block->sem);
return atom;
}
/***********************************************************************
* GlobalDeleteAtom (USER.269)
*/
ATOM GlobalDeleteAtom( ATOM atom )
{
int atom_idx;
int atom_ofs;
AtomData_ptr atom_ptr;
ATOM retval=(ATOM) 0;
dprintf_atom(stddeb,"GlobalDeleteAtom(\"%d\")\n",(int)atom);
atom_idx=(int)atom - MIN_STR_ATOM;
if (atom_idx < 0 )
return 0;
DDE_IPC_init(); /* will initialize only if needed */
shm_write_wait(main_block->sem);
/* return used only once from here on -- for semaphore simplicity */
switch (atom_ofs=ATOM_OFS(atom_idx)) {
case DELETED:
case EMPTY:
fprintf(stderr,"trying to free unallocated atom %d\n", atom);
retval=atom;
break;
default :
atom_ptr=OFS2AtomData_ptr(atom_ofs);
if ( --atom_ptr->count == 0) {
shm_FragmentFree(&main_block->block,atom_ofs);
ATOM_OFS(atom_idx)=DELETED;
}
}
shm_write_signal(main_block->sem);
return retval;
}
/***********************************************************************
* GlobalFindAtom (USER.270)
*/
ATOM GlobalFindAtom( LPCSTR str )
{
int atom_idx;
int atom_ofs;
dprintf_atom(stddeb,"GlobalFindAtom(%p)\n", str );
if ((unsigned) str < MIN_STR_ATOM) /* MS-windows convention */
return (ATOM) (unsigned) str;
if (str[0] == '#') { /* wine convention */
ATOM atom= (ATOM) atoi(&str[1]);
return (atom<MIN_STR_ATOM) ? atom : 0;
}
dprintf_atom(stddeb,"GlobalFindAtom(\"%s\")\n",str);
DDE_IPC_init(); /* will initialize only if needed */
shm_read_wait(main_block->sem);
atom_idx=FindHash(str);
if (atom_idx>=0)
atom_ofs=ATOM_OFS(atom_idx); /* is it free ? */
else
atom_ofs=EMPTY;
shm_read_signal(main_block->sem);
if (atom_ofs==EMPTY || atom_ofs==DELETED)
return 0;
else
return (ATOM)(atom_idx+MIN_STR_ATOM);
}
/***********************************************************************
* GlobalGetAtomName (USER.271)
*/
WORD GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
{
int atom_idx, atom_ofs;
int size;
/* temporary buffer to hold maximum "#65535\0" */
char str_num[7];
if (count<2) /* no sense to go on */
return 0;
atom_idx=(int)atom - MIN_STR_ATOM;
if (atom_idx < 0) { /* word atom */
/* use wine convention... */
sprintf(str_num,"#%d%n",(int)atom,&size);
if (size+1>count) { /* overflow ? */
/* truncate the string */
size=count-1;
str_num[size]='\0';
}
strcpy(buffer,str_num);
return size;
}
DDE_IPC_init(); /* will initialize only if needed */
/* string atom */
shm_read_wait(main_block->sem);
atom_ofs=ATOM_OFS(atom_idx);
if (atom_ofs==EMPTY || atom_ofs==DELETED) {
fprintf(stderr,"GlobalGetAtomName: illegal atom=%d\n",(int)atom);
size=0;
} else { /* non empty entry */
/* string length will be at most count-1, find actual size */
sprintf(buffer,"%.*s%n",count-1, OFS2AtomStr(atom_ofs), &size);
}
shm_read_signal(main_block->sem);
return size;
}
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: dde_atom_test.c
* Purpose : tests for dde_atom object
***************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <win.h>
#include "dde_atom.h"
#include "shm_main_blk.h"
#include <stddebug.h>
#include <debug.h>
#define TOGETHER (DDE_ATOMS/5)
/* run random sequences */
int main()
{
ATOM atom_list[TOGETHER];
char str[TOGETHER][80];
int i,j,atom_n;
int atom_len[TOGETHER];
debugging_shm=1;
debugging_atom=0;
debugging_sem=0;
for (i=0 ; i<=10000/TOGETHER ; i++) {
for (atom_n=0 ; atom_n<TOGETHER ; atom_n++) {
atom_len[atom_n]=rand()%64+1;
for (j=atom_len[atom_n]-1; j>=0; j--)
do {
str[atom_n][j]=(char)(rand()%255+1);
} while (j==0 && str[atom_n][j]=='#');
str[atom_n][ atom_len[atom_n] ]='\0';
atom_list[atom_n]=GlobalAddAtom(str[atom_n]);
if (atom_list[atom_n]==0) {
fprintf(stderr,"failed i=%d, atom_n=%d\n",i,atom_n);
return 1;
}
if (atom_list[atom_n]!=GlobalAddAtom(str[atom_n])) {
fprintf(stderr,
"wrong second GlobalAddAtom(\"%s\")\n", str[atom_n]);
return 1;
}
} /* for */
for (atom_n=0 ; atom_n<TOGETHER ; atom_n++) {
char buf[80];
int len;
len=GlobalGetAtomName( atom_list[atom_n], buf, 79);
if (atom_len[atom_n] != len) {
fprintf(stderr, "i=%d, atom_n=%d; ", i, atom_n);
fprintf(stderr,
"wrong length of GlobalGetAtomName(\"%s\")\n",
str[atom_n]);
return 1;
}
}
for (atom_n=0 ; atom_n<TOGETHER ; atom_n++) {
GlobalDeleteAtom(atom_list[atom_n]);
if (atom_list[atom_n]!=GlobalAddAtom(str[atom_n])) {
fprintf(stderr, "i=%d, atom_n=%d; ", i, atom_n);
fprintf(stderr,
"wrong third GlobalAddAtom(\"%s\")\n", str[atom_n]);
return 1;
}
GlobalDeleteAtom(atom_list[atom_n]);
GlobalDeleteAtom(atom_list[atom_n]);
atom_list[atom_n]=GlobalAddAtom(str[atom_n]);
if (atom_list[atom_n]!=GlobalAddAtom(str[atom_n])) {
fprintf(stderr,
"i=%d, atom_n=%d wrong fifth GlobalAddAtom(\"%s\")\n",
i, atom_n,
str[atom_n]);
return 1;
}
GlobalDeleteAtom(atom_list[atom_n]);
if (atom_list[atom_n]!=GlobalFindAtom(str[atom_n])) {
fprintf(stderr,
"i=%d, atom_n=%d wrong GlobalFindAtom(\"%s\")\n",
i, atom_n,
str[atom_n]);
return 1;
}
GlobalDeleteAtom(atom_list[atom_n]);
}
}
return 0;
}
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: dde_mem.c
* Purpose : shared DDE memory functionality for DDE
***************************************************************************
*/
#include <stdio.h>
#include <stddebug.h>
#include <debug.h>
#include <assert.h>
#include "ldt.h"
#include "shm_main_blk.h"
#include "shm_fragment.h"
#include "shm_semaph.h"
#include "dde_mem.h"
#include "bit_array.h"
#define SEGPTR2HANDLE_INFO(sptr) ( (struct handle_info*)PTR_SEG_TO_LIN(sptr) )
#define HINFO2DATAPTR(h_info_ptr) ( (void*) ( (char*)h_info_ptr + \
sizeof(struct handle_info) ) )
#define DDE_MEM_IDX(handle) ((handle)& 0x7fff)
#define DDE_MEM_HANDLE(idx) ((idx) | 0x8000)
#define DDE_MEM_INFO(handle) (main_block->handles[ DDE_MEM_IDX(handle) ])
/* List of shared handles.
* This entry resides on the shared memory, the data comes right
* after the `handle_info'.
* The entry is on the same block as the actual data.
* The `next' field gives relative reference (relative to the start of
* the blcok.
*/
struct handle_info {
WORD lock_count;
WORD flags;
int size; /* size of the data (net)*/
};
static bit_array free_handles;
int debug_last_handle_size= 0; /* for debugging purpose only */
/* locate_handle:
* locate a shared memory handle.
* Application:
* The handle is first searched for in attached blocks.
* At the beginning, only blocks owned by this process are
* attached.
* If a handle is not found, new blocks are attached.
* Arguments:
* h - the handle.
* RETURN: pointer to handle info.
*/
static struct handle_info *locate_handle(HGLOBAL h, struct local_shm_map *map)
{
struct shm_block *block;
dprintf_global(stddeb,"shm:locate_handle(0x%04x)\n", h);
if (SampleBit( &free_handles, DDE_MEM_IDX(h)) == 0) {
dprintf_global(stddeb, "shm:locate_handle: return NULL\n");
return NULL; /* free!!! */
}
block= shm_locate_block(DDE_MEM_INFO(h).shmid, map);
if (block == NULL) {
/* nothing found */
dprintf_global(stddeb, "shm:locate_handle: return NULL\n");
return NULL;
}
return (struct handle_info *) REL2PTR(block, DDE_MEM_INFO(h).rel);
}
/* dde_alloc_handle: allocate shared DDE handle */
static HGLOBAL dde_alloc_handle()
{
int bit_nr;
bit_nr= AllocateBit( &free_handles);
if (bit_nr != -1)
return DDE_MEM_HANDLE(bit_nr);
dprintf_global(stddeb,"dde_alloc_handle: no free DDE handle found\n");
return 0;
}
/**********************************************************************
* DDE_malloc
*/
void *
DDE_malloc(unsigned int flags, unsigned long size, SHMDATA *shmdata)
{
int shmid;
struct shm_block *block;
struct handle_info *h_info;
struct local_shm_map *curr;
HGLOBAL handle;
dprintf_global(stddeb,"DDE_malloc flags %4X, size %ld\n", flags, size);
DDE_IPC_init(); /* make sure main shm block allocated */
shm_write_wait(main_block->proc[curr_proc_idx].sem);
/* Try to find fragment big enough for `size' */
/* iterate through all local shm blocks, and try to allocate
the fragment */
h_info= NULL;
for (curr= shm_map ; curr != NULL ; curr= curr->next) {
if (curr->proc_idx == curr_proc_idx) {
h_info= (struct handle_info *)
shm_FragPtrAlloc(curr->ptr, size+sizeof(struct handle_info));
if (h_info!=NULL) {
shmid= curr->shm_id;
break;
}
}
}
if (h_info == NULL) {
block= shm_create_block(0, size+sizeof(struct handle_info), &shmid);
if (block==NULL) {
shm_write_signal(main_block->proc[curr_proc_idx].sem);
return 0;
}
/* put the new block in the linked list */
block->next_shm_id= main_block->proc[curr_proc_idx].shmid;
main_block->proc[curr_proc_idx].shmid= shmid;
h_info= (struct handle_info *)
shm_FragPtrAlloc(block, size+sizeof(struct handle_info));
if (h_info==NULL) {
fprintf(stderr,"DDE_malloc: BUG! unallocated fragment\n");
shm_write_signal(main_block->proc[curr_proc_idx].sem);
return 0;
}
} else {
block= curr->ptr;
}
/* Here we have an allocated fragment */
h_info->flags= flags;
h_info->lock_count= 0;
h_info->size= size;
handle= dde_alloc_handle();
if (handle) {
dprintf_global(stddeb,
"DDE_malloc returning handle=0x%4x, ptr=0x%08lx\n",
(int)handle, (long) HINFO2DATAPTR(h_info));
DDE_MEM_INFO(handle).rel= PTR2REL(block, h_info);
DDE_MEM_INFO(handle).shmid= shmid;
}
else
dprintf_global(stddeb,"DDE_malloc failed\n");
shm_write_signal(main_block->proc[curr_proc_idx].sem);
shmdata->handle= handle;
return (char *)HINFO2DATAPTR(h_info);
}
HGLOBAL DDE_GlobalFree(HGLOBAL h)
{
struct handle_info *h_info;
int handle_index= h & 0x7fff;
struct local_shm_map map;
dprintf_global(stddeb,"DDE_GlobalFree(0x%04x)\n",h);
if (h==0)
return 0;
h_info= locate_handle(h, &map);
if (h_info == NULL)
return h;
shm_write_wait(main_block->proc[map.proc_idx].sem);
shm_FragPtrFree(map.ptr, (struct shm_fragment *) h_info);
AssignBit( &free_handles, handle_index, 0);
/* FIXME: must free the shm block some day. */
shm_write_signal(main_block->proc[map.proc_idx].sem);
return 0;
}
WORD DDE_SyncHandle(HGLOBAL handle, WORD sel)
{
struct handle_info *h_info;
void *local_ptr;
ldt_entry entry;
h_info= locate_handle(handle, NULL);
local_ptr= (void *)GET_SEL_BASE(sel);
if (h_info == NULL)
return 0;
if (local_ptr == (void *) HINFO2DATAPTR(h_info))
return sel;
/* need syncronization ! */
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
entry.base= (unsigned long) HINFO2DATAPTR(h_info);
LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
return sel;
}
/*
* DDE_AttachHandle:
* Attach shm memory (The data must not be already attached).
* Parameters:
* handle - the memory to attach.
* segptr - in not null, return SEGPTR to the same block.
* return value:
* 32 bit pointer to the memory.
*/
void *DDE_AttachHandle(HGLOBAL handle, SEGPTR *segptr)
{
struct handle_info *h_info;
SHMDATA shmdata;
void *ptr;
HGLOBAL hOwner = GetCurrentPDB();
assert(is_dde_handle(handle));
if (segptr != NULL)
*segptr=0;
dprintf_global(stddeb,"DDE_AttachHandle(%04x)\n",handle);
h_info=locate_handle(handle, NULL);
if (h_info == NULL)
return NULL;
if ( !(h_info->flags & GMEM_DDESHARE) ) {
fprintf(stderr,"DDE_AttachHandle: Corrupted memory handle info\n");
return NULL;
}
dprintf_global(stddeb,"DDE_AttachHandle: h_info=%06lx\n",(long)h_info);
shmdata.handle= handle;
shmdata.shmid= DDE_MEM_INFO(handle).shmid;
ptr= HINFO2DATAPTR(h_info);
/* Allocate the selector(s) */
if (! GLOBAL_CreateBlock( h_info->flags, ptr, h_info->size, hOwner,
FALSE, FALSE, FALSE, &shmdata))
return NULL;
if (segptr != NULL)
*segptr= (SEGPTR)MAKELONG( 0, shmdata.sel);
if (debugging_dde)
debug_last_handle_size= h_info->size;
dprintf_global(stddeb,"DDE_AttachHandle returns ptr=0x%08lx\n", (long)ptr);
return (LPSTR)ptr;
}
void DDE_mem_init()
{
int nr_of_bits;
shm_init();
nr_of_bits= BITS_PER_BYTE * sizeof(main_block->free_handles);
AssembleArray( &free_handles, main_block->free_handles, nr_of_bits);
}
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: dde_mem_test.c
* Purpose : test shared DDE memory functionality for DDE
* Usage: Look for assertion failures
***************************************************************************
*/
#include <stdio.h>
#include <assert.h>
#include <win.h>
#include "dde_mem.h"
/* stub */
void ATOM_GlobalInit()
{
printf("ATOM_GlobalInit\n");
}
int main()
{
HWND h1,h2,h3;
int ret;
void *p1,*p2,*p3,*p;
SHMDATA shmdata;
/* alloc h1, h2, h3 */
setbuf(stdout,NULL);
p1=DDE_malloc(GMEM_DDESHARE, 0x6000, &shmdata);
h1= shmdata.handle;
assert(p1 != NULL);
assert(h1 != 0);
p2=DDE_malloc(GMEM_DDESHARE, 0xff00, &shmdata);
h2= shmdata.handle;
assert(p2 != NULL);
assert(h2 != 0);
p3=DDE_malloc(GMEM_DDESHARE, 0x6000, &shmdata);
h3= shmdata.handle;
assert(p3 != 0);
assert(h3 != 0);
/* lock h1, h2, h3 */
p=DDE_AttachHandle(h1,NULL);
assert(p1==p);
p=DDE_AttachHandle(h2,NULL);
assert(p2==p);
p=DDE_AttachHandle(h3,NULL);
assert(p3==p);
ret=DDE_GlobalFree(h1);
assert(ret==0);
/* do some implementation dependant tests */
p=DDE_malloc(GMEM_DDESHARE, 0x6000, &shmdata);
assert(p!=NULL);
assert(shmdata.handle==h1);
p=DDE_AttachHandle(h1,NULL);
assert(p1==p);
/* check freeing */
ret=DDE_GlobalFree(h1);
assert(ret==0);
ret=DDE_GlobalFree(h2);
assert(ret==0);
ret=DDE_GlobalFree(h3);
assert(ret==0);
return 0;
}
This diff is collapsed. Click to expand it.
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: dde_proc.c
* Purpose : test DDE signals and processes functionality for DDE
* Usage: run two independant processes, one with an argument another
* without (with the argument is the server).
***************************************************************************
*/
#if defined(__NetBSD__) || defined(__FreeBSD__)
#include <sys/syscall.h>
#include <sys/param.h>
#else
#include <syscall.h>
#endif
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <win.h>
#include "dde.h"
#include "dde_proc.h"
#include "shm_main_blk.h"
#if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__)
char * cstack[4096];
#endif
#ifdef linux
extern void ___sig_restore();
extern void ___masksig_restore();
/* Similar to the sigaction function in libc, except it leaves alone the
restorer field */
static int
wine_sigaction(int sig,struct sigaction * new, struct sigaction * old)
{
__asm__("int $0x80":"=a" (sig)
:"0" (SYS_sigaction),"b" (sig),"c" (new),"d" (old));
if (sig>=0)
return 0;
errno = -sig;
return -1;
}
#endif
struct sigaction usr2_act;
void init_signals()
{
#ifdef linux
usr2_act.sa_handler = (__sighandler_t) stop_wait;
usr2_act.sa_flags = 0;
usr2_act.sa_restorer =
(void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
wine_sigaction(SIGUSR2,&usr2_act,NULL);
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__)
usr2_act.sa_hadnler = (void (*)) stop_wait;
usr2_act.sa_flags = SA_ONSTACK;
usr2_act.sa_mask = sig_mask;
usr2_act.sa_restorer =
(void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
if (sigaction(SIGUSR2,&usr2_act,NULL) <0) {
perror("sigaction: SIGUSR2");
exit(1);
}
#endif
}
void ATOM_GlobalInit()
{
printf("ATOM_GlobalInit\n");
}
void idle_loop()
{
int timeout;
for(timeout=500; timeout ; timeout--) {
if (DDE_GetRemoteMessage())
exit(0); ;
usleep(1000);
}
exit(-1);
}
void client()
{
MSG msg;
msg.hwnd=(HWND)-1;
msg.message= WM_DDE_INITIATE;
msg.wParam= 3;
msg.lParam= 4;
if (!DDE_SendMessage(&msg))
exit(-1);
idle_loop();
}
void server()
{
DDE_IPC_init();
idle_loop();
}
int main(int argc, char *argv[])
{
printf("Kill when done one message\n");
init_signals();
if (argc>1)
server();
else
client();
return 0;
}
/***************************************************************************
* Copyright 1995 Michael Veksler. mveksler@vnet.ibm.com
***************************************************************************
* File: generic_hash.h
* Purpose : dynamically growing hash, may use shared or local memory.
***************************************************************************
*/
#ifndef _GENERIC_HASH_H_
#define _GENERIC_HASH_H_
#include "wintypes.h"
#include "shm_block.h"
/* default hash values */
#define HASH_LOAD 70
#define HASH_MEM_ALLOC (HASH_PTR (*)(int size)) malloc
#define HASH_MEM_FREE (void (*)(HASH_PTR)) free
#define HASH_MEM_ACCESS access_local_hash
#define HASH_REALLOC_JUMPS 1.5 /* Relative size of the new memory */
#define MIN_HASH 13
typedef union {
char string[1];
WORD words[1];
DWORD dwords[1];
char *ptr;
SEGPTR segptr;
} HASH_VAL;
typedef struct hash_item_struct {
DWORD key;
HASH_VAL data;
} HASH_ITEM;
/* point to the hash structure */
typedef union {
HASH_ITEM* ptr; /* Local pointer */
REL_PTR rel; /* IPC relative address */
SEGPTR segptr; /* Universal (can be IPC or local) */
} HASH_PTR;
typedef struct hash_share_struct {
int total_items; /* total number of items (array size) */
int free_items; /* number of free items (excluding deleted) */
int deleted_items; /* number of deleted items */
int ptr_updates; /* Number of updates to `items' pointer */
/* (of items) - used for intecepting */
/* changes to the pointer. */
HASH_PTR items; /* pointer to the items */
} HASH_SHARED;
typedef BOOL HASH_ITEM_TEST(HASH_VAL *value, HASH_VAL *seeked_data);
/* NOTE:
* 1. Keys 0 and -1 are reserved.
* 2. none of these items should be accessed directly, use existing
* functions. If they are not enough, add a new function.
*/
typedef struct hash_container_struct {
int bytes_per_item;
int maximum_load; /* in percents (0..100) default is 70 */
int min_free_items; /* minimum free items before reallocating
(Function of maximum_load) */
int last_ptr_update; /* to be compared with shared.ptr_updates */
BOOL shared_was_malloced; /* Need that to know how to destroy hash */
/* This is an optional handler.
* If not NULL, this function is used for distinguishing between
* different data with the same key (key field holds integer and
* is too short for long keys like strings).
*/
HASH_ITEM_TEST *is_correct_item;
/* Handlers used for reallocating memory
* [by allocating new data and then freeing old data]
*/
HASH_PTR (*allocate_mem)(int size);
void (*free_mem)(HASH_PTR);
/* Translator from HASH_PTR construct to a regular pointer.
use HASH_MEM_ACCESS, if no translation is needed */
HASH_ITEM *(*access_mem)(HASH_PTR);
HASH_ITEM *items;
HASH_SHARED *shared; /* Things to be on shared memory. */
} HASH_CONTAINER;
/********** Hash maintenance functions ***********/
/* Attach existing & running remote (i.e. shared) hash.
* Attach the items using the data stored in "shared"
*/
HASH_CONTAINER *attach_remote_hash(HASH_SHARED *shared, int bytes_per_datum,
HASH_ITEM *(*access_mem)(HASH_PTR));
HASH_CONTAINER *create_remote_hash(HASH_SHARED *shared,
int bytes_per_datum,
int total_items,
HASH_PTR (*allocate_mem)(int size),
HASH_ITEM *(*access_mem)(HASH_PTR));
/* hash constructor: create brand new hash (not on shared memory) */
HASH_CONTAINER *create_hash(int bytes_per_datum, int total_items);
/* set the extra handlers to non default values */
void set_hash_handlers(HASH_CONTAINER *hash,
HASH_ITEM_TEST *is_correct_item,
HASH_PTR (*allocate_mem)(int size),
void (*free_mem)(HASH_PTR),
HASH_ITEM *(*access_mem)(HASH_PTR));
/* set extra parameters */
void set_hash_parameters(HASH_CONTAINER *hash, int load);
/* hash destructors */
void destroy_hash(HASH_CONTAINER *hash);
void detach_hash(HASH_CONTAINER *hash);
/********** Hash usage *************/
/* All following functions have the same format:
* hash- the hash structure to use
* key- used as primary means to get to the entry.
* data- 1. a secondary key (used only if `is_correct_item' is set).
* 2. data to store. (for hash_add_item).
*/
HASH_VAL *hash_locate_item(HASH_CONTAINER* hash,int key, HASH_VAL* seeked_data);
BOOL hash_add_item(HASH_CONTAINER* hash, int key, HASH_VAL* data);
BOOL hash_delete_item(HASH_CONTAINER* hash, int key, HASH_VAL* seeked_data);
void *ret_null(); /* function returning null (used for */
/* disabling memory reallocation) */
/* access function used by local (non IPC) memory */
HASH_ITEM *access_local_hash(HASH_PTR ptr);
#endif /* _GENERIC_HASH_H_ */
/***************************************************************************
* Copyright 1995 Michael Veksler. mveksler@vnet.ibm.com
***************************************************************************
* File: hash_test.c
* Purpose : test generic_hash correctness.
* NOTE:
* This code covers only about 80% of generic_hash code.
* There might be bugs in the remaining 20% - although most
* of the functionality is tested with wine linckage.
* For complete testing a little more work should be done.
***************************************************************************
*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "generic_hash.h"
#define SIZE 200
typedef struct { int a,b;} DATA ;
DATA data[SIZE];
int keys[SIZE];
int peeks=0;
HASH_CONTAINER *hash1;
HASH_CONTAINER *hash2; /* actual data is shared with hash1 */
/* test insertion using keys[] and data[] inserting using hash1 and */
/* hash2 periodically, test hash after every 2 insertions */
void test_insert()
{
int i,j;
HASH_VAL *item;
printf("testing insertion \n");
for (i=0 ; i < SIZE-1 ; i+=2) {
assert(hash_add_item(hash1, keys[i], (HASH_VAL *)&data[i]));
assert(hash_add_item(hash2, keys[i+1], (HASH_VAL *)&data[i+1]));
for (j=0 ; j <= i+1 ; j++) {
item= hash_locate_item(hash1, keys[j], (HASH_VAL *)&data[j]);
if (item == NULL) {
printf("NULL item: i=%d,j=%d\n",i,j);
continue;
}
peeks++;
if (memcmp(item,&data[j],sizeof(DATA))!=0) {
printf("i=%d,j=%d\n",i,j);
printf("saved=(%d,%d), orig=(%d,%d)\n",
((DATA*)item)->a, ((DATA*)item)->b,
data[j].a, data[j].b);
}
}
}
}
/* test deletion using keys[] and data[] deleting using hash1 and */
/* hash2 periodicly, test hash after every 2 deletions */
void test_delete()
{
int i,j;
HASH_VAL *item;
printf("testing deletion\n");
for (i=0 ; i < SIZE-1 ; i+=2) {
assert(hash_delete_item(hash2, keys[i], NULL));
assert(hash_delete_item(hash1, keys[i+1], NULL));
for (j=0 ; j < SIZE ; j++) {
item= hash_locate_item(hash2, keys[j], (HASH_VAL *)&data[j]);
if (item == NULL) {
if ( j > i+1)
printf("NULL item: i=%d,j=%d\n",i,j);
continue;
}
if (item != NULL && j <= i+1) {
printf("Non NULL item: i=%d,j=%d\n",i,j);
continue;
}
if (memcmp(item,&data[j],sizeof(DATA))!=0) {
printf("i=%d,j=%d\n",i,j);
printf("saved=(%d,%d), orig=(%d,%d)\n",
((DATA*)item)->a, ((DATA*)item)->b,
data[j].a, data[j].b);
}
}
}
}
int main()
{
int i;
hash1= create_hash(sizeof(DATA), 1);
assert(hash1);
hash2= attach_remote_hash(hash1->shared, sizeof(DATA), HASH_MEM_ACCESS);
assert(hash2);
for (i=0 ; i< SIZE ; i++) {
data[i].a= rand();
data[i].b= rand();
keys[i]= rand();
}
test_insert();
detach_hash(hash1);
free(hash1);
hash1= attach_remote_hash(hash2->shared, sizeof(DATA), HASH_MEM_ACCESS);
test_delete();
test_insert();
detach_hash(hash1);
destroy_hash(hash2);
printf("peeks=%d\n", peeks);
return 0;
}
#!/bin/sh
bit_array_test
bit_array=$?
dde_mem_test
mem=$?
hash_test
hash=$?
shm_semaph_test
semaph=$?
dde_atom_test
atom=$?
dde_proc_test 1 > proc_server &
sleep 1
dde_proc_test > proc_client
fgrep "DDE:receive sent message. msg=03e0 wPar=fffb lPar=00000004" proc_server &&
fgrep "DDE_GetRemoteMessage: sending ACK to wnd=fffb, proc=1" proc_server &&
fgrep "get_ack: received DDE_ACK message" proc_client
proc=$?
rm proc_client proc_server
shm_fragment_test | diff TEST_FRAGMENT.std -
fragment=$?
echo ====================================================================
echo Test results:
echo -n "bit_array "
if [ $bit_array -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
echo -n "dde_mem "
if [ $mem -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
echo -n "hash "
if [ $hash -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
echo -n "shm_semaph "
if [ $semaph -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
echo -n "dde_proc "
if [ $proc -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
echo -n "shm_fragment "
if [ $fragment -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: shm_block.c
* Purpose: Treat a shared memory block.
***************************************************************************
*/
#define inline __inline__
#include <sys/sem.h>
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
#include <stddebug.h>
#include <debug.h>
#include <global.h>
#include "selectors.h"
#include "shm_fragment.h"
#include "shm_block.h"
#include "shm_semaph.h"
#include "dde_proc.h"
/* How each shmid is maped to local pointer */
/* Only attached shm blocks are in this construct */
struct local_shm_map *shm_map=NULL;
/* setup a new shm block (construct a shm block object).
* block: The pointer to the memory block (local mapping)
* first: The first data byte (excluding header stuff),
* if 0 (zero) Use the default.
* size: The size of the memory block.
*/
void shm_setup_block(struct shm_block *block, int first, int size)
{
dprintf_shm(stddeb,"Setting up shm block at 0x%08x\n",(int )block);
/* setup block internal data structure */
if (first <= 0) {
first=sizeof(*block);
/* round up - so everything starts on cache line boundary
* (assume cache line=32 bytes, may be bigger/smaller for
* different processors and different L2 caches .)
*/
first=(first+0x1f) & ~0x1f;
}
block->free=size-first;
block->next_shm_id=-1; /* IPC shm ID (for initial linking) */
block->proc_idx= curr_proc_idx;
/* block->size is initialized in shm_FragmentInit */
shm_FragmentInit(block, first, size); /* first item in the free list */
dprintf_shm(stddeb,
"block was set up at 0x%08x, size=0x%04xKB, 1st usable=%02x\n",
(int )block,size/1024,first);
}
/* shm_attach_block: attach existing shm block, setup selectors
* shm_id - id of the block to attach.
* proc_idx - if not -1, puts this data into local mapping
* map - localy mapped info about this block.
*/
/* NOTE: there is no check if this block is already attached.
* Attaching the same block more than once - is possible
* In case of doubt use shm_locate_block.
*/
struct shm_block *shm_attach_block(int shm_id, int proc_idx,
struct local_shm_map *map)
{
struct shm_block *block;
struct shmid_ds ds;
struct local_shm_map *this;
shmctl(shm_id, IPC_STAT, &ds );
block=(struct shm_block*)shmat(shm_id, NULL, 0);
if (block==NULL) return NULL;
this=(struct local_shm_map *)malloc(sizeof(*this));
this->next= shm_map;
shm_map = this;
this->shm_id= shm_id;
this->ptr = block;
if (proc_idx < 0)
this->proc_idx=block->proc_idx;
else
this->proc_idx=proc_idx;
if (map != NULL) {
memcpy(map, this, sizeof(map));
map->next= NULL; /* don't pass private info */
}
return block;
}
struct shm_block *shm_create_block(int first, int size, int *shm_id)
{
struct shm_block *block;
if (size==0)
size=SHM_MINBLOCK;
else
/* round up size to a multiple of SHM_MINBLOCK */
size= (size+SHM_MINBLOCK-1) & ~(SHM_MINBLOCK-1);
*shm_id= shmget ( IPC_PRIVATE, size ,0700);
if (*shm_id==-1)
return NULL;
block=shm_attach_block(*shm_id, curr_proc_idx, NULL);
if (block!=NULL)
shm_setup_block(block, first, size);
return block;
}
/*
** Locate attached block. (return it, or NULL on failure)
** shm_id is the block we look for.
** *map - will get all the info related to this local map + proc_idx
** (may be NULL)
** *seg - will get the segment this block is attached to.
*/
struct shm_block *shm_locate_attached_block(int shm_id,
struct local_shm_map *map)
{
struct local_shm_map *curr;
for (curr= shm_map ; curr != NULL ; curr= curr->next) {
if (curr->shm_id == shm_id) {
if (map) {
memcpy(map, curr, sizeof(*curr) );
map->next = NULL; /* this is private info ! */
}
return curr->ptr;
}
}
/* block not found ! */
return 0;
}
/* shm_locate_block: see shm_attach_block.
In addition to shm_attach_block, make sure this
block is not already attached.
*/
struct shm_block *shm_locate_block(int shm_id, struct local_shm_map *map)
{
struct shm_block *ret;
ret= shm_locate_attached_block(shm_id, map);
if (ret!=NULL)
return ret;
/* block not found ! , try to attach */
return shm_attach_block(shm_id, -1, map);
}
static void forget_attached(int shmid)
{
struct local_shm_map *curr, **point_to_curr;
for (curr= shm_map, point_to_curr= &shm_map ;
curr != NULL ;
curr= curr->next, point_to_curr= &curr->next ) {
if (curr->shm_id == shmid) {
*point_to_curr= curr->next;
return;
}
}
}
/* delete chain of shm blocks (pointing to each other)
* Do it in reverse order. (This is what the recursion is for)
*/
void shm_delete_chain(int *shmid)
{
struct shm_block *block;
if (*shmid == -1)
return;
block= shm_locate_block(*shmid, NULL);
forget_attached( *shmid );
if (block == NULL)
return;
shm_delete_chain(&block->next_shm_id);
shmctl(*shmid, IPC_RMID, NULL);
*shmid=-1;
shmdt((char *)block);
}
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: shm_fragment.c
* Purpose: Data fragments and free list items. Allocate and free blocks.
***************************************************************************
*/
#include <stdio.h> /* for debugging only */
#include <stddebug.h>
#include <debug.h> /* for "stddeb" */
#include "shm_fragment.h"
#include "shm_block.h"
/******************************************************************************
*
* Free list: all fragments are ordered according to memory location.
* new fragments are inserted in this way.
*
******************************************************************************
*/
#define FRAG_PTR(block,ofs) ((struct shm_fragment *) ((char *) block + ofs) )
#define NEXT_FRAG(block,ofs) ( FRAG_PTR(block,ofs)->info.next )
/* setup first item in the free list */
void shm_FragmentInit(struct shm_block *block,int first, int size)
{
struct shm_fragment *fragment;
/* round up to nearest 16 byte boundary */
first=(first+15)& ~15;
block->free_list=first;
/* make all the block (exluding the header) free */
fragment= FRAG_PTR(block, first);
block->free= fragment->size= size-first;
fragment->info.next=0;
}
void shm_FragPtrFree(struct shm_block *block, void *ptr)
{
/* ptr points to fragment->info.data, find pointer to fragment,
* find the offset of this pointer in block.
*/
if (ptr)
shm_FragmentFree(block, PTR2REL(block, ptr));
}
void shm_FragmentFree(struct shm_block *block, int fragment_ofs)
{
struct shm_fragment *fragment=NULL;
int prev;
int next;
fragment_ofs-=(int )&fragment->info.data;
fragment= FRAG_PTR(block, fragment_ofs);
block->free+=fragment->size;
/* scan free list to find candidates for merging with fragment */
for (prev=0, next=block->free_list;
(next!=0) && (fragment_ofs > next) ;
prev=next, next=NEXT_FRAG(block,next) )
;
/* insert fragment between, prev and next
* prev==0: fragment will be the first item in free list
* next==0: fragment will be the last item in free list
*/
/* update fragment (point to next, or merge with next) */
if ( fragment_ofs+fragment->size == next ) {
/* merge with the next free block */
fragment->size+= FRAG_PTR(block,next)->size;
fragment->info.next=FRAG_PTR(block,next)->info.next;
} else
/* fragment should be inserted before the next fragment or end of */
/* list. (not merged) */
fragment->info.next=next;
/* now fragment has all the information about the rest of the list */
/* upate prev fragment (point or merge with fragment) */
if (prev==0) /* first item in free list */
block->free_list=fragment_ofs;
else if ( prev+FRAG_PTR(block,prev)->size == fragment_ofs ) {
/* merge fragment with previous fragment */
FRAG_PTR(block,prev)->size+= fragment->size;
FRAG_PTR(block,prev)->info.next=fragment->info.next;
} else
/* insert fragment after previous fragment */
FRAG_PTR(block,prev)->info.next=fragment_ofs;
}
/* use "first fit" algorithm,
* return: offset to data in fragment.
*/
int shm_FragmentAlloc(struct shm_block *block, int size)
{
int prev;
int candidate;
struct shm_fragment *fragment;
struct shm_fragment *ret_fragment;
if (size <= 0)
return NIL;
/* add size of "fragment->size" */
size+= (char *)&fragment->info.data - (char *)fragment ;
/* round "size" to nearest 16 byte value */
size= (size+15) & ~15;
if (size > block->free)
return NIL;
/* scan free list to find candidates for allocation */
for (prev=0, candidate=block->free_list;
candidate!=0 ;
prev=candidate, candidate= fragment->info.next )
{
fragment=FRAG_PTR(block,candidate);
if (fragment->size >= size)
break;
}
if (candidate == 0)
return NIL;
block->free-=size;
if (fragment->size == size) {
if (prev == 0)
block->free_list= fragment->info.next;
else
FRAG_PTR(block,prev)->info.next= fragment->info.next;
return PTR2REL(block, &fragment->info.data);
}
/* fragment->size > size */
/* Split fragment in two, return one part, put the other in free list. */
/* The part that starts at the old location - will stay in the free list. */
fragment->size -= size;
ret_fragment=FRAG_PTR(block, candidate + fragment->size);
ret_fragment->size= size;
return PTR2REL(block, ret_fragment->info.data);
}
/* like shm_FragmentAlloc, returns pointer instead of offset */
char *shm_FragPtrAlloc(struct shm_block *block, int size)
{
int ofs;
ofs= shm_FragmentAlloc(block,size);
if (ofs == NIL)
return NULL;
else
return (char *) REL2PTR(block, ofs);
}
/* This is used for debugging only */
void shm_print_free_list(struct shm_block *block)
{
struct shm_fragment *fragment;
int item;
item=block->free_list;
if (item==0) {
fprintf(stddeb,"no free fragments");
} else {
for (; item ; item=fragment->info.next) {
fragment=FRAG_PTR(block,item);
fprintf(stddeb,"{0x%04x,0x%04x} ",item,fragment->size);
}
}
fprintf(stddeb," [total free=%04x]\n",block->free);
fflush(stddeb);
}
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: shm_fragment_test.c
* Purpose: Test data fragments and free list items. Allocate and free blocks.
***************************************************************************
*/
#include <assert.h>
#include <stdio.h>
#include <stddebug.h>
#define DEBUG_DEFINE_VARIABLES /* just avoid dumb errors */
#include <debug.h> /* for "stddeb" */
#include <stdlib.h>
#include <string.h>
#include "shm_block.h"
#include "shm_fragment.h"
#define DO_FREE(id) (-id)
#define LIST_LENGTH 20
int main()
{
struct shm_block *block;
char *ret;
int size;
int i;
/* important: The test will work only for the current implementation of */
/* allocation, if the implementation will change, the list should also */
/* cahnge. */
static int sizes[LIST_LENGTH]={
SHM_MINBLOCK, /* 0: should fail */
0x3fe0-4, /* 1: */
0x4000-4, /* 2: */
0x4000-4, /* 3: */
0x4000-4+1, /* 4: should fail */
0x4000-4, /* 5: */
/* allocated(5,3,2,1) free() */
-5, /* 6: */
0x1c00-4, /* 7: */
0x1400-4, /* 8: */
0x1000-4, /* 9: */
/* allocated(9,8,7,3,2,1) free() */
-9, /* 10: */
-3, /* 11: */
-1, /* 12: */
/* allocated(8,7,2) free(9,3,1) */
0x1000-4, /* 13: */
-13, /* 14: */
0x1000+1-4, /* 15: */
/* allocated(8,7,15,2) free(9,[3-15],1) */
-2, /* 16: */
/* allocated(8,7,15) free(9,[3-15],1+2) */
-8, /* 17: */
-7, /* 18: */
-15 /* 19: */
};
static char *ptr[LIST_LENGTH];
block=malloc(SHM_MINBLOCK);
assert(block);
/* setup first item in the free list */
shm_FragmentInit(block, sizeof(*block), SHM_MINBLOCK);
fprintf(stddeb,"After shm_FragmentInit\n");
shm_print_free_list(block);
for(i=0 ; i < LIST_LENGTH; i++) {
size=sizes[i];
if (size>0) { /* allocate */
ret=shm_FragPtrAlloc(block, size);
ptr[i]=ret;
fprintf(stddeb,
"%d: After shm_FragmentAlloc(block, 0x%06x) == ",
i, size);
if (ret==NULL)
fprintf(stddeb, "NULL\n");
else {
fprintf(stddeb, "0x%06x\n", (int)ret-(int)block);
bzero (ret,size); /* test boundaries */
}
} else { /* free */
/* free shm fragment */
ret=ptr[-sizes[i]];
fprintf(stddeb, "%d: Doing shm_FragmentFree(block, ", i);
if (ret==NULL)
fprintf(stddeb, "NULL)\n");
else
fprintf(stddeb, "0x%06x)\n", (int)ret-(int)block);
fflush(stddeb);
shm_FragPtrFree(block, ret);
}
shm_print_free_list(block);
}
return 0;
}
/***************************************************************************
* Copyright 1995, Technion, Israel Institute of Technology
* Electrical Eng, Software Lab.
* Author: Michael Veksler.
***************************************************************************
* File: shm_main_blk.c
* Purpose: Main Wine's shared memory block
***************************************************************************
*/
#define inline __inline__
#include <sys/sem.h>
#include <stdio.h>
#include <time.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <stddebug.h>
#include <debug.h>
#include "shm_fragment.h"
#include "shm_block.h"
#include "shm_main_blk.h"
#include "shm_semaph.h"
#define WineKey ( 'W'+((int)'i'<<8)+((int)'n'<<16)+((int)'e'<<24) )
#define SHM_KEY_RANGE 8
/* main block (set during initialization) */
struct shm_main_block *main_block=NULL;
static char *shm_header="Wine - Windows emulator DDE mechanism";
static int main_shm_id;
static void shm_main_refresh();
/* for debugging only */
static void print_perm(struct ipc_perm *perm)
{
printf("Permission:\n");
printf("\tKey=%d, mode=%03o, sequence #=%d\n",
(int)perm->key,perm->mode, perm->seq);
printf("\towner: uid=%d, gid=%d ;" ,perm->uid, perm->gid);
printf(" creator: uid=%d, gid=%d\n",perm->cuid,perm->cgid);
}
/* for debugging only */
/* print_shm_info: print shared memory descriptor info */
static void print_shm_info(int shm_id)
{
struct shmid_ds ds;
shmctl(shm_id, IPC_STAT, &ds );
printf("shm_id=%d, Size=0x%08x , Number of attaches=%d\n",
shm_id, ds.shm_segsz, (int)ds.shm_nattch);
if (ds.shm_atime)
printf("Last attach=%s",ctime(&ds.shm_atime));
if (ds.shm_dtime)
printf("Last detach=%s",ctime(&ds.shm_dtime));
printf("Last change=%s",ctime(&ds.shm_ctime));
printf("pid: creator=%d, last operator=%d\n",
(int)ds.shm_cpid,(int)ds.shm_lpid);
print_perm( &ds.shm_perm);
}
int proc_exist(__pid_t pid)
{
if ( kill(pid,0) == 0) /* dummy signal to test existence */
return 1;
else if (errno==ESRCH) /* "no such process" */
return 0;
else
return 1;
}
/* setup a new main shm block (only construct a shm block object). */
static void shm_setup_main_block()
{
dprintf_shm(stddeb,"creating data structure\n");
main_block->build_lock=1;
strcpy(main_block->magic, shm_header);
shm_setup_block(&main_block->block,sizeof(*main_block),SHM_MINBLOCK);
dde_proc_init(main_block->proc);
ATOM_GlobalInit();
shm_sem_init(&main_block->sem);
/* main block set and data structure is stable now */
main_block->build_lock=0;
}
/* Delete everything related to main_block */
void shm_delete_all(int shmid)
{
int proc_idx;
if (shmid == -1)
shmid= main_shm_id;
shmctl( shmid, IPC_RMID, NULL);
for (proc_idx= 0 ; proc_idx < DDE_PROCS ; proc_idx++)
dde_proc_done( &main_block->proc[proc_idx] );
shm_sem_done(&main_block->sem);
shmdt( (void *) main_block);
main_block= NULL;
}
int DDE_no_of_attached()
{
struct shmid_ds shm_info;
if (shmctl(main_shm_id, IPC_STAT, &shm_info) == -1)
return -1;
return shm_info.shm_nattch;
}
/*
** Test if shm_id is MainBlock and attach it (if it is),
** Return 1 if ok, 0 otherwise.
*/
static int attach_MainBlock(int shm_id)
{
struct shmid_ds shm_info;
if (shmctl(shm_id, IPC_STAT, &shm_info) == -1)
return 0;
/* Make sure we don't work on somebody else's block */
if (shm_info.shm_perm.cuid != getuid()) { /* creator is not me */
dprintf_shm(stddeb,"Creator is not me!\n");
return 0;
}
dprintf_shm(stddeb,"shared memory exist, attaching anywhere\n");
main_block=(struct shm_main_block *)shmat(shm_id, 0, 0);
if ( (int)main_block==-1) {
dprintf_shm(stddeb,"Attach failed\n");
return 0;
}
if (strcmp(main_block->magic, shm_header) != 0) {
dprintf_shm(stddeb,"Detaching, wrong magic\n");
shmdt((void *)main_block);
return 0;
}
if (debugging_shm)
print_shm_info(shm_id);
/* Is it an old unused block ? */
if (shm_info.shm_nattch == 0) {
dprintf_shm(stddeb,"No attaches, deleting old data\n");
shm_delete_all(shm_id);
return 0;
}
/* Wait for data structure to stabilize */
while (main_block->build_lock)
usleep(10000);
main_shm_id= shm_id;
shm_main_refresh();
return 1;
}
/* (Function used by the constructor)
* Try to get existing shared memory with key="Wine", size=SHM_MINBLOCK
* complete user permission.
* If such block is found - return true (1), else return false (0)
*/
static int shm_locate_MainBlock(key_t shm_key)
{
int shm_id; /* Descriptor to this shared memory */
int i;
dprintf_shm(stddeb,"shm_locate_MainBlock: trying to attach, key=0x%x\n",
shm_key);
for (i=0 ; i < SHM_KEY_RANGE ; i++) {
dprintf_shm(stddeb,"iteration=%d\n", i);
shm_id= shmget ( shm_key+i, SHM_MINBLOCK ,0700);
if (shm_id != -1) {
if ( attach_MainBlock(shm_id) ) {
return 1; /* success! */
}
} else {
switch(errno) {
case EIDRM: /* segment destroyed */
case EACCES: /* no user permision */
break;
case ENOMEM: /* no free memory */
case ENOENT: /* this key does not exist */
default :
dprintf_shm(stddeb,"shmget failed, errno=%d, %s\n",
errno, strerror(errno) );
return 0; /* Failed */
}
} /* if .. else */
} /* for */
return 0;
}
/* (Function used by the constructor)
* Try to allocate new shared memory with key="Wine", size=SHM_MINBLOCK
* with complete user permission.
* If allocation succeeds - return true (1), else return false (0)
*/
static int shm_create_MainBlock(key_t MainShmKey)
{
int shm_id;
int flags= 0700 | IPC_CREAT | IPC_EXCL;
int i;
dprintf_shm(stddeb,"creating shared memory\n");
/* try to allocate shared memory with key="Wine", size=SHM_MINBLOCK, */
/* complete user permission */
for (i=0 ; i < SHM_KEY_RANGE ; i++) {
shm_id= shmget ( (key_t) MainShmKey, SHM_MINBLOCK, flags);
if (shm_id != -1)
break;
}
if (shm_id == -1) {
dprintf_shm(stddeb,"failed to create shared memory\n");
return 0;
}
dprintf_shm(stddeb,"shared memory created, attaching\n");
main_block=(struct shm_main_block*) shmat(shm_id, 0,0);
if (debugging_shm)
print_shm_info(shm_id);
main_shm_id= shm_id;
shm_setup_main_block();
dde_wnd_setup();
return 1;
}
/* link to the dde shared memory block */
/* RETURN: 0 on success, non zero on failure */
int shm_init(void)
{
if ( !shm_locate_MainBlock(WineKey)
&& !shm_create_MainBlock(WineKey)) {
fflush(stdout);
fprintf(stderr,"shm_init: failed to init main shm block\n");
exit(1);
}
dde_proc_add(main_block->proc);
return 0;
}
static void shm_main_refresh()
{
int proc_idx;
for (proc_idx= 0 ; proc_idx < DDE_PROCS ; proc_idx++)
dde_proc_refresh( &main_block->proc[proc_idx] );
}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment