Commit e94f9f72 authored by Edric Milaret's avatar Edric Milaret Committed by Guillaume Roguez

Win32 daemon portability

Refs #69827

Change-Id: Id9f7f888e49b1c3f4d8728b524991fb9ef6e3174
parent 099aa7b9
......@@ -12,8 +12,8 @@ without warranty of any kind.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
Briefly, the shell command `./configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
......
......@@ -20,13 +20,7 @@ endif
ACLOCAL_AMFLAGS = -I m4
#FIXME: this will change when libring is fixed
if HAVE_WIN32
SUBDIRS = bin
else
SUBDIRS = src ringtones man $(TESTS_DIR) doc bin
endif
EXTRA_DIST = m4/libtool.m4 \
m4/lt~obsolete.m4 \
......
if HAVE_WIN32
libexec_PROGRAMS = ringcli
ringcli_SOURCES = winmain.cpp
#FIXME This is temporary
ringcli_LDADD = $(SPEEX_LIBS)
ringcli_CXXFLAGS = -I$(top_srcdir)/src \
-I$(top_srcdir)/src/dring \
-DTOP_BUILDDIR=\"$$(cd "$(top_builddir)"; pwd)\"
ringcli_LDADD = $(top_builddir)/src/libring.la
endif
if HAVE_OSX
......
#include <speex/speex.h>
#include <cstdio>
#include <cmath>
/*
* Copyright (C) 2004-2015 Savoir-Faire Linux Inc.
* Author: Edric Milaret <edric.ladent-milaret@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
int main()
#include <iostream>
#include <thread>
#include <cstring>
#include <signal.h>
#include <getopt.h>
#include <string>
#include "dring.h"
#include "callmanager_interface.h"
#include "configurationmanager_interface.h"
#include "presencemanager_interface.h"
#ifdef RING_VIDEO
#include "videomanager_interface.h"
#endif
#include "fileutils.h"
#include <windows.h>
using namespace std::placeholders;
bool isActive = false;
static int ringFlags = 0;
bool loop = true;
static void
print_title()
{
std::cout
<< "Ring Daemon " << DRing::version()
<< ", by Savoir-Faire Linux 2004-2015" << std::endl
<< "http://www.ring.cx/" << std::endl;
}
static void
print_usage()
{
std::cout << std::endl <<
"-c, --console \t- Log in console (instead of syslog)" << std::endl <<
"-d, --debug \t- Debug mode (more verbose)" << std::endl <<
"-p, --persistent \t- Stay alive after client quits" << std::endl <<
"-h, --help \t- Print help" << std::endl;
}
// Parse command line arguments, setting debug options or printing a help
// message accordingly.
// returns true if we should quit (i.e. help was printed), false otherwise
static bool
parse_args(int argc, char *argv[], bool& persistent)
{
static const struct option long_options[] = {
/* These options set a flag. */
{"debug", no_argument, NULL, 'd'},
{"console", no_argument, NULL, 'c'},
{"persistent", no_argument, NULL, 'p'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{0, 0, 0, 0} /* Sentinel */
};
int consoleFlag = false;
int debugFlag = false;
int helpFlag = false;
int versionFlag = false;
while (true) {
/* getopt_long stores the option index here. */
int option_index = 0;
auto c = getopt_long(argc, argv, "dcphv", long_options, &option_index);
// end of the options
if (c == -1)
break;
switch (c) {
case 'd':
debugFlag = true;
break;
case 'c':
consoleFlag = true;
break;
case 'p':
persistent = true;
break;
case 'h':
case '?':
helpFlag = true;
break;
case 'v':
versionFlag = true;
break;
default:
break;
}
}
if (helpFlag) {
print_usage();
return true;
}
if (versionFlag) {
// We've always print the title/version, so we can just exit
return true;
}
if (consoleFlag)
ringFlags |= DRing::DRING_FLAG_CONSOLE_LOG;
if (debugFlag)
ringFlags |= DRing::DRING_FLAG_DEBUG;
return false;
}
void
IncomingCall(const std::string& accountId,
const std::string& callId, const std::string& message)
{
if (not isActive) {
DRing::accept(callId);
isActive = true;
} else
DRing::refuse(callId);
}
static int
run()
{
using SharedCallback = std::shared_ptr<DRing::CallbackWrapperBase>;
DRing::init(static_cast<DRing::InitFlag>(ringFlags));
std::map<std::string, SharedCallback> callHandlers;
callHandlers.insert(DRing::exportable_callback<DRing::CallSignal::IncomingCall>
(std::bind(&IncomingCall, _1, _2, _3)));
registerCallHandlers(callHandlers);
if (!DRing::start())
return -1;
while (loop) {
DRing::pollEvents();
Sleep(1000); // milliseconds
}
DRing::fini();
}
static void
interrupt()
{
const SpeexMode *mode = speex_lib_get_mode(SPEEX_MODEID_NB);
printf("Hello %s %f\n", mode->modeName, M_PI);
return 0;
loop = false;
}
static void
signal_handler(int code)
{
std::cerr << "Caught signal " << code
<< ", terminating..." << std::endl;
// Unset signal handlers
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
interrupt();
}
int
main(int argc, char *argv [])
{
// make a copy as we don't want to modify argv[0], copy it to a vector to
// guarantee that memory is correctly managed/exception safe
std::string programName {argv[0]};
std::vector<char> writable(programName.size() + 1);
std::copy(std::begin(programName), std::end(programName),std::begin(writable));
ring::fileutils::set_program_dir(writable.data());
print_title();
bool persistent = false;
if (parse_args(argc, argv, persistent))
return 0;
// TODO: Block signals for all threads but the main thread, decide how/if we should
// handle other signals
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
#ifdef RING_VIDEO
std::cerr << "Warning: built with video support" << std::endl;
#endif
return run();
}
......@@ -63,10 +63,6 @@ case "${host_os}" in
SYS=mingw32
AC_CHECK_TOOL(WINDRES, windres, :)
AC_CHECK_TOOL(OBJCOPY, objcopy, :)
AH_TOP([#if defined(_WIN32) && !defined(_WIN32_WINNT)])
AH_TOP([# define _WIN32_WINNT 0x0502 /* Windows XP SP2 */])
AH_TOP([#endif])
AC_DEFINE([_WIN32_IE], 0x0600, [Define to '0x0600' for IE 6.0 (and shell) APIs.])
AC_DEFINE([_UNICODE], [1], [Define to 1 for Unicode (Wide Chars) APIs.])
AC_DEFINE([UNICODE], [1], [Define to 1 for Unicode (Wide Chars) APIs.])
AC_DEFINE([_ISOC99_SOURCE], [1], [Extensions to ISO C89 from ISO C99.])
......@@ -77,8 +73,8 @@ case "${host_os}" in
AC_DEFINE([_XOPEN_SOURCE_EXTENDED], [1], [XPG things and X/Open Unix extensions.])
AC_DEFINE([_BSD_SOURCE], [1], [ISO C, POSIX, and 4.3BSD things.])
AC_DEFINE([_SVID_SOURCE], [1], [ISO C, POSIX, and SVID things.])
LDFLAGS="${LDFLAGS} -Wl,--nxcompat -Wl,--no-seh -Wl,--dynamicbase"
CPPFLAGS+="-D_WIN32_WINNT=0x0601 -DWINVER=0x0601"
LDFLAGS+="-no-undefined -avoid-version -Wl,--nxcompat -Wl,--dynamicbase"
ac_default_prefix="`pwd`/_win32"
DESTDIR="`pwd`/_win32/"
AC_SUBST(WINDOWS_ARCH)
......@@ -218,6 +214,11 @@ AS_IF([test -n "${CONTRIB_DIR}"], [
CFLAGS="${CFLAGS} -I${CONTRIB_DIR}/include"
CXXFLAGS="${CXXFLAGS} -I${CONTRIB_DIR}/include"
OBJCFLAGS="${OBJCFLAGS} -I${CONTRIB_DIR}/include"
AS_IF([test "${SYS}" = "mingw32"],[
PKG_CONFIG_PATH_CUSTOM="${CONTRIB_DIR}/lib/pkgconfig:${CONTRIB_DIR}/lib64/pkgconfig"
AC_SUBST(PKG_CONFIG_PATH_CUSTOM)
export PKG_CONFIG_PATH_CUSTOM
])
export PKG_CONFIG_PATH="${CONTRIB_DIR}/lib/pkgconfig:${CONTRIB_DIR}/lib64/pkgconfig:$PKG_CONFIG_PATH"
LDFLAGS="${LDFLAGS} -L${CONTRIB_DIR}/lib"
......@@ -301,6 +302,22 @@ AS_IF([test "x$have_jack" = "xyes"],,
])
])
dnl check for libportaudio
AS_IF([test "${SYS}" = "mingw32"],[
AC_ARG_WITH([portaudio], [AS_HELP_STRING([--without-portaudio],
[disable support for portaudio])], [], [with_portaudio=yes])
AS_IF([test "x$with_portaudio" = "xyes"],
[PKG_CHECK_MODULES(PORTAUDIO, [portaudio-2.0],
[AC_DEFINE([HAVE_PORTAUDIO], 1, [Define if you have portaudio])],
[AC_MSG_WARN([Missing libportaudio development files])
AC_DEFINE([HAVE_PORTAUDIO], 0, [Define if you have portaudio])
])
])
])
AM_CONDITIONAL(BUILD_PORTAUDIO, test "x$with_portaudio" = "xyes")
AM_CONDITIONAL(HAVE_PORTAUDIO, test "x$with_portaudio" = "xyes")
AC_DEFINE_UNQUOTED([HAVE_JACK], `if test "x$have_jack" = "xyes"; then echo 1; else echo 0; fi`, [Define if you have jack])
AM_CONDITIONAL(BUILD_JACK, test "x$have_jack" = "xyes")
......@@ -572,7 +589,7 @@ dnl debug mode is default-disabled
AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [Build in debug mode, adds stricter warnings, disables optimization]))
AS_IF([test "x$enable_debug" = "xyes"],
[CXXFLAGS="${CXXFLAGS} -g -Wall -Wextra -Wnon-virtual-dtor -O0"])
[CXXFLAGS="${CXXFLAGS} -g -fno-omit-frame-pointer -Wall -Wextra -Wnon-virtual-dtor -O0"])
dnl What Makefiles to generate
......@@ -591,6 +608,7 @@ AC_CONFIG_FILES([Makefile \
src/media/audio/opensl/Makefile \
src/media/audio/jack/Makefile \
src/media/audio/coreaudio/Makefile \
src/media/audio/portaudio/Makefile \
src/media/audio/sound/Makefile \
src/config/Makefile \
src/client/Makefile \
......@@ -598,6 +616,7 @@ AC_CONFIG_FILES([Makefile \
src/media/video/Makefile \
src/media/video/v4l2/Makefile \
src/media/video/osxvideo/Makefile \
src/media/video/winvideo/Makefile \
src/media/video/test/Makefile \
src/upnp/Makefile \
test/Makefile \
......
FFMPEG_HASH := f90c9bbbca32620a9cb78898a2b1b7d2cce9ad0f
FFMPEG_GITURL := https://github.com/FFmpeg/FFmpeg.git
ifdef HAVE_WIN32
PKGS += ffmpeg
endif
FFMPEGCONF = \
--cc="$(CC)" \
--pkg-config="$(PKG_CONFIG)"
#disable everything
FFMPEGCONF += \
--disable-everything \
--enable-zlib \
--enable-gpl \
--enable-swscale \
--enable-protocols \
--disable-programs \
--disable-sdl
#enable muxers/demuxers
FFMPEGCONF += \
--enable-demuxers \
--enable-muxers
#enable parsers
FFMPEGCONF += \
--enable-parser=h263 \
--enable-parser=h264 \
--enable-parser=mpeg4video \
--enable-parser=vp8
#librairies
FFMPEGCONF += \
--enable-libx264 \
--enable-libvpx
#encoders/decoders
FFMPEGCONF += \
--enable-encoder=adpcm_g722 \
--enable-decoder=adpcm_g722 \
--enable-encoder=rawvideo \
--enable-decoder=rawvideo \
--enable-encoder=libx264 \
--enable-decoder=h264 \
--enable-encoder=pcm_alaw \
--enable-decoder=pcm_alaw \
--enable-encoder=pcm_mulaw \
--enable-decoder=pcm_mulaw \
--enable-encoder=mpeg4 \
--enable-decoder=mpeg4 \
--enable-encoder=libvpx_vp8 \
--enable-decoder=vp8 \
--enable-encoder=h263 \
--enable-decoder=h263 \
--enable-encoder=mjpeg \
--enable-decoder=mjpeg \
--enable-decoder=mjpegb \
FFMPEGCONF += \
--enable-indev=dshow \
--enable-dxva2
# There is an unresolved symbol for speex when linking statically
ifndef HAVE_WIN32
FFMPEGCONF += \
--enable-libspeex \
--enable-libopus \
--enable-encoder=libspeex \
--enable-decoder=libspeex
endif
DEPS_ffmpeg = iconv zlib x264 vpx opus speex $(DEPS_vpx)
ifdef HAVE_CROSS_COMPILE
FFMPEGCONF += --cross-prefix=$(HOST)-
endif
# x86 stuff
ifeq ($(ARCH),i386)
FFMPEGCONF += --arch=x86
endif
ifeq ($(ARCH),x86_64)
FFMPEGCONF += --arch=x86_64
endif
# Windows
ifdef HAVE_WIN32
FFMPEGCONF += --target-os=mingw32 --enable-memalign-hack
FFMPEGCONF += --enable-w32threads --disable-decoder=dca
endif
ifeq ($(call need_pkg,"ffmpeg >= 2.6.1"),)
PKGS_FOUND += ffmepg
endif
$(TARBALLS)/ffmpeg-$(FFMPEG_HASH).tar.xz:
$(call download_git,$(FFMPEG_GITURL),release/2.6, $(FFMPEG_HASH))
.sum-ffmpeg: ffmpeg-$(FFMPEG_HASH).tar.xz
$(warning Not implemented.)
touch $@
ffmpeg: ffmpeg-$(FFMPEG_HASH).tar.xz .sum-ffmpeg
rm -Rf $@ $@-$(FFMPEG_HASH)
mkdir -p $@-$(FFMPEG_HASH)
(cd $@-$(FFMPEG_HASH) && tar xv --strip-components=1 -f ../$<)
$(UPDATE_AUTOCONFIG)
$(MOVE)
.ffmpeg: ffmpeg
cd $< && $(HOSTVARS) ./configure \
--extra-ldflags="$(LDFLAGS)" $(FFMPEGCONF) \
--prefix="$(PREFIX)" --enable-static --disable-shared
cd $< && $(MAKE) install-libs install-headers
touch $@
......@@ -41,12 +41,22 @@ ifeq ($(ARCH)-$(HAVE_WIN32),x86_64-1)
HAVE_WIN64 := 1
endif
ifdef HAVE_CROSS_COMPILE
PKG_CONFIG ?= $(HOST)-pkg-config --static
PKG_CONFIG_PATH_CUSTOM = $(PREFIX)/lib/pkgconfig
export PKG_CONFIG_PATH_CUSTOM
else
PKG_CONFIG ?= pkg-config
endif
PKG_CONFIG_PATH := $(PKG_CONFIG_PATH):$(PREFIX)/lib/pkgconfig
export PKG_CONFIG_PATH
ifdef HAVE_CROSS_COMPILE
need_pkg = 1
else
need_pkg = $(shell $(PKG_CONFIG) $(1) || echo 1)
endif
#
# Default values for tools
#
......@@ -147,6 +157,7 @@ ifdef HAVE_WIN32
ifneq ($(shell $(CC) $(CFLAGS) -E -dM -include _mingw.h - < /dev/null | grep -E __MINGW64_VERSION_MAJOR),)
HAVE_MINGW_W64 := 1
endif
EXTRA_CXXFLAGS += -std=c++11
endif
ifdef HAVE_SOLARIS
......@@ -186,16 +197,7 @@ endif
ACLOCAL_AMFLAGS += -I$(PREFIX)/share/aclocal
export ACLOCAL_AMFLAGS
PKG_CONFIG ?= pkg-config
ifdef HAVE_CROSS_COMPILE
# This inhibits .pc file from within the cross-compilation toolchain sysroot.
# Hopefully, nobody ever needs that.
PKG_CONFIG_PATH := /usr/share/pkgconfig
PKG_CONFIG_LIBDIR := /usr/$(HOST)/lib/pkgconfig
export PKG_CONFIG_LIBDIR
endif
PKG_CONFIG_PATH := $(PKG_CONFIG_PATH):$(PREFIX)/lib/pkgconfig
export PKG_CONFIG_PATH
ifndef GIT
ifeq ($(shell git --version >/dev/null 2>&1 || echo FAIL),)
......@@ -268,7 +270,7 @@ HOSTCONF += --enable-static --disable-shared
endif
ifdef HAVE_WIN32
HOSTCONF += --without-pic
HOSTCONF += --enable-static --disable-shared --without-pic
PIC :=
else
HOSTCONF += --with-pic
......
--- pjproject/pjlib/include/pj/errno.h 2013-04-04 23:02:19.000000000 -0400
+++ pjproject/pjlib/include/pj/errno.h 2015-02-27 12:21:24.171567801 -0500
@@ -432,6 +432,11 @@
* Socket is stopped
*/
#define PJ_ESOCKETSTOP (PJ_ERRNO_START_STATUS + 24)/* 70024 */
+/**
+ * @hideinitializer
+ * There is no data available right now, try again later.
+ */
+#define PJ_EAGAIN (PJ_ERRNO_START_STATUS + 25)/* 70025 */
/** @} */ /* pj_errnum */
......@@ -83,7 +83,7 @@ index a296266..03f727f 100755
+$as_echo "Using SSL prefix... $with_ssl" >&6; }
+ fi
+ if test "x$ssl_backend" = "xgnutls"; then
+ for ac_prog in pkg-config "python pkgconfig.py"
+ for ac_prog in ${host}-pkg-config pkg-config "python pkgconfig.py"
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
......@@ -330,7 +330,7 @@ index cd71a7a..465285e 100644
+ fi
+ if test "x$ssl_backend" = "xgnutls"; then
+ AC_CHECK_PROGS(PKG_CONFIG,
+ pkg-config "python pkgconfig.py",
+ $host-pkg-config pkg-config "python pkgconfig.py",
+ none)
+ AC_MSG_RESULT([checking for GnuTLS installations..])
+ AC_SUBST(gnutls_h_present)
......@@ -1062,7 +1062,7 @@ index 0000000..7b4b941
+ if (circ_write(&ssock->circ_buf_output, data, len) != PJ_SUCCESS) {
+ pj_lock_release(ssock->circ_buf_output_mutex);
+
+ errno = ENOMEM;
+ errno = PJ_ENOMEM;
+ return -1;
+ }
+
......@@ -1085,7 +1085,7 @@ index 0000000..7b4b941
+ pj_lock_release(ssock->circ_buf_input_mutex);
+
+ /* Data buffers not yet filled */
+ errno = EAGAIN;
+ errno = PJ_EAGAIN;
+ return -1;
+ }
+
......
......@@ -23,6 +23,9 @@ PJPROJECT_OPTIONS := --disable-oss \
ifdef HAVE_ANDROID
PJPROJECT_OPTIONS += --with-ssl=$(PREFIX)
endif
ifdef HAVE_WIN32
PJPROJECT_OPTIONS += --with-ssl=$(PREFIX)
endif
PJPROJECT_EXTRA_CFLAGS = -DPJ_ICE_MAX_CAND=32 -DPJ_ICE_MAX_CHECKS=150 -DPJ_ICE_COMP_BITS=2
......@@ -50,6 +53,7 @@ ifdef HAVE_WIN32
$(APPLY) $(SRC)/pjproject/intptr_t.patch
$(APPLY) $(SRC)/pjproject/pj_win.patch
endif
$(APPLY) $(SRC)/pjproject/errno.patch
$(APPLY) $(SRC)/pjproject/aconfigureupdate.patch
$(APPLY) $(SRC)/pjproject/endianness.patch
$(APPLY) $(SRC)/pjproject/unknowncipher.patch
......
078adfdc2cec7fbd4019837eee65f8411b873b51064dfd7334e1c55118c26ea1fb68cb22e46ee69adb69c78d026b00a7ed973c40632e7d79703e12669a62ee3e portaudio-v19_20140130.tgz
\ No newline at end of file
# PortAudio
PORTAUDIO_VERSION := v19_20140130
PORTAUDIO_URL := http://www.portaudio.com/archives/pa_stable_$(PORTAUDIO_VERSION).tgz
ifdef HAVE_WIN32
PKGS += portaudio
endif
ifeq ($(call need_pkg,"portaudio >= 2.0"),)
PKGS_FOUND += portaudio
endif
$(TARBALLS)/portaudio-$(PORTAUDIO_VERSION).tgz:
$(call download,$(PORTAUDIO_URL))
.sum-portaudio: portaudio-$(PORTAUDIO_VERSION).tgz
portaudio: portaudio-$(PORTAUDIO_VERSION).tgz .sum-portaudio
$(UNPACK)
.portaudio: portaudio
cd $< && $(HOSTVARS) ./configure $(HOSTCONF)
cd $< && $(MAKE) install
touch $@
......@@ -12,6 +12,10 @@ if HAVE_OSX
RING_VIDEO_LIBS+= \
./media/video/osxvideo/libosxvideo.la
endif
if HAVE_WIN32
RING_VIDEO_LIBS+= \
./media/video/winvideo/libwinvideo.la
endif
endif
if BUILD_INSTANT_MESSAGING
......@@ -66,6 +70,7 @@ libring_la_LDFLAGS = \
@YAMLCPP_LIBS@ \
@SPEEXDSP_LIBS@ \
@LIBUPNP_LIBS@ \
@PORTAUDIO_LIBS@ \
$(TLS_LIB) \
$(IAX_LIB) \
$(IM_LIB) \
......@@ -88,6 +93,7 @@ libring_la_CFLAGS = \
@LIBUPNP_CFLAGS@ \
@SPEEXDSP_CFLAGS@ \
@LIBUPNP_CFLAGS@ \
@PORTAUDIO_CFLAGS@ \
$(TLS_CFLAGS)
if USE_DHT
......@@ -143,6 +149,12 @@ libring_la_SOURCES = conference.cpp \
gnutls_support.h \
rational.h
if HAVE_WIN32
libring_la_SOURCES += \
dlfcn.c \
winsyslog.c
endif
nobase_include_HEADERS= dring/dring.h \
dring/security_const.h \
dring/callmanager_interface.h \
......
/*
* dlfcn-win32
* Copyright (c) 2007 Ramiro Polla
*
* dlfcn-win32 is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* dlfcn-win32 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with dlfcn-win32; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <windows.h>
#include <stdio.h>
#include "dlfcn.h"
/* Note:
* MSDN says these functions are not thread-safe. We make no efforts to have
* any kind of thread safety.
*/
typedef struct global_object {
HMODULE hModule;
struct global_object *previous;
struct global_object *next;
} global_object;
static global_object first_object;
/* These functions implement a double linked list for the global objects. */
static global_object *global_search( HMODULE hModule )
{
global_object *pobject;
if( hModule == NULL )
return NULL;
for( pobject = &first_object; pobject ; pobject = pobject->next )
if( pobject->hModule == hModule )
return pobject;
return NULL;
}
static void global_add( HMODULE hModule )
{
global_object *pobject;
global_object *nobject;
if( hModule == NULL )
return;
pobject = global_search( hModule );
/* Do not add object again if it's already on the list */
if( pobject )
return;
for( pobject = &first_object; pobject->next ; pobject = pobject->next );
nobject = malloc( sizeof(global_object) );
/* Should this be enough to fail global_add, and therefore also fail
* dlopen?
*/
if( !nobject )
return;
pobject->next = nobject;
nobject->next = NULL;
nobject->previous = pobject;
nobject->hModule = hModule;
}
static void global_rem( HMODULE hModule )
{
global_object *pobject;
if( hModule == NULL )
return;
pobject = global_search( hModule );
if( !pobject )
return;
if( pobject->next )
pobject->next->previous = pobject->previous;
if( pobject->previous )
pobject->previous->next = pobject->next;