diff --git a/INSTALL b/INSTALL
index 007e9396d0a2492cd2d6e17d42f359655dfe0b5e..2099840756e6302d837dcd51b5dcd6262f7adb16 100644
--- a/INSTALL
+++ b/INSTALL
@@ -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
diff --git a/Makefile.am b/Makefile.am
index 939db31e1d55e167a55d70579608444b376f082a..aed0bdd4a39d037f25d9e4987b9243750c9a425e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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 \
diff --git a/bin/Makefile.am b/bin/Makefile.am
index 96b12d76efd87a6c1e2930889a545f335815f35c..1d30d435c42108ab2659df9fcd547fa393a1f779 100644
--- a/bin/Makefile.am
+++ b/bin/Makefile.am
@@ -1,8 +1,10 @@
 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
diff --git a/bin/winmain.cpp b/bin/winmain.cpp
index 6addb4b3854f7103417e33fc4dcff7507589d278..992a7c92a116533e8becbb9f23bec0fba63b399a 100644
--- a/bin/winmain.cpp
+++ b/bin/winmain.cpp
@@ -1,10 +1,231 @@
-#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();
 }
diff --git a/configure.ac b/configure.ac
index d8371dbae0474491c96c69df7fde4f7068c80713..4ec4867309cf9cdcb91029ca66f456184182d4ec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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 \
diff --git a/contrib/src/ffmpeg/rules.mak b/contrib/src/ffmpeg/rules.mak
new file mode 100644
index 0000000000000000000000000000000000000000..7196653acc1617a04e1dcc4eddf0fe4f79fc4f85
--- /dev/null
+++ b/contrib/src/ffmpeg/rules.mak
@@ -0,0 +1,119 @@
+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 $@
diff --git a/contrib/src/main.mak b/contrib/src/main.mak
index 046be757a40aa8cac23fdf20377ba41f1b50038a..b16b6fac0ffdf22b8e479fc63519686bbd4876a3 100644
--- a/contrib/src/main.mak
+++ b/contrib/src/main.mak
@@ -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
diff --git a/contrib/src/pjproject/errno.patch b/contrib/src/pjproject/errno.patch
new file mode 100644
index 0000000000000000000000000000000000000000..357fb19c9417e7c5c0c3dfbd6ca808c039abb7b9
--- /dev/null
+++ b/contrib/src/pjproject/errno.patch
@@ -0,0 +1,13 @@
+--- 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 */
diff --git a/contrib/src/pjproject/gnutls.patch b/contrib/src/pjproject/gnutls.patch
index 2b2903fd6e5fbaa837960b6d0c6c8d1538a30b92..6330d077c9a8df73585d766dfbd7669adec48ecd 100644
--- a/contrib/src/pjproject/gnutls.patch
+++ b/contrib/src/pjproject/gnutls.patch
@@ -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;
 +    }
 +
diff --git a/contrib/src/pjproject/rules.mak b/contrib/src/pjproject/rules.mak
index e9bf51c0ca8c6d90cc91e4abe3a9e3ca63f4e811..a401cee89835ddd9aae46df767e49c72db25f43e 100644
--- a/contrib/src/pjproject/rules.mak
+++ b/contrib/src/pjproject/rules.mak
@@ -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
diff --git a/contrib/src/portaudio/SHA512SUMS b/contrib/src/portaudio/SHA512SUMS
new file mode 100644
index 0000000000000000000000000000000000000000..4f6479a77579eaae6259b7457e5222ce57d44ae0
--- /dev/null
+++ b/contrib/src/portaudio/SHA512SUMS
@@ -0,0 +1 @@
+078adfdc2cec7fbd4019837eee65f8411b873b51064dfd7334e1c55118c26ea1fb68cb22e46ee69adb69c78d026b00a7ed973c40632e7d79703e12669a62ee3e  portaudio-v19_20140130.tgz
\ No newline at end of file
diff --git a/contrib/src/portaudio/rules.mak b/contrib/src/portaudio/rules.mak
new file mode 100644
index 0000000000000000000000000000000000000000..c0db18a8b5b429e65e051e79bc96e7993bc3e775
--- /dev/null
+++ b/contrib/src/portaudio/rules.mak
@@ -0,0 +1,26 @@
+# 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 $@
diff --git a/src/Makefile.am b/src/Makefile.am
index 539e128e6e5af688d8ae90b2734ceb1ee186f375..fb02b72c8e3f68ce7e389b446a190513eec68f45 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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 \
diff --git a/src/dlfcn.c b/src/dlfcn.c
new file mode 100644
index 0000000000000000000000000000000000000000..3ade181716ff77c5c7273132f0bb4532c44a9f58
--- /dev/null
+++ b/src/dlfcn.c
@@ -0,0 +1,246 @@
+/*
+* 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;
+	free( pobject );
+}
+/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one
+* static buffer.
+* MSDN says the buffer cannot be larger than 64K bytes, so we set it to
+* the limit.
+*/
+static char error_buffer[65535];
+static char *current_error;
+static int copy_string( char *dest, int dest_size, const char *src )
+{
+	int i = 0;
+/* gcc should optimize this out */
+	if( !src || !dest )
+		return 0;
+	for( i = 0 ; i < dest_size-1 ; i++ )
+	{
+		if( !src[i] )
+			break;
+		else
+			dest[i] = src[i];
+	}
+	dest[i] = '\0';
+	return i;
+}
+static void save_err_str( const char *str )
+{
+	DWORD dwMessageId;
+	DWORD pos;
+	dwMessageId = GetLastError( );
+	if( dwMessageId == 0 )
+		return;
+/* Format error message to:
+* "<argument to function that failed>": <Windows localized error message>
+*/
+pos = copy_string( error_buffer, sizeof(error_buffer), "\"" );
+pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, str );
+pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, "\": " );
+pos += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId,
+	MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
+	error_buffer+pos, sizeof(error_buffer)-pos, NULL );
+if( pos > 1 )
+{
+/* POSIX says the string must not have trailing <newline> */
+	if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' )
+		error_buffer[pos-2] = '\0';
+}
+current_error = error_buffer;
+}
+static void save_err_ptr_str( const void *ptr )
+{
+char ptr_buf[19]; /* 0x<pointer> up to 64 bits. */
+	sprintf( ptr_buf, "0x%p", ptr );
+	save_err_str( ptr_buf );
+}
+void *dlopen( const char *file, int mode )
+{
+	HMODULE hModule;
+	UINT uMode;
+	current_error = NULL;
+/* Do not let Windows display the critical-error-handler message box */
+	uMode = SetErrorMode( SEM_FAILCRITICALERRORS );
+	if( file == 0 )
+	{
+/* POSIX says that if the value of file is 0, a handle on a global
+* symbol object must be provided. That object must be able to access
+* all symbols from the original program file, and any objects loaded
+* with the RTLD_GLOBAL flag.
+* The return value from GetModuleHandle( ) allows us to retrieve
+* symbols only from the original program file. For objects loaded with
+* the RTLD_GLOBAL flag, we create our own list later on.
+*/
+hModule = GetModuleHandle( NULL );
+if( !hModule )
+	save_err_ptr_str( file );
+}
+else
+{
+	char lpFileName[MAX_PATH];
+	int i;
+/* MSDN says backslashes *must* be used instead of forward slashes. */
+	for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ )
+	{
+		if( !file[i] )
+			break;
+		else if( file[i] == '/' )
+			lpFileName[i] = '\\';
+		else
+			lpFileName[i] = file[i];
+	}
+	lpFileName[i] = '\0';
+/* POSIX says the search path is implementation-defined.
+* LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely
+* to UNIX's search paths (start with system folders instead of current
+* folder).
+*/
+hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL,
+	LOAD_WITH_ALTERED_SEARCH_PATH );
+/* If the object was loaded with RTLD_GLOBAL, add it to list of global
+* objects, so that its symbols may be retrieved even if the handle for
+* the original program file is passed. POSIX says that if the same
+* file is specified in multiple invocations, and any of them are
+* RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the
+* symbols will remain global.
+*/
+if( !hModule )
+	save_err_str( lpFileName );
+else if( (mode & RTLD_GLOBAL) )
+	global_add( hModule );
+}
+/* Return to previous state of the error-mode bit flags. */
+SetErrorMode( uMode );
+return (void *) hModule;
+}
+int dlclose( void *handle )
+{
+	HMODULE hModule = (HMODULE) handle;
+	BOOL ret;
+	current_error = NULL;
+	ret = FreeLibrary( hModule );
+/* If the object was loaded with RTLD_GLOBAL, remove it from list of global
+* objects.
+*/
+if( ret )
+	global_rem( hModule );
+else
+	save_err_ptr_str( handle );
+/* dlclose's return value in inverted in relation to FreeLibrary's. */
+ret = !ret;
+return (int) ret;
+}
+void *dlsym( void *handle, const char *name )
+{
+	FARPROC symbol;
+	current_error = NULL;
+	symbol = GetProcAddress( handle, name );
+	if( symbol == NULL )
+	{
+		HMODULE hModule;
+/* If the handle for the original program file is passed, also search
+* in all globally loaded objects.
+*/
+hModule = GetModuleHandle( NULL );
+if( hModule == handle )
+{
+	global_object *pobject;
+	for( pobject = &first_object; pobject ; pobject = pobject->next )
+	{
+		if( pobject->hModule )
+		{
+			symbol = GetProcAddress( pobject->hModule, name );
+			if( symbol != NULL )
+				break;
+		}
+	}
+}
+}
+if( symbol == NULL )
+	save_err_str( name );
+return (void*) symbol;
+}
+char *dlerror( void )
+{
+	char *error_pointer = current_error;
+/* POSIX says that invoking dlerror( ) a second time, immediately following
+* a prior invocation, shall result in NULL being returned.
+*/
+current_error = NULL;
+return error_pointer;
+}
\ No newline at end of file
diff --git a/src/dlfcn.h b/src/dlfcn.h
new file mode 100644
index 0000000000000000000000000000000000000000..42ed6c6aba12d61586ccc346456f6d0f4e79543d
--- /dev/null
+++ b/src/dlfcn.h
@@ -0,0 +1,43 @@
+/*
+* 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
+*/
+#ifndef DLFCN_H
+#define DLFCN_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* POSIX says these are implementation-defined.
+* To simplify use with Windows API, we treat them the same way.
+*/
+#define RTLD_LAZY 0
+#define RTLD_NOW 0
+#define RTLD_GLOBAL (1 << 1)
+#define RTLD_LOCAL (1 << 2)
+/* These two were added in The Open Group Base Specifications Issue 6.
+* Note: All other RTLD_* flags in any dlfcn.h are not standard compliant.
+*/
+#define RTLD_DEFAULT 0
+#define RTLD_NEXT 0
+void *dlopen ( const char *file, int mode );
+int dlclose( void *handle );
+void *dlsym ( void *handle, const char *name );
+char *dlerror( void );
+#ifdef __cplusplus
+}
+#endif
+#endif /* DLFCN_H */
\ No newline at end of file
diff --git a/src/dring/account_const.h b/src/dring/account_const.h
index 7b6543c844182ecc28301c4ec80522f16818ab92..0ceb5a2da6a274318c028b92fe60adb0266903c0 100644
--- a/src/dring/account_const.h
+++ b/src/dring/account_const.h
@@ -31,6 +31,11 @@
 #ifndef DRING_ACCOUNT_H
 #define DRING_ACCOUNT_H
 
+//Defined in windows.h
+#ifdef ERROR
+#undef ERROR
+#endif
+
 namespace DRing {
 
 namespace Account {
diff --git a/src/fileutils.cpp b/src/fileutils.cpp
index b96bb745d4bfd6ad6ce8ab4c39589747847c4b3b..1b66b332ca4cd53cd203c88bf495137cb74dd5d0 100644
--- a/src/fileutils.cpp
+++ b/src/fileutils.cpp
@@ -47,8 +47,13 @@
 #include <signal.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <pwd.h>
-#ifndef __ANDROID__
+#ifndef _WIN32
+    #include <pwd.h>
+#else
+    #include <shlobj.h>
+    #define NAME_MAX 255
+#endif
+#if !defined __ANDROID__ && !defined _WIN32
 #   include <wordexp.h>
 #endif
 
@@ -71,7 +76,11 @@ bool check_dir(const char *path)
     DIR *dir = opendir(path);
 
     if (!dir) { // doesn't exist
+#ifndef _WIN32
         if (mkdir(path, 0755) != 0) {   // couldn't create the dir
+#else
+        if (recursive_mkdir(path) != true) {
+#endif
             perror(path);
             return false;
         }
@@ -97,6 +106,7 @@ const char *get_program_dir()
     return program_dir;
 }
 
+#ifndef _WIN32
 /* Lock a file region */
 static int
 lockReg(int fd, int cmd, int type, int whence, int start, off_t len)
@@ -159,11 +169,12 @@ create_pidfile()
 
     return f;
 }
+#endif // !_WIN32
 
 std::string
 expand_path(const std::string &path)
 {
-#ifdef __ANDROID__
+#if defined __ANDROID__ || defined WIN32
     RING_ERR("Path expansion not implemented, returning original");
     return path;
 #else
@@ -276,7 +287,11 @@ readDirectory(const std::string& dir)
     dirent* entry;
 
     std::vector<std::string> files;
+#ifndef _WIN32
     while (!readdir_r(dp, reinterpret_cast<dirent*>(buf.data()), &entry) && entry) {
+#else
+    while ((entry = readdir(dp)) != nullptr) {
+#endif
         const std::string fname {entry->d_name};
         if (fname == "." || fname == "..")
             continue;
@@ -323,7 +338,16 @@ get_cache_dir()
 std::string
 get_home_dir()
 {
-#ifdef __ANDROID__
+#if defined __ANDROID__
+    return get_program_dir();
+#elif defined _WIN32
+    WCHAR path[MAX_PATH];
+    if (SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_PROFILE, nullptr, 0, path))) {
+        char tmp[MAX_PATH];
+        char DefChar = ' ';
+        WideCharToMultiByte(CP_ACP, 0, path, -1, tmp, MAX_PATH, &DefChar, nullptr);
+        return std::string(tmp);
+    }
     return get_program_dir();
 #else
 
@@ -365,4 +389,22 @@ get_data_dir()
 #endif
 }
 
+#ifdef _WIN32
+bool
+recursive_mkdir(const std::string& path)
+{
+    if (mkdir(path.data()) != 0) {
+        if (errno == ENOENT) {
+            recursive_mkdir(path.substr(0, path.find_last_of(DIR_SEPARATOR_STR)));
+        } else if (errno != EEXIST) {
+            if (mkdir(path.data()) != 0) {
+                RING_ERR("Could not create directory.");
+                return false;
+            }
+        }
+    }
+    return true;
+}
+#endif // !_WIN32
+
 }} // namespace ring::fileutils
diff --git a/src/fileutils.h b/src/fileutils.h
index b1558e6f21caed7590ca41ea54dffd613e835aad..192fba01223acec7e42e54ae82fae53cca660bdb 100644
--- a/src/fileutils.h
+++ b/src/fileutils.h
@@ -44,8 +44,13 @@
 #define PIDFILE ".ring.pid"
 
 
+#ifndef _WIN32
 #define DIR_SEPARATOR_STR "/"   // Directory separator char
 #define DIR_SEPARATOR_CH  '/'  // Directory separator string
+#else
+#define DIR_SEPARATOR_STR "\\"   // Directory separator char
+#define DIR_SEPARATOR_CH  '\\'  // Directory separator string
+#endif
 
 namespace ring { namespace fileutils {
 
@@ -58,6 +63,10 @@ namespace ring { namespace fileutils {
     std::string expand_path(const std::string &path);
     bool isDirectoryWritable(const std::string &directory);
 
+#ifdef _WIN32
+    bool recursive_mkdir(const std::string& path);
+#endif
+
     /**
      * Read content of the directory.
      * The result is a list of full paths of files in the directory,
diff --git a/src/ip_utils.cpp b/src/ip_utils.cpp
index 422f67a457b3246032e60c83b4b22d472eb05475..dfd6ad600d69b156328eeb95125bbd2b7677fa79 100644
--- a/src/ip_utils.cpp
+++ b/src/ip_utils.cpp
@@ -34,16 +34,14 @@
 
 #include "sip/sip_utils.h"
 
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-
-#include <netdb.h>
-#include <net/if.h>
 #include <sys/types.h>
-#include <sys/ioctl.h>
 #include <unistd.h>
 
+#ifdef _WIN32
+#define InetPtonA inet_pton
+WINSOCK_API_LINKAGE INT WSAAPI InetPtonA(INT Family, LPCSTR pStringBuf, PVOID pAddr);
+#endif
+
 namespace ring {
 
 std::vector<IpAddr>
@@ -141,6 +139,7 @@ ip_utils::getInterfaceAddr(const std::string &interface, pj_uint16_t family)
     const auto unix_family = family == pj_AF_INET() ? AF_INET : AF_INET6;
     IpAddr addr = {};
 
+#ifndef _WIN32
     int fd = socket(unix_family, SOCK_DGRAM, 0);
     if (fd < 0) {
         RING_ERR("Could not open socket: %m");
@@ -170,6 +169,35 @@ ip_utils::getInterfaceAddr(const std::string &interface, pj_uint16_t family)
     addr = ifr.ifr_addr;
     if (addr.isUnspecified())
         return getLocalAddr(addr.getFamily());
+#else // _WIN32
+    struct addrinfo hints;
+    struct addrinfo *result = NULL;
+    struct sockaddr_in  *sockaddr_ipv4;
+    struct sockaddr_in6 *sockaddr_ipv6;
+
+    ZeroMemory(&hints, sizeof(hints));
+
+    DWORD dwRetval = getaddrinfo(interface.c_str(), "0", &hints, &result);
+    if (dwRetval != 0) {
+        RING_ERR("getaddrinfo failed with error: %d", dwRetval);
+        return addr;
+    }
+
+    switch (result->ai_family) {
+        sockaddr_ipv4 = (struct sockaddr_in *) result->ai_addr;
+        addr = sockaddr_ipv4->sin_addr;
+        break;
+        case AF_INET6:
+        sockaddr_ipv6 = (struct sockaddr_in6 *) result->ai_addr;
+        addr = sockaddr_ipv6->sin6_addr;
+        break;
+        default:
+        break;
+    }
+
+    if (addr.isUnspecified())
+            return getLocalAddr(addr.getFamily());
+#endif // !_WIN32
 
     return addr;
 }
@@ -177,11 +205,11 @@ ip_utils::getInterfaceAddr(const std::string &interface, pj_uint16_t family)
 std::vector<std::string>
 ip_utils::getAllIpInterfaceByName()
 {
-    static ifreq ifreqs[20];
-    ifconf ifconf;
-
     std::vector<std::string> ifaceList;
     ifaceList.push_back("default");
+#ifndef _WIN32
+    static ifreq ifreqs[20];
+    ifconf ifconf;
 
     ifconf.ifc_buf = (char*) (ifreqs);
     ifconf.ifc_len = sizeof(ifreqs);
@@ -196,6 +224,9 @@ ip_utils::getAllIpInterfaceByName()
         close(sock);
     }
 
+#else
+        RING_ERR("Not implemented yet. (iphlpapi.h problem)");
+#endif
     return ifaceList;
 }
 
@@ -222,7 +253,7 @@ std::vector<IpAddr>
 ip_utils::getLocalNameservers()
 {
     std::vector<IpAddr> res;
-#ifdef __ANDROID__
+#if defined __ANDROID__ || defined _WIN32
 #warning "Not implemented"
 #else
     if (not (_res.options & RES_INIT))
diff --git a/src/ip_utils.h b/src/ip_utils.h
index ee23b5c36237b337e85b09053daa50a4405a910f..4adaba22f1a3a2bbfa60602c33ae3c8a41b7521f 100644
--- a/src/ip_utils.h
+++ b/src/ip_utils.h
@@ -34,7 +34,28 @@
 
 #include <pjlib.h>
 
-#include <netinet/ip.h>
+#ifdef _WIN32
+    #include <ws2tcpip.h>
+    #include <config.h>
+    #include <winsock2.h>
+
+    //define in mingw
+    #ifdef interface
+    #undef interface
+    #endif
+    #ifdef s_addr
+    #undef s_addr
+    #endif
+#else
+    #include <arpa/inet.h>
+    #include <netinet/in.h>
+    #include <arpa/nameser.h>
+    #include <resolv.h>
+    #include <netdb.h>
+    #include <netinet/ip.h>
+    #include <net/if.h>
+    #include <sys/ioctl.h>
+#endif
 
 #include <string>
 #include <vector>
diff --git a/src/logger.c b/src/logger.c
index 9dd07e0cb45a3c755e84b4f2146cfaf5b6ec6f5e..9200c49d34d3476482785095fbe38168dbba1e78 100644
--- a/src/logger.c
+++ b/src/logger.c
@@ -38,6 +38,10 @@
 static int consoleLog;
 static int debugMode;
 
+#ifdef WIN32
+#include "winsyslog.h"
+#endif
+
 void logger(const int level, const char* format, ...)
 {
     if (!debugMode && level == LOG_DEBUG)
@@ -51,11 +55,21 @@ void logger(const int level, const char* format, ...)
 
 void vlogger(const int level, const char *format, va_list ap)
 {
+#ifdef WIN32
+    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+    CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
+    WORD saved_attributes;
+#endif
+
     if (!debugMode && level == LOG_DEBUG)
         return;
 
     if (consoleLog) {
+#ifndef _WIN32
         const char *color_prefix = "";
+#else
+        WORD color_prefix = FOREGROUND_GREEN;
+#endif
 
         switch (level) {
             case LOG_ERR:
@@ -66,9 +80,23 @@ void vlogger(const int level, const char *format, va_list ap)
                 break;
         }
 
+#ifndef _WIN32
         fputs(color_prefix, stderr);
+#else
+        GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
+        saved_attributes = consoleInfo.wAttributes;
+        SetConsoleTextAttribute(hConsole, color_prefix);
+#endif
+
         vfprintf(stderr, format, ap);
+
+#ifndef _WIN32
         fputs(END_COLOR"\n", stderr);
+#else
+        fputs("\n", stderr);
+        SetConsoleTextAttribute(hConsole, saved_attributes);
+#endif
+
     } else {
         vsyslog(level, format, ap);
     }
diff --git a/src/logger.h b/src/logger.h
index 379d9d7a1156ef34028fab1934fc9275940949d6..2658d3cadf0522d13547021845454ee29e171df5 100644
--- a/src/logger.h
+++ b/src/logger.h
@@ -73,8 +73,8 @@ void strErr();
                            ##__VA_ARGS__
 #else
 
-#define LOG_FORMAT(M, ...) "%s:%d: " M, FILE_NAME, __LINE__, \
-                           ##__VA_ARGS__
+#define LOG_FORMAT(M, ...) "%s:%d: " M, FILE_NAME , __LINE__, \
+                            ##__VA_ARGS__
 #endif
 
 #ifdef __ANDROID__
@@ -98,14 +98,18 @@ void strErr();
 #define LOGGER(M, LEVEL, ...) __android_log_print(LEVEL, APP_NAME, \
                                                   LOG_FORMAT(M, ##__VA_ARGS__))
 
-/* TODO: WINDOWS, Actually implement logging system. */
-#elif defined _WIN32
-#define LOG_ERR     0
-#define LOG_WARNING 1
-#define LOG_INFO    2
-#define LOG_DEBUG   3
+#elif _WIN32
+
+#include "winsyslog.h"
 
-#define LOGGER(M, LEVEL, ...) printf(M, ##__VA_ARGS__)
+#define LOG_ERR     EVENTLOG_ERROR_TYPE
+#define LOG_WARNING EVENTLOG_WARNING_TYPE
+#define LOG_INFO    EVENTLOG_INFORMATION_TYPE
+#define LOG_DEBUG   EVENTLOG_SUCCESS
+
+#define FILE_NAME __FILE__
+
+#define LOGGER(M, LEVEL, ...) logger(LEVEL, LOG_FORMAT(M, ##__VA_ARGS__))
 
 #else
 
@@ -122,9 +126,7 @@ void strErr();
 #define RING_INFO(M, ...)    LOGGER(M, LOG_INFO, ##__VA_ARGS__)
 #define RING_DBG(M, ...)   LOGGER(M, LOG_DEBUG, ##__VA_ARGS__)
 
-
 #define BLACK "\033[22;30m"
-#define RED "\033[22;31m"
 #define GREEN "\033[22;32m"
 #define BROWN "\033[22;33m"
 #define BLUE "\033[22;34m"
@@ -134,13 +136,20 @@ void strErr();
 #define DARK_GREY "\033[01;30m"
 #define LIGHT_RED "\033[01;31m"
 #define LIGHT_SCREEN "\033[01;32m"
-#define YELLOW "\033[01;33m"
 #define LIGHT_BLUE "\033[01;34m"
 #define LIGHT_MAGENTA "\033[01;35m"
 #define LIGHT_CYAN "\033[01;36m"
 #define WHITE "\033[01;37m"
 #define END_COLOR "\033[0m"
 
+#ifndef _WIN32
+#define RED "\033[22;31m"
+#define YELLOW "\033[01;33m"
+#else
+#define RED FOREGROUND_RED
+#define YELLOW FOREGROUND_RED + FOREGROUND_GREEN
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp
index f217e59546c38923dfc78449bdeee57d07795734..e3a9a07c45e1f4e91972e99573c467bb4e300d00 100644
--- a/src/managerimpl.cpp
+++ b/src/managerimpl.cpp
@@ -2000,7 +2000,11 @@ ManagerImpl::retrieveConfigPath() const
     if (not xdg_env.empty())
         configdir = xdg_env + DIR_SEPARATOR_STR + PACKAGE;
 
+#ifndef _WIN32
     if (mkdir(configdir.data(), 0700) != 0) {
+#else
+    if (fileutils::recursive_mkdir(configdir.data()) != true) {
+#endif
         // If directory creation failed
         if (errno != EEXIST)
             RING_DBG("Cannot create directory: %s!", configdir.c_str());
diff --git a/src/media/Makefile.am b/src/media/Makefile.am
index ec6072a4fc88b0b2d0b4a0fb1c1307703b5d1d2f..730b78c04ff3f6de564a3dade1b9ff61d02d7203 100644
--- a/src/media/Makefile.am
+++ b/src/media/Makefile.am
@@ -43,6 +43,10 @@ endif
 
 libmedia_la_LDFLAGS = @LIBAVCODEC_LIBS@ @LIBAVFORMAT_LIBS@ @LIBAVDEVICE_LIBS@ @LIBSWSCALE_LIBS@ @LIBAVUTIL_LIBS@
 
+if HAVE_WIN32
+libmedia_la_LDFLAGS += -lws2_32 -lwsock32
+endif
+
 AM_CFLAGS=@LIBAVCODEC_CFLAGS@ @LIBAVFORMAT_CFLAGS@ @LIBAVDEVICE_CFLAGS@ @LIBSWSCALE_CFLAGS@
 
 AM_CXXFLAGS=@LIBAVCODEC_CFLAGS@ @LIBAVFORMAT_CFLAGS@ @LIBAVDEVICE_CFLAGS@ @LIBSWSCALE_CFLAGS@
diff --git a/src/media/audio/Makefile.am b/src/media/audio/Makefile.am
index d39e5851b2e1025f296acff9bc4c5d189e5ff922..85e2686cfbf3abd50a9583e3cb46c78bd064e749 100644
--- a/src/media/audio/Makefile.am
+++ b/src/media/audio/Makefile.am
@@ -24,6 +24,10 @@ if HAVE_OSX
 SUBDIRS += coreaudio
 endif
 
+if HAVE_PORTAUDIO
+SUBDIRS += portaudio
+endif
+
 if BUILD_SPEEXDSP
 RING_SPEEXDSP_SRC=dsp.cpp
 RING_SPEEXDSP_HEAD=dsp.h
@@ -89,3 +93,8 @@ if BUILD_OPENSL
 libaudio_la_LIBADD += ./opensl/libopensl.la
 libaudio_la_LDFLAGS += -lOpenSLES
 endif
+
+if BUILD_PORTAUDIO
+libaudio_la_LIBADD += ./portaudio/libportaudiolayer.la
+libaudio_la_LDFLAGS += @PORTAUDIO_LIBS@
+endif
diff --git a/src/media/audio/audiolayer.h b/src/media/audio/audiolayer.h
index 78fad4f1d386cd351517bf5502a47b4dbb0a2d47..97ba7297916abc7bfbba4ccdd8ff2684a6a88cb2 100644
--- a/src/media/audio/audiolayer.h
+++ b/src/media/audio/audiolayer.h
@@ -53,6 +53,7 @@
 #define ALSA_API_STR                "alsa"
 #define JACK_API_STR                "jack"
 #define COREAUDIO_API_STR           "coreaudio"
+#define PORTAUDIO_API_STR           "portaudio"
 
 #define PCM_DEFAULT "default"         // Default ALSA plugin
 #define PCM_DSNOOP  "plug:dsnoop"     // Alsa plugin for microphone sharing
diff --git a/src/media/audio/portaudio/Makefile.am b/src/media/audio/portaudio/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..a8fed9adfea088cb002dde553e556c62cd4b3997
--- /dev/null
+++ b/src/media/audio/portaudio/Makefile.am
@@ -0,0 +1,14 @@
+include $(top_srcdir)/globals.mak
+
+if BUILD_PORTAUDIO
+
+noinst_LTLIBRARIES = libportaudiolayer.la
+
+libportaudiolayer_la_SOURCES = \
+		portaudiolayer.cpp
+
+
+noinst_HEADERS = \
+		portaudiolayer.h
+
+endif
diff --git a/src/media/audio/portaudio/portaudiolayer.cpp b/src/media/audio/portaudio/portaudiolayer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0795a2d2dec2891e040ec24fa6f14e79b0966f17
--- /dev/null
+++ b/src/media/audio/portaudio/portaudiolayer.cpp
@@ -0,0 +1,446 @@
+/*
+ *  Copyright (C) 2004-2015 Savoir-Faire Linux Inc.
+ *  Author: Edric Ladent-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 3 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.
+ */
+
+#include "portaudiolayer.h"
+#include "manager.h"
+#include "noncopyable.h"
+#include "audio/resampler.h"
+#include "audio/ringbufferpool.h"
+#include "audio/ringbuffer.h"
+
+namespace ring {
+//FIXME: We should use WASAPi or DirectSound
+PortAudioLayer::PortAudioLayer(const AudioPreference &pref)
+    : AudioLayer(pref)
+    , indexIn_(pref.getAlsaCardin())
+    , indexOut_(pref.getAlsaCardout())
+    , indexRing_(pref.getAlsaCardring())
+    , playbackBuff_(0, audioFormat_)
+    , mainRingBuffer_(Manager::instance().getRingBufferPool().getRingBuffer(RingBufferPool::DEFAULT_ID))
+{
+    isStarted_ = false;
+    this->init();
+}
+
+PortAudioLayer::~PortAudioLayer()
+{
+    this->terminate();
+}
+
+std::vector<std::string>
+PortAudioLayer::getCaptureDeviceList() const
+{
+    return this->getDeviceByType(false);
+}
+
+std::vector<std::string>
+PortAudioLayer::getPlaybackDeviceList() const
+{
+    return this->getDeviceByType(true);
+}
+
+int
+PortAudioLayer::getAudioDeviceIndex(const std::string& name,
+    DeviceType type) const
+{
+
+    int numDevices = 0;
+    (void) type;
+
+    numDevices = Pa_GetDeviceCount();
+    if (numDevices < 0)
+        this->handleError(numDevices);
+    else {
+        const PaDeviceInfo *deviceInfo;
+        for (int i = 0; i < numDevices; i++) {
+            deviceInfo = Pa_GetDeviceInfo(i);
+            if (deviceInfo->name == name)
+                return i;
+        }
+    }
+    return -1;
+}
+
+std::string
+PortAudioLayer::getAudioDeviceName(int index, DeviceType type) const
+{
+    (void) type;
+    const PaDeviceInfo *deviceInfo;
+    deviceInfo = Pa_GetDeviceInfo(index);
+    return deviceInfo->name;
+}
+
+int
+PortAudioLayer::getIndexCapture() const
+{
+    return this->indexIn_;
+}
+
+int
+PortAudioLayer::getIndexPlayback() const
+{
+    return this->indexOut_;
+}
+
+int
+PortAudioLayer::getIndexRingtone() const
+{
+    return this->indexRing_;
+}
+
+void
+PortAudioLayer::startStream()
+{
+    if (isRunning_)
+        return;
+    this->initStream();
+    isRunning_ = isStarted_ = true;
+}
+
+void
+PortAudioLayer::stopStream()
+{
+
+    if (!isRunning_)
+        return;
+
+    RING_DBG("Stop PortAudio Streams");
+
+    //FIX ME : Abort or Stop ??
+    for (int i = 0; i < Direction::End; i++) {
+        auto err = Pa_AbortStream(streams[i]);
+        if(err != paNoError)
+            this->handleError(err);
+
+        err = Pa_CloseStream(streams[i]);
+        if (err != paNoError)
+            this->handleError(err);
+    }
+
+    isRunning_ = isStarted_ = false;
+
+    /* Flush the ring buffers */
+    flushUrgent();
+    flushMain();
+}
+
+void
+PortAudioLayer::updatePreference(AudioPreference &preference,
+    int index, DeviceType type)
+{
+    switch (type) {
+        case DeviceType::PLAYBACK:
+        preference.setAlsaCardout(index);
+        break;
+
+        case DeviceType::CAPTURE:
+        preference.setAlsaCardin(index);
+        break;
+
+        case DeviceType::RINGTONE:
+        preference.setAlsaCardring(index);
+        break;
+
+        default:
+        break;
+    }
+}
+
+std::vector<std::string>
+PortAudioLayer::getDeviceByType(const bool& playback) const
+{
+    std::vector<std::string> ret;
+    int numDevices = 0;
+
+    numDevices = Pa_GetDeviceCount();
+    if (numDevices < 0)
+        this->handleError(numDevices);
+    else {
+        for (int i = 0; i < numDevices; i++) {
+            const auto deviceInfo = Pa_GetDeviceInfo(i);
+            if (playback) {
+                if (deviceInfo->maxOutputChannels > 0)
+                    ret.push_back(deviceInfo->name);
+            } else {
+                if (deviceInfo->maxInputChannels > 0)
+                    ret.push_back(deviceInfo->name);
+            }
+        }
+    }
+    return ret;
+}
+
+int
+PortAudioLayer::paOutputCallback(const void *inputBuffer, void *outputBuffer,
+    unsigned long framesPerBuffer,
+    const PaStreamCallbackTimeInfo* timeInfo,
+    PaStreamCallbackFlags statusFlags,
+    void *userData)
+{
+
+    (void) inputBuffer;
+    (void) timeInfo;
+    (void) statusFlags;
+
+    auto ref = (PortAudioLayer*)userData;
+    auto out = (AudioSample*)outputBuffer;
+
+    AudioFormat mainBufferAudioFormat =
+        Manager::instance().getRingBufferPool().getInternalAudioFormat();
+    bool resample =
+        ref->audioFormat_.sample_rate != mainBufferAudioFormat.sample_rate;
+    auto urgentFramesToGet =
+        ref->urgentRingBuffer_.availableForGet(RingBufferPool::DEFAULT_ID);
+
+    if (urgentFramesToGet > 0) {
+        RING_WARN("Getting urgent frames.");
+        size_t totSample = std::min(framesPerBuffer,
+            (unsigned long)urgentFramesToGet);
+
+        ref->playbackBuff_.setFormat(ref->audioFormat_);
+        ref->playbackBuff_.resize(totSample);
+        ref->urgentRingBuffer_.get(ref->playbackBuff_, RingBufferPool::DEFAULT_ID);
+
+        ref->playbackBuff_.applyGain(ref->isPlaybackMuted_ ? 0.0 : ref->playbackGain_);
+
+        ref->playbackBuff_.interleave(out);
+
+        Manager::instance().getRingBufferPool().discard(totSample,
+            RingBufferPool::DEFAULT_ID);
+    }
+
+    unsigned normalFramesToGet =
+        Manager::instance().getRingBufferPool().availableForGet(RingBufferPool::DEFAULT_ID);
+    if (normalFramesToGet > 0) {
+        double resampleFactor = 1.0;
+        unsigned readableSamples = framesPerBuffer;
+
+        if (resample) {
+            resampleFactor =
+                static_cast<double>(ref->audioFormat_.sample_rate)
+                    / mainBufferAudioFormat.sample_rate;
+            readableSamples = std::ceil(framesPerBuffer / resampleFactor);
+        }
+
+        readableSamples = std::min(readableSamples, normalFramesToGet);
+
+        ref->playbackBuff_.setFormat(ref->audioFormat_);
+        ref->playbackBuff_.resize(readableSamples);
+        Manager::instance().getRingBufferPool().getData(ref->playbackBuff_,
+            RingBufferPool::DEFAULT_ID);
+        ref->playbackBuff_.applyGain(ref->isPlaybackMuted_ ? 0.0 : ref->playbackGain_);
+
+        if (resample) {
+            AudioBuffer resampledOutput(readableSamples, ref->audioFormat_);
+            ref->resampler_->resample(ref->playbackBuff_, resampledOutput);
+
+            resampledOutput.interleave(out);
+        } else {
+            ref->playbackBuff_.interleave(out);
+        }
+    }
+    if (normalFramesToGet <= 0) {
+        auto tone = Manager::instance().getTelephoneTone();
+        auto file_tone = Manager::instance().getTelephoneFile();
+
+        ref->playbackBuff_.setFormat(ref->audioFormat_);
+        ref->playbackBuff_.resize(framesPerBuffer);
+
+        if (tone) {
+            tone->getNext(ref->playbackBuff_, ref->playbackGain_);
+        } else if (file_tone) {
+            file_tone->getNext(ref->playbackBuff_, ref->playbackGain_);
+        } else {
+            //RING_WARN("No tone or file_tone!");
+            ref->playbackBuff_.reset();
+        }
+        ref->playbackBuff_.interleave(out);
+    }
+    return paContinue;
+}
+
+int
+PortAudioLayer::paInputCallback(const void *inputBuffer, void *outputBuffer,
+    unsigned long framesPerBuffer,
+    const PaStreamCallbackTimeInfo* timeInfo,
+    PaStreamCallbackFlags statusFlags,
+    void *userData)
+{
+
+    (void) outputBuffer;
+    (void) timeInfo;
+    (void) statusFlags;
+
+    auto ref = (PortAudioLayer*)userData;
+    auto in = (AudioSample*)inputBuffer;
+
+    if (framesPerBuffer == 0) {
+        RING_WARN("No frames for input.");
+        return paContinue;
+    }
+
+    const auto mainBufferFormat =
+        Manager::instance().getRingBufferPool().getInternalAudioFormat();
+    bool resample =
+        ref->audioInputFormat_.sample_rate != mainBufferFormat.sample_rate;
+
+    AudioBuffer inBuff(framesPerBuffer, ref->audioInputFormat_);
+
+    inBuff.deinterleave(in, framesPerBuffer, ref->audioInputFormat_.nb_channels);
+
+    inBuff.applyGain(ref->isCaptureMuted_ ? 0.0 : ref->captureGain_);
+
+    if (resample) {
+        auto outSamples =
+            framesPerBuffer
+            / (static_cast<double>(ref->audioInputFormat_.sample_rate)
+                / mainBufferFormat.sample_rate);
+        AudioBuffer out(outSamples, mainBufferFormat);
+        ref->inputResampler_->resample(inBuff, out);
+        ref->dcblocker_.process(out);
+        ref->mainRingBuffer_->put(out);
+    } else {
+        ref->dcblocker_.process(inBuff);
+        ref->mainRingBuffer_->put(inBuff);
+    }
+    return paContinue;
+}
+
+// PRIVATE METHOD
+void
+PortAudioLayer::handleError(const PaError& err) const
+{
+    RING_ERR("PortAudioLayer error : %s",  Pa_GetErrorText(err));
+}
+
+void
+PortAudioLayer::init()
+{
+    RING_DBG("Init PortAudioLayer");
+    const auto err = Pa_Initialize();
+    if (err != paNoError) {
+        this->handleError(err);
+        this->terminate();
+    }
+    //FIXME: Maybe find a better way
+    const PaDeviceInfo *outputDeviceInfo = Pa_GetDeviceInfo(indexOut_);
+    audioFormat_.nb_channels = outputDeviceInfo->maxOutputChannels;
+    audioFormat_.sample_rate = 48000;
+    hardwareFormatAvailable(audioFormat_);
+}
+
+void
+PortAudioLayer::terminate() const
+{
+    RING_DBG("PortAudioLayer terminate.");
+    const auto err = Pa_Terminate();
+    if (err != paNoError)
+        this->handleError(err);
+}
+
+void
+PortAudioLayer::initStream()
+{
+    dcblocker_.reset();
+
+    RING_DBG("Open PortAudio Output Stream");
+    PaStreamParameters outputParameters;
+    outputParameters.device = indexOut_;
+    RING_DBG("Index Device: %d", indexOut_);
+    if (outputParameters.device == paNoDevice) {
+        //TODO Should we fallback to default output device ?
+        RING_ERR("Error: No valid output device. There will be no sound.");
+    }
+    const auto outputDeviceInfo =
+        Pa_GetDeviceInfo(outputParameters.device);
+    RING_DBG("Default Sample Rate : %d", outputDeviceInfo->defaultSampleRate);
+    outputParameters.channelCount =
+        audioFormat_.nb_channels = outputDeviceInfo->maxOutputChannels;
+    //FIX ME : Default is 0....
+    audioFormat_.sample_rate = 48000;
+
+    outputParameters.sampleFormat = paInt16;
+    outputParameters.suggestedLatency = outputDeviceInfo->defaultLowOutputLatency;
+    outputParameters.hostApiSpecificStreamInfo = NULL;
+
+    PaError err = Pa_OpenStream(
+        &streams[Direction::Output],
+        NULL,
+        &outputParameters,
+        audioFormat_.sample_rate,
+        paFramesPerBufferUnspecified,
+        paNoFlag,
+        &PortAudioLayer::paOutputCallback,
+        this);
+    if(err != paNoError)
+        this->handleError(err);
+
+    RING_DBG("Open PortAudio Input Stream");
+    PaStreamParameters inputParameters;
+    inputParameters.device = indexIn_;
+    if (inputParameters.device == paNoDevice) {
+        //TODO Should we fallback to default output device ?
+        RING_ERR("Error: No valid input device. There will be no mic.");
+    }
+
+    const auto inputDeviceInfo =
+        Pa_GetDeviceInfo(inputParameters.device);
+    //FIX ME : Default is 0....
+    audioInputFormat_.sample_rate = 48000;
+    inputParameters.channelCount =
+        audioInputFormat_.nb_channels = inputDeviceInfo->maxInputChannels;
+    inputParameters.sampleFormat = paInt16;
+    inputParameters.suggestedLatency = inputDeviceInfo->defaultLowInputLatency;
+    inputParameters.hostApiSpecificStreamInfo = NULL;
+
+    err = Pa_OpenStream(
+        &streams[Direction::Input],
+        &inputParameters,
+        NULL,
+        audioInputFormat_.sample_rate,
+        paFramesPerBufferUnspecified,
+        paNoFlag,
+        &PortAudioLayer::paInputCallback,
+        this);
+
+    RING_DBG("Start PortAudio Streams");
+    for (int i = 0; i < Direction::End; i++) {
+        err = Pa_StartStream(streams[i]);
+        if (err != paNoError)
+            this->handleError(err);
+    }
+
+    hardwareFormatAvailable(audioFormat_);
+    hardwareInputFormatAvailable(audioInputFormat_);
+
+    flushUrgent();
+    flushMain();
+}
+} // namespace ring
diff --git a/src/media/audio/portaudio/portaudiolayer.h b/src/media/audio/portaudio/portaudiolayer.h
new file mode 100644
index 0000000000000000000000000000000000000000..a982c378eee96cb1dd1b3cf328797dd762787fe3
--- /dev/null
+++ b/src/media/audio/portaudio/portaudiolayer.h
@@ -0,0 +1,106 @@
+/*
+ *  Copyright (C) 2004-2015 Savoir-Faire Linux Inc.
+ *  Author: Edric Ladent-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 3 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.
+ */
+
+#ifndef PORTAUDIO_LAYER_H
+#define PORTAUDIO_LAYER_H
+
+#include <portaudio.h>
+
+#include "audio/audiolayer.h"
+#include "noncopyable.h"
+
+namespace ring {
+
+class PortAudioLayer : public AudioLayer {
+
+public:
+    PortAudioLayer(const AudioPreference &pref);
+    ~PortAudioLayer();
+
+    virtual std::vector<std::string> getCaptureDeviceList() const;
+    virtual std::vector<std::string> getPlaybackDeviceList() const;
+
+    virtual int getAudioDeviceIndex(const std::string& name, DeviceType type) const;
+    virtual std::string getAudioDeviceName(int index, DeviceType type) const;
+    virtual int getIndexCapture() const;
+    virtual int getIndexPlayback() const;
+    virtual int getIndexRingtone() const;
+
+    /**
+     * Start the capture stream and prepare the playback stream.
+     * The playback starts accordingly to its threshold
+     */
+    virtual void startStream();
+
+    /**
+     * Stop the playback and capture streams.
+     * Drops the pending frames and put the capture and playback handles to PREPARED state
+     */
+    virtual void stopStream();
+
+    virtual void updatePreference(AudioPreference &pref, int index, DeviceType type);
+
+ private:
+    NON_COPYABLE(PortAudioLayer);
+
+    void handleError(const PaError& err) const;
+    void init(void);
+    void terminate(void) const;
+    void initStream(void);
+    std::vector<std::string> getDeviceByType(const bool& playback) const;
+
+    PaDeviceIndex   indexIn_;
+    PaDeviceIndex   indexOut_;
+    PaDeviceIndex   indexRing_;
+
+    AudioBuffer playbackBuff_;
+
+    std::shared_ptr<RingBuffer> mainRingBuffer_;
+
+    bool isRunning_;
+
+    enum Direction {Input=0, Output=1, End=2};
+    PaStream*   streams[(int)Direction::End];
+
+    static int paOutputCallback(const void *inputBuffer, void* outputBuffer,
+                            unsigned long framesPerBuffer,
+                            const PaStreamCallbackTimeInfo* timeInfo,
+                            PaStreamCallbackFlags statusFlags,
+                            void *userData);
+
+    static int paInputCallback(const void *inputBuffer, void* outputBuffer,
+                            unsigned long framesPerBuffer,
+                            const PaStreamCallbackTimeInfo* timeInfo,
+                            PaStreamCallbackFlags statusFlags,
+                            void *userData);
+ };
+ }
+
+#endif
\ No newline at end of file
diff --git a/src/media/audio/sound/audiofile.cpp b/src/media/audio/sound/audiofile.cpp
index 113237d5293b252facb12494fc29536c26144252..5cc2dde353e7d9ac13b53d1d6cc4ac92e4ccd561 100644
--- a/src/media/audio/sound/audiofile.cpp
+++ b/src/media/audio/sound/audiofile.cpp
@@ -97,7 +97,7 @@ AudioFile::AudioFile(const std::string &fileName, unsigned int sampleRate) :
     if (!fileHandle)
         throw AudioFileException("File handle " + fileName + " could not be created");
     if (fileHandle.error()) {
-        RING_ERR("%s", fileHandle.strError());
+        RING_ERR("Error fileHandle: %s", fileHandle.strError());
         throw AudioFileException("File " + fileName + " doesn't exist");
     }
 
diff --git a/src/media/media_codec.h b/src/media/media_codec.h
index 181d0bf2bda7adcc5049f30604fc25bacdab44ca..e4ff91b39c1a99aa502b453d9a32c8d6d8150bde 100644
--- a/src/media/media_codec.h
+++ b/src/media/media_codec.h
@@ -33,6 +33,10 @@
 #ifndef __MEDIA_CODEC_H__
 #define __MEDIA_CODEC_H__
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include "audio/audiobuffer.h" // for AudioFormat
 #include "ip_utils.h"
 
diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp
index 6f9f2252aa79c5634b7e739fda1d35c6f1524658..f62c6111fc90b73fcd19952652b1bd70ad23f5c8 100644
--- a/src/media/media_decoder.cpp
+++ b/src/media/media_decoder.cpp
@@ -223,7 +223,6 @@ int MediaDecoder::setupFromVideoData()
 #else
     ret = avformat_find_stream_info(inputCtx_, NULL);
 #endif
-
     if (ret < 0) {
         // workaround for this bug:
         // http://patches.libav.org/patch/22541/
@@ -284,7 +283,6 @@ int MediaDecoder::setupFromVideoData()
         RING_ERR("Could not open codec");
         return -1;
     }
-
     return 0;
 }
 
diff --git a/src/media/socket_pair.cpp b/src/media/socket_pair.cpp
index b7f0ab1379f4345f55d22f01215258c196bd6fd9..4011f4bde7caa6aa5274054d846aab1af9f4cede 100644
--- a/src/media/socket_pair.cpp
+++ b/src/media/socket_pair.cpp
@@ -43,10 +43,12 @@ extern "C" {
 #include <cstring>
 #include <stdexcept>
 #include <unistd.h>
-#include <poll.h>
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
+
+#ifdef _WIN32
+#define SOCK_NONBLOCK FIONBIO
+#define poll WSAPoll
+#endif
 
 #ifdef __ANDROID__
 #include <asm-generic/fcntl.h>
@@ -308,7 +310,7 @@ SocketPair::readRtpData(void *buf, int buf_size)
         socklen_t from_len = sizeof(from);
 
 start:
-        int result = recvfrom(rtpHandle_, buf, buf_size, 0,
+        int result = recvfrom(rtpHandle_, (char*)buf, buf_size, 0,
                               (struct sockaddr *)&from, &from_len);
         if (result > 0 and srtpContext_ and srtpContext_->srtp_in.aes)
             if (ff_srtp_decrypt(&srtpContext_->srtp_in, data, &result) < 0)
@@ -341,7 +343,7 @@ SocketPair::readRtcpData(void *buf, int buf_size)
         // work with system socket
         struct sockaddr_storage from;
         socklen_t from_len = sizeof(from);
-        return recvfrom(rtcpHandle_, buf, buf_size, 0,
+        return recvfrom(rtcpHandle_,(char*) buf, buf_size, 0,
                         (struct sockaddr *)&from, &from_len);
     }
 
@@ -375,11 +377,11 @@ SocketPair::writeRtpData(void* buf, int buf_size)
             if (buf_size < 0)
                 return buf_size;
 
-            return sendto(rtpHandle_, srtpContext_->encryptbuf, buf_size, 0,
+            return sendto(rtpHandle_, (char*)srtpContext_->encryptbuf, buf_size, 0,
                           (sockaddr*) &rtpDestAddr_, rtpDestAddrLen_);
         }
 
-        return sendto(rtpHandle_, buf, buf_size, 0,
+        return sendto(rtpHandle_, (char*)buf, buf_size, 0,
                       (sockaddr*) &rtpDestAddr_, rtpDestAddrLen_);
     }
 
@@ -406,7 +408,7 @@ SocketPair::writeRtcpData(void *buf, int buf_size)
         auto ret = ff_network_wait_fd(rtcpHandle_);
         if (ret < 0)
             return ret;
-        return sendto(rtcpHandle_, buf, buf_size, 0,
+        return sendto(rtcpHandle_,(char*) buf, buf_size, 0,
                       (sockaddr*) &rtcpDestAddr_, rtcpDestAddrLen_);
     }
 
diff --git a/src/media/socket_pair.h b/src/media/socket_pair.h
index b1df9343eae7ef2455b76ff4c3cd0a086fdb5d16..7c6bc07ca6468b757169ab38138bcab804fd84d9 100644
--- a/src/media/socket_pair.h
+++ b/src/media/socket_pair.h
@@ -32,9 +32,22 @@
 #ifndef SOCKET_PAIR_H_
 #define SOCKET_PAIR_H_
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include "media_io_handle.h"
 
+#ifndef _WIN32
 #include <sys/socket.h>
+#include <netdb.h>
+#include <poll.h>
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h>
+using socklen_t = int;
+#endif
+
 #include <mutex>
 #include <memory>
 #include <atomic>
diff --git a/src/media/video/Makefile.am b/src/media/video/Makefile.am
index 73876d36a360e237d24726100402578d6f631920..7aebbe40d122e01032ca62c9bd331b0bc18c4992 100644
--- a/src/media/video/Makefile.am
+++ b/src/media/video/Makefile.am
@@ -12,6 +12,11 @@ SUBDIRS+= \
     osxvideo
 endif
 
+if HAVE_WIN32
+SUBDIRS+= \
+	winvideo
+endif
+
 noinst_LTLIBRARIES = libvideo.la
 libvideo_la_SOURCES = \
 	video_device.h \
diff --git a/src/media/video/sinkclient.cpp b/src/media/video/sinkclient.cpp
index 910cce4b76b462d387e2ea45491dc9e8517c33e8..8e83deb7276381de2775fc0b67336c45fdb09b47 100644
--- a/src/media/video/sinkclient.cpp
+++ b/src/media/video/sinkclient.cpp
@@ -51,7 +51,9 @@
 #include "client/ring_signal.h"
 #include "dring/videomanager_interface.h"
 
+#ifndef _WIN32
 #include <sys/mman.h>
+#endif
 #include <fcntl.h>
 #include <cstdio>
 #include <sstream>
diff --git a/src/media/video/winvideo/Makefile.am b/src/media/video/winvideo/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..835c37398d517af18aa50828c9e17e147827e243
--- /dev/null
+++ b/src/media/video/winvideo/Makefile.am
@@ -0,0 +1,11 @@
+include $(top_srcdir)/globals.mak
+
+noinst_LTLIBRARIES = libwinvideo.la
+
+libwinvideo_la_SOURCES = \
+	video_device_impl.cpp \
+	video_device_monitor_impl.cpp
+
+AM_OBJCXXFLAGS = -std=c++11
+
+libwinvideo_la_LIBADD = -ldxguid -lole32 -luuid -lstrmiids -loleaut32
\ No newline at end of file
diff --git a/src/media/video/winvideo/capture_graph_interfaces.h b/src/media/video/winvideo/capture_graph_interfaces.h
new file mode 100644
index 0000000000000000000000000000000000000000..fe74f8c3dcb06a31d906e1fee4dedd4855ea6232
--- /dev/null
+++ b/src/media/video/winvideo/capture_graph_interfaces.h
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (C) 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 3 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.
+ */
+
+#ifndef CAPTURE_GRAPH_INTERFACES
+#define CAPTURE_GRAPH_INTERFACES
+
+#include <dshow.h>
+
+namespace ring { namespace video {
+
+class CaptureGraphInterfaces {
+public:
+    CaptureGraphInterfaces()
+        : captureGraph_(nullptr)
+        , graph_(nullptr)
+        , videoInputFilter_(nullptr)
+        , streamConf_(nullptr)
+    {}
+
+    ICaptureGraphBuilder2* captureGraph_;
+    IGraphBuilder* graph_;
+    IBaseFilter* videoInputFilter_;
+    IAMStreamConfig* streamConf_;
+};
+
+}} // namespace ring::video
+
+#endif
\ No newline at end of file
diff --git a/src/media/video/winvideo/video_device_impl.cpp b/src/media/video/winvideo/video_device_impl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f6cbf60f186d46d75afb9e33c2c2c2bbcad936ef
--- /dev/null
+++ b/src/media/video/winvideo/video_device_impl.cpp
@@ -0,0 +1,356 @@
+/*
+ *  Copyright (C) 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 3 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.
+ */
+
+#include <algorithm>
+#include <cassert>
+#include <climits>
+#include <map>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+#include "logger.h"
+#include "../video_device.h"
+#include "capture_graph_interfaces.h"
+
+#include <dshow.h>
+
+namespace ring { namespace video {
+
+class VideoDeviceImpl {
+    public:
+        /**
+        * @throw std::runtime_error
+        */
+        VideoDeviceImpl(const std::string& path);
+        std::string device;
+        std::string name;
+        unsigned int id;
+
+        std::vector<std::string> getChannelList() const;
+        std::vector<std::string> getSizeList(const std::string& channel) const;
+        std::vector<std::string> getSizeList() const;
+        std::vector<std::string> getRateList(const std::string& channel,
+            const std::string& size) const;
+        float getRate(unsigned rate) const;
+
+        VideoSettings getSettings() const;
+        void applySettings(VideoSettings settings);
+
+        DeviceParams getDeviceParams() const;
+
+    private:
+        std::unique_ptr<CaptureGraphInterfaces> cInterface;
+
+        void setup();
+        std::vector<std::string> sizeList_;
+        std::map<std::string, std::vector<std::string> > rateList_;
+        std::map<std::string, AM_MEDIA_TYPE*> capMap_;
+};
+
+VideoDeviceImpl::VideoDeviceImpl(const std::string& id)
+    : id(atoi(id.c_str()))
+    , cInterface(new CaptureGraphInterfaces())
+{
+    setup();
+
+    applySettings(VideoSettings());
+}
+
+void
+VideoDeviceImpl::setup()
+{
+    HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+    if (FAILED(hr))
+        return RING_ERR("Could not initialize video device.");
+
+    hr = CoCreateInstance(
+        CLSID_CaptureGraphBuilder2,
+        nullptr,
+        CLSCTX_INPROC_SERVER,
+        IID_ICaptureGraphBuilder2,
+        (void**) &cInterface->captureGraph_);
+    if (FAILED(hr))
+        return RING_ERR("Could not create the Filter Graph Manager");
+
+    hr = CoCreateInstance(CLSID_FilterGraph,
+        nullptr,
+        CLSCTX_INPROC_SERVER,IID_IGraphBuilder,
+        (void**) &cInterface->graph_);
+    if (FAILED(hr))
+      return RING_ERR("Could not add the graph builder!");
+
+    hr = cInterface->captureGraph_->SetFiltergraph(cInterface->graph_);
+    if (FAILED(hr))
+        return RING_ERR("Could not set filtergraph.");
+
+    ICreateDevEnum *pSysDevEnum = nullptr;
+    hr = CoCreateInstance(CLSID_SystemDeviceEnum,
+        nullptr,
+        CLSCTX_INPROC_SERVER,
+        IID_ICreateDevEnum,
+        (void **)&pSysDevEnum);
+    if (FAILED(hr))
+        return RING_ERR("Could not create the enumerator!");
+
+    IEnumMoniker *pEnumCat = nullptr;
+    hr = pSysDevEnum->CreateClassEnumerator(
+        CLSID_VideoInputDeviceCategory,
+        &pEnumCat,
+        0);
+    if (SUCCEEDED(hr)) {
+        IMoniker *pMoniker = nullptr;
+        ULONG cFetched;
+        unsigned int deviceCounter = 0;
+        bool done = false;
+        while ((pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) && (not done))
+        {
+            if (deviceCounter == this->id) {
+                IPropertyBag *pPropBag;
+                hr = pMoniker->BindToStorage(
+                    0,
+                    0,
+                    IID_IPropertyBag,
+                    (void **)&pPropBag);
+                if (SUCCEEDED(hr)) {
+                    VARIANT varName;
+                    VariantInit(&varName);
+                    hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+                    if (SUCCEEDED(hr)) {
+                        int l = WideCharToMultiByte(
+                            CP_UTF8,
+                            0,
+                            varName.bstrVal,
+                            -1,
+                            0, 0, 0, 0);
+                        auto tmp = new char[l];
+                        WideCharToMultiByte(
+                            CP_UTF8,
+                            0,
+                            varName.bstrVal,
+                            -1,
+                            tmp,
+                            l,
+                            0, 0);
+                        this->name = std::string(tmp);
+                        this->device = std::string("video=") + this->name;
+                        hr = pMoniker->BindToObject(
+                            nullptr, nullptr,
+                            IID_IBaseFilter,
+                            (void**)&cInterface->videoInputFilter_);
+                        if (SUCCEEDED(hr))
+                            hr = cInterface->graph_->AddFilter(
+                                cInterface->videoInputFilter_,
+                                varName.bstrVal);
+                        else {
+                            RING_ERR("Could not add filter to device.");
+                            break;
+                        }
+                        hr = cInterface->captureGraph_->FindInterface(
+                            &PIN_CATEGORY_PREVIEW,
+                            &MEDIATYPE_Video,
+                            cInterface->videoInputFilter_,
+                            IID_IAMStreamConfig,
+                            (void **)&cInterface->streamConf_);
+                        if(FAILED(hr)) {
+                            hr = cInterface->captureGraph_->FindInterface(
+                                &PIN_CATEGORY_CAPTURE,
+                                &MEDIATYPE_Video,
+                                cInterface->videoInputFilter_,
+                                IID_IAMStreamConfig,
+                                (void **)&cInterface->streamConf_);
+                            if (FAILED(hr)) {
+                                RING_ERR("Couldn't config the stream!");
+                                break;
+                            }
+                        }
+                        done = true;
+                    }
+                    VariantClear(&varName);
+                    pPropBag->Release();
+                    pPropBag = nullptr;
+                    pMoniker->Release();
+                    pMoniker = nullptr;
+                }
+            }
+            deviceCounter++;
+        }
+        pEnumCat->Release();
+        pEnumCat = nullptr;
+        if (done && SUCCEEDED(hr)) {
+            int piCount;
+            int piSize;
+            cInterface->streamConf_->GetNumberOfCapabilities(&piCount, &piSize);
+            AM_MEDIA_TYPE *pmt;
+            VIDEO_STREAM_CONFIG_CAPS pSCC;
+            for (int i = 0; i < piCount; i++) {
+                cInterface->streamConf_->GetStreamCaps(i, &pmt, (BYTE*)&pSCC);
+                if (pmt->formattype == FORMAT_VideoInfo) {
+                    auto videoInfo = (VIDEOINFOHEADER*) pmt->pbFormat;
+                    sizeList_.push_back(
+                        std::to_string(videoInfo->bmiHeader.biWidth) + "x" +
+                        std::to_string(videoInfo->bmiHeader.biHeight));
+                    rateList_[sizeList_.back()].push_back(
+                        std::to_string(1e7 / pSCC.MinFrameInterval));
+                    rateList_[sizeList_.back()].push_back(
+                        std::to_string(1e7 / pSCC.MaxFrameInterval));
+                    capMap_[sizeList_.back()] = pmt;
+                }
+            }
+        }
+    }
+    pSysDevEnum->Release();
+    pSysDevEnum = NULL;
+}
+
+void
+VideoDeviceImpl::applySettings(VideoSettings settings)
+{
+    if (!settings.video_size.empty()) {
+        auto pmt = capMap_[settings.video_size];
+        ((VIDEOINFOHEADER*) pmt->pbFormat)->AvgTimePerFrame = settings.framerate;
+        if (FAILED(cInterface->streamConf_->SetFormat(capMap_[settings.video_size]))) {
+            RING_ERR("Could not set settings.");
+        }
+    }
+}
+
+DeviceParams
+VideoDeviceImpl::getDeviceParams() const
+{
+    DeviceParams params;
+
+    params.input = device;
+    params.format = "dshow";
+
+    AM_MEDIA_TYPE *pmt;
+    HRESULT hr = cInterface->streamConf_->GetFormat(&pmt);
+    if (SUCCEEDED(hr)) {
+        if (pmt->formattype == FORMAT_VideoInfo) {
+            auto videoInfo = (VIDEOINFOHEADER*) pmt->pbFormat;
+            params.width = videoInfo->bmiHeader.biWidth;
+            params.height = videoInfo->bmiHeader.biHeight;
+            params.framerate = 1e7 /  videoInfo->AvgTimePerFrame;
+        }
+    }
+    return params;
+}
+
+VideoSettings
+VideoDeviceImpl::getSettings() const
+{
+    VideoSettings settings;
+
+    settings.name = name;
+
+    AM_MEDIA_TYPE *pmt;
+    HRESULT hr = cInterface->streamConf_->GetFormat(&pmt);
+    if (SUCCEEDED(hr)) {
+        if (pmt->formattype == FORMAT_VideoInfo) {
+            auto videoInfo = (VIDEOINFOHEADER*) pmt->pbFormat;
+            settings.video_size = std::to_string(videoInfo->bmiHeader.biWidth) +
+                "x" + std::to_string(videoInfo->bmiHeader.biHeight);
+            settings.framerate = 1e7 / videoInfo->AvgTimePerFrame;
+        }
+    }
+    return settings;
+}
+
+VideoDevice::VideoDevice(const std::string& path)
+    : deviceImpl_(new VideoDeviceImpl(path))
+{
+    node_ = path;
+    name = deviceImpl_->name;
+}
+
+DeviceParams
+VideoDevice::getDeviceParams() const
+{
+    return deviceImpl_->getDeviceParams();
+}
+
+void
+VideoDevice::applySettings(VideoSettings settings)
+{
+    deviceImpl_->applySettings(settings);
+}
+
+VideoSettings
+VideoDevice::getSettings() const
+{
+    return deviceImpl_->getSettings();
+}
+
+std::vector<std::string>
+VideoDeviceImpl::getSizeList() const
+{
+    return sizeList_;
+}
+
+std::vector<std::string>
+VideoDeviceImpl::getRateList(const std::string& channel,
+    const std::string& size) const
+{
+    (void) channel;
+    return rateList_.at(size);
+}
+
+std::vector<std::string>
+VideoDeviceImpl::getSizeList(const std::string& channel) const
+{
+    (void) channel;
+    return sizeList_;
+}
+
+std::vector<std::string>
+VideoDeviceImpl::getChannelList() const
+{
+    return {"default"};
+}
+
+DRing::VideoCapabilities
+VideoDevice::getCapabilities() const
+{
+    DRing::VideoCapabilities cap;
+
+    for (const auto& chan : deviceImpl_->getChannelList()) {
+        for (const auto& size : deviceImpl_->getSizeList(chan)) {
+            cap[chan][size] = deviceImpl_->getRateList(chan, size);
+        }
+    }
+    return cap;
+}
+
+VideoDevice::~VideoDevice()
+{}
+
+}} // namespace ring::video
\ No newline at end of file
diff --git a/src/media/video/winvideo/video_device_monitor_impl.cpp b/src/media/video/winvideo/video_device_monitor_impl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e66624e29bf70f90afeac4f8a857812bc8f5d78b
--- /dev/null
+++ b/src/media/video/winvideo/video_device_monitor_impl.cpp
@@ -0,0 +1,169 @@
+/*
+ *  Copyright (C) 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 3 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.
+ */
+
+#include <algorithm>
+#include <cerrno>
+#include <cstdio>
+#include <mutex>
+#include <sstream>
+#include <stdexcept> // for std::runtime_error
+#include <string>
+#include <thread>
+#include <unistd.h>
+#include <vector>
+
+#include "../video_device_monitor.h"
+#include "logger.h"
+#include "noncopyable.h"
+
+#include <dshow.h>
+#include <dbt.h>
+
+namespace ring { namespace video {
+
+class VideoDeviceMonitorImpl {
+    public:
+        /*
+        * This is the only restriction to the pImpl design:
+        * as the Linux implementation has a thread, it needs a way to notify
+        * devices addition and deletion.
+        *
+        * This class should maybe inherit from VideoDeviceMonitor instead of
+        * being its pImpl.
+        */
+        VideoDeviceMonitorImpl(VideoDeviceMonitor* monitor);
+        ~VideoDeviceMonitorImpl();
+
+        void start();
+
+    private:
+        NON_COPYABLE(VideoDeviceMonitorImpl);
+
+        VideoDeviceMonitor* monitor_;
+
+        void run();
+
+        mutable std::mutex mutex_;
+        bool probing_;
+        std::thread thread_;
+};
+
+VideoDeviceMonitorImpl::VideoDeviceMonitorImpl(VideoDeviceMonitor* monitor)
+    : monitor_(monitor)
+    , mutex_()
+    , thread_()
+{}
+
+void
+VideoDeviceMonitorImpl::start()
+{
+    probing_ = true;
+    thread_ = std::thread(&VideoDeviceMonitorImpl::run, this);
+}
+
+VideoDeviceMonitorImpl::~VideoDeviceMonitorImpl()
+{
+    probing_ = false;
+    if (thread_.joinable())
+        thread_.join();
+}
+
+void
+VideoDeviceMonitorImpl::run()
+{
+    //FIX ME : That's one shot
+    std::list<std::string> deviceList;
+    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+    ICreateDevEnum *pDevEnum;
+    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
+        CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
+
+    IEnumMoniker *pEnum;
+    if (SUCCEEDED(hr)) {
+        hr = pDevEnum->CreateClassEnumerator(
+            CLSID_VideoInputDeviceCategory,
+            &pEnum, 0);
+        if (FAILED(hr)) {
+            RING_ERR("No webcam found.");
+            hr = VFW_E_NOT_FOUND;
+        }
+        pDevEnum->Release();
+        if (hr != VFW_E_NOT_FOUND) {
+            IMoniker *pMoniker = NULL;
+            unsigned deviceID = 0;
+            while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
+            {
+                IPropertyBag *pPropBag;
+                HRESULT hr = pMoniker->BindToStorage(
+                    0,
+                    0,
+                    IID_PPV_ARGS(&pPropBag));
+                if (FAILED(hr)) {
+                    pMoniker->Release();
+                    continue;
+                }
+
+                VARIANT var;
+                VariantInit(&var);
+                hr = pPropBag->Read(L"Description", &var, 0);
+                if (FAILED(hr)) {
+                    hr = pPropBag->Read(L"FriendlyName", &var, 0);
+                }
+                if (SUCCEEDED(hr)) {
+                    deviceList.push_back(std::to_string(deviceID));
+                    VariantClear(&var);
+                }
+
+                hr = pPropBag->Write(L"FriendlyName", &var);
+                pPropBag->Release();
+                pMoniker->Release();
+                deviceID++;
+            }
+            pEnum->Release();
+            for (auto device : deviceList) {
+                //FIXME: Custom id is a weak way to do that
+                monitor_->addDevice(device);
+            }
+        }
+    }
+}
+
+VideoDeviceMonitor::VideoDeviceMonitor()
+    : preferences_()
+    , devices_()
+    , monitorImpl_(new VideoDeviceMonitorImpl(this))
+{
+    monitorImpl_->start();
+}
+
+VideoDeviceMonitor::~VideoDeviceMonitor()
+{}
+
+}} // namespace ring::video
diff --git a/src/preferences.cpp b/src/preferences.cpp
index 473b252dcc9aeb3a538a66af63215462f6f1ebfc..ef1b16508b9efd36f452208e519af2a660dfa6e1 100644
--- a/src/preferences.cpp
+++ b/src/preferences.cpp
@@ -50,6 +50,9 @@
 #if HAVE_COREAUDIO
 #include "audio/coreaudio/corelayer.h"
 #endif
+#if HAVE_PORTAUDIO
+#include "audio/portaudio/portaudiolayer.h"
+#endif
 #endif /* HAVE_OPENSL */
 
 #include <yaml-cpp/yaml.h>
@@ -58,6 +61,7 @@
 #include "sip/sip_utils.h"
 #include <sstream>
 #include <algorithm>
+#include <stdexcept>
 #include "fileutils.h"
 
 namespace ring {
@@ -356,6 +360,8 @@ AudioLayer* AudioPreference::createAudioLayer()
                 audioApi_ = ALSA_API_STR;
 #elif HAVE_COREAUDIO
                 audioApi_ = COREAUDIO_API_STR;
+#elif HAVE_PORTAUDIO
+                audioApi_ = PORTAUDIO_API_STR;
 #else
                 throw;
 #endif
@@ -396,6 +402,15 @@ AudioLayer* AudioPreference::createAudioLayer()
     return NULL;
 #endif
 
+#if HAVE_PORTAUDIO
+    audioApi_ = PORTAUDIO_API_STR;
+    try {
+        return new PortAudioLayer(*this);
+    } catch (const std::runtime_error &e) {
+        RING_WARN("Could not create PortAudio layer. There will be no sound.");
+    }
+    return nullptr;
+#endif
 #endif // __ANDROID__
 }
 
diff --git a/src/registration_states.h b/src/registration_states.h
index 5b72325b44287fe0701cb04f00767d5633dea0c7..e523b93cdbee7e6f1c25f11218352fb544634f83 100644
--- a/src/registration_states.h
+++ b/src/registration_states.h
@@ -32,6 +32,10 @@
 #ifndef REGISTRATION_STATES_H_
 #define REGISTRATION_STATES_H_
 
+#ifdef REGISTERED
+#undef REGISTERED
+#endif
+
 namespace ring {
 
 /** Contains all the Registration states for an account can be in */
diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp
index 8d7987a8c2f1d674cf229932164073c5d27579a2..299a1f6ad466f1e6aab548b2b8e223878f38342f 100644
--- a/src/ringdht/ringaccount.cpp
+++ b/src/ringdht/ringaccount.cpp
@@ -690,7 +690,7 @@ void RingAccount::doRegister_()
 
 #if 0 // enable if dht_ logging is needed
         dht_.setLoggers(
-            [](char const* m, va_list args){ vlogger(LOG_ERR, m, args); },
+            [](char const* m, va_list args){ vlogger(LOG_ERR, m, args); }
             [](char const* m, va_list args){ vlogger(LOG_WARNING, m, args); },
             [](char const* m, va_list args){ vlogger(LOG_DEBUG, m, args); }
         );
diff --git a/src/ringdht/sips_transport_ice.cpp b/src/ringdht/sips_transport_ice.cpp
index 9a0bc223713dd361b3cd2866bc6cf99c8f92504d..cbbf482071daaa15f5c852590228c3c5a4567744 100644
--- a/src/ringdht/sips_transport_ice.cpp
+++ b/src/ringdht/sips_transport_ice.cpp
@@ -401,7 +401,7 @@ SipsIceTransport::certGetInfo(pj_pool_t* pool, pj_ssl_cert_info* ci,
     std::memset(ci, 0, sizeof(pj_ssl_cert_info));
 
     /* Full raw certificate */
-    const pj_str_t raw_crt_pjstr {(char*)crt_raw.data, crt_raw.size};
+    const pj_str_t raw_crt_pjstr {(char*)crt_raw.data, (long int) crt_raw.size};
     pj_strdup(pool, &ci->cert_raw, &raw_crt_pjstr);
 
     /* Version */
diff --git a/src/sip/sip_utils.cpp b/src/sip/sip_utils.cpp
index 0df195756ab3b4b6bf782edd7899a29b51aba0d8..6b1510c7e7b650e2c8bed984c179b84858638354 100644
--- a/src/sip/sip_utils.cpp
+++ b/src/sip/sip_utils.cpp
@@ -43,10 +43,12 @@
 #include <pjsip/sip_uri.h>
 #include <pj/list.h>
 
+#ifndef _WIN32
 #include <netdb.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#endif
 
 #include <vector>
 #include <algorithm>
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index ad35de41578f29e2174664b8f73440b1abef21b7..b6a698e34fdb824f2a7abc51a555f1e987943e2c 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -68,7 +68,7 @@
 #include "string_utils.h"
 
 #include <unistd.h>
-#include <pwd.h>
+
 
 #include <algorithm>
 #include <array>
@@ -76,6 +76,15 @@
 #include <sstream>
 #include <cstdlib>
 
+#include "upnp/upnp_control.h"
+#include "ip_utils.h"
+
+#ifdef _WIN32
+#include <lmcons.h>
+#else
+#include <pwd.h>
+#endif
+
 namespace ring {
 
 using yaml_utils::parseValue;
@@ -1332,10 +1341,18 @@ bool SIPAccount::proxyMatch(const std::string& hostname, pjsip_endpoint * /*endp
 
 std::string SIPAccount::getLoginName()
 {
+#ifndef _WIN32
     struct passwd * user_info = getpwuid(getuid());
     return user_info ? user_info->pw_name : "";
+#else
+    LPWSTR username[UNLEN+1];
+    DWORD username_len = UNLEN+1;
+    return GetUserName(*username, &username_len) ? std::string((char*)*username) : "";
+#endif
 }
 
+
+
 std::string SIPAccount::getFromUri() const
 {
     std::string scheme;
diff --git a/src/sip/sipaccountbase.h b/src/sip/sipaccountbase.h
index 1cef21d25a3876bf764e726f58c1235952ae65d5..d1c764722b00c176cccf67f1d8be7a58479039a5 100644
--- a/src/sip/sipaccountbase.h
+++ b/src/sip/sipaccountbase.h
@@ -43,6 +43,7 @@
 #include "noncopyable.h"
 
 #include <pjsip/sip_types.h>
+#include <opendht/value.h>
 
 #include <array>
 #include <vector>
diff --git a/src/sip/tlsvalidator.cpp b/src/sip/tlsvalidator.cpp
index 2837bf2dc1290218dd449ee765e68fc27dba36c0..14790f9a37e6f15e8503c55d447522de0c79d82c 100644
--- a/src/sip/tlsvalidator.cpp
+++ b/src/sip/tlsvalidator.cpp
@@ -54,10 +54,12 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifndef _WIN32
 #include <sys/socket.h>
 #include <netinet/tcp.h>
 #include <netinet/in.h>
 #include <netdb.h>
+#endif
 #include <unistd.h>
 #include <fcntl.h>
 
diff --git a/src/sip/tlsvalidator.h b/src/sip/tlsvalidator.h
index 563164364b359d684a3177d1351b5fa171a9eed3..e68319d1a69fe225ab805072421d7df76d90b205 100644
--- a/src/sip/tlsvalidator.h
+++ b/src/sip/tlsvalidator.h
@@ -35,6 +35,32 @@ namespace ring { namespace tls {
 class GnuTlsGlobalInit;
 }} // namespace ring::tls
 
+#if !defined (S_IRWXG)
+#define S_IRWXG 00070
+#endif /* S_IRWXG */
+#if !defined (S_IRGRP)
+#define S_IRGRP 00040
+#endif /* S_IRGRP */
+#if !defined (S_IWGRP)
+#define S_IWGRP 00020
+#endif /* S_IWGRP */
+#if !defined (S_IXGRP)
+#define S_IXGRP 00010
+#endif /* S_IXGRP */
+#if !defined (S_IRWXO)
+#define S_IRWXO 00007
+#endif /* S_IRWXO */
+#if !defined (S_IROTH)
+#define S_IROTH 00004
+#endif /* S_IROTH */
+#if !defined (S_IWOTH)
+#define S_IWOTH 00002
+#endif /* S_IWOTH */
+#if !defined (S_IXOTH)
+#define S_IXOTH 00001
+#endif /* S_IXOTH */
+
+
 namespace ring {
 
 class TlsValidatorException : public std::runtime_error {
diff --git a/src/winsyslog.c b/src/winsyslog.c
new file mode 100644
index 0000000000000000000000000000000000000000..69f311b449a868e2abec67134b0dc87b4b80b330
--- /dev/null
+++ b/src/winsyslog.c
@@ -0,0 +1,108 @@
+/*
+ * This header borrowed from Cygnus GNUwin32 project
+ *
+ * Modified for use with functions to map syslog
+ * calls to EventLog calls on the windows platform
+ *
+ * much of this is not used, but here for the sake of
+ * error free compilation.  EventLogs will most likely
+ * not behave as syslog does, but may be useful anyway.
+ * much of what syslog does can be emulated here, but
+ * that will have to be done later.
+ */
+
+#include "winsyslog.h"
+#include <stdio.h>
+#include <fcntl.h>
+#include <process.h>
+#include <stdlib.h>
+
+#ifndef THREAD_SAFE
+static char *loghdr;            /* log file header string */
+static HANDLE loghdl = NULL;    /* handle of event source */
+#endif
+
+static CHAR *                       //   return error message
+getLastErrorText(                   // converts "Lasr Error" code into text
+    CHAR *pBuf,                     //   message buffer
+    ULONG bufSize)                  //   buffer size
+{
+    DWORD retSize;
+    LPTSTR pTemp=NULL;
+
+    if (bufSize < 16) {
+        if (bufSize > 0) {
+           pBuf[0]='\0';
+       }
+       return(pBuf);
+   }
+   retSize=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
+       FORMAT_MESSAGE_FROM_SYSTEM|
+       FORMAT_MESSAGE_ARGUMENT_ARRAY,
+       NULL,
+       GetLastError(),
+       LANG_NEUTRAL,
+       (LPTSTR)&pTemp,
+       0,
+       NULL);
+   if (!retSize || pTemp == NULL) {
+        pBuf[0]='\0';
+    }
+    else {
+        pTemp[strlen(pTemp)-2]='\0'; //remove cr and newline character
+        sprintf(pBuf,"%0.*s (0x%x)",bufSize-16,pTemp,GetLastError());
+        LocalFree((HLOCAL)pTemp);
+    }
+    return(pBuf);
+}
+
+void closelog(void)
+{
+    DeregisterEventSource(loghdl);
+    free(loghdr);
+}
+
+/* Emulator for GNU vsyslog() routine
+ * Accepts: priority
+ *      format
+ *      arglist
+ */
+// TODO: use a real EventIdentifier with a Message Text file ?
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363679%28v=vs.85%29.aspx
+ void vsyslog(int level, const char* format, va_list arglist)
+ {
+    CONST CHAR *arr[1];
+    char tmp[1024];
+
+    if (!loghdl)
+        openlog(LOGFILE, WINLOG_PID, WINLOG_MAIL);
+
+    vsprintf(tmp, format, arglist);
+
+    arr[0] = tmp;
+    BOOL err = ReportEvent(loghdl, (unsigned short) level, (unsigned short)level,
+        level, NULL, 1, 0, arr, NULL);
+
+    if (err == 0)
+    {
+        CHAR errText[1024];
+        puts(getLastErrorText(errText, 1024));
+    }
+}
+
+/* Emulator for BSD openlog() routine
+ * Accepts: identity
+ *      options
+ *      facility
+ */
+ void openlog(const char *ident, int logopt, int facility)
+ {
+    char tmp[1024];
+
+    if (loghdl) {
+        closelog();
+    }
+    loghdl = RegisterEventSource(NULL, ident);
+    sprintf(tmp, (logopt & WINLOG_PID) ? "%s[%d]" : "%s", ident, getpid());
+    loghdr = _strdup(tmp);  /* save header for later */
+}
\ No newline at end of file
diff --git a/src/winsyslog.h b/src/winsyslog.h
new file mode 100644
index 0000000000000000000000000000000000000000..628573206354bba26e481fc3edd8190632c7b1c2
--- /dev/null
+++ b/src/winsyslog.h
@@ -0,0 +1,64 @@
+/*
+ * This header borrowed from Cygnus GNUwin32 project
+ *
+ * Modified for use with functions to map syslog
+ * calls to EventLog calls on the windows platform
+ *
+ * much of this is not used, but here for the sake of
+ * error free compilation.  EventLogs will most likely
+ * not behave as syslog does, but may be useful anyway.
+ * much of what syslog does can be emulated here, but
+ * that will have to be done later.
+ */
+
+#ifndef WINSYSLOG_H
+#define WINSYSLOG_H
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#define WINLOG_PRIMASK  0x07
+
+#define WINLOG_PRI(p)   ((p) & WINLOG_PRIMASK)
+#define WINLOG_MAKEPRI(fac, pri)    (((fac) << 3) | (pri))
+
+#define WINLOG_KERN (0<<3)
+#define WINLOG_USER (1<<3)
+#define WINLOG_MAIL (2<<3)
+#define WINLOG_DAEMON   (3<<3)
+#define WINLOG_AUTH (4<<3)
+#define WINLOG_SYSLOG   (5<<3)
+#define WINLOG_LPR      (6<<3)
+#define WINLOG_NEWS (7<<3)
+#define WINLOG_UUCP (8<<3)
+#define WINLOG_CRON (9<<3)
+#define WINLOG_AUTHPRIV (10<<3)
+
+#define WINLOG_NFACILITIES  10
+#define WINLOG_FACMASK  0x03f8
+#define WINLOG_FAC(p)   (((p) & WINLOG_FACMASK) >> 3)
+
+#define WINLOG_MASK(pri)    (1 << (pri))
+#define WINLOG_UPTO(pri)    ((1 << ((pri)+1)) - 1)
+
+#define LOGFILE "ringcli"
+
+/*
+ * Option flags for openlog.
+ *
+ * WINLOG_ODELAY no longer does anything.
+ * WINLOG_NDELAY is the inverse of what it used to be.
+ */
+#define WINLOG_PID         0x01 /* log the pid with each message */
+#define WINLOG_CONS        0x02 /* log on the console if errors in sending */
+#define WINLOG_ODELAY      0x04 /* delay open until first syslog() (default) */
+#define WINLOG_NDELAY      0x08 /* don't delay open */
+#define WINLOG_NOWAIT      0x10 /* don't wait for console forks: DEPRECATED */
+#define WINLOG_PERROR      0x20 /* log to stderr as well */
+
+#define strerror_r(errno,buf,len) strerror_s(buf,len,errno)
+
+extern void closelog(void);
+extern void openlog(const char *, int, int);
+extern void vsyslog(int, const char *, va_list);
+
+#endif
\ No newline at end of file