diff --git a/Daemon.h b/Daemon.h
index e755e3e9..4f31b2dc 100644
--- a/Daemon.h
+++ b/Daemon.h
@@ -20,6 +20,7 @@ namespace i2p
 			virtual bool init(int argc, char* argv[]);
 			virtual bool start();
 			virtual bool stop();
+			virtual void run () {};
 
 			bool isLogging;
 			bool isDaemon;
@@ -61,8 +62,10 @@ namespace i2p
 				return instance;
 			}
 
-			virtual bool start();
-			virtual bool stop();
+			bool start();
+			bool stop();
+;			void run ();
+
                 private:
                        std::string pidfile;
                        int pidFH;
diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp
index 2ccbfe38..53d9f61e 100644
--- a/DaemonLinux.cpp
+++ b/DaemonLinux.cpp
@@ -4,6 +4,7 @@
 
 #include <signal.h>
 #include <stdlib.h>
+#include <thread>
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/stat.h>
@@ -118,6 +119,14 @@ namespace i2p
 
 			return Daemon_Singleton::stop();			
 		}
+
+		void DaemonLinux::run ()
+		{
+			while (running)
+			{
+				std::this_thread::sleep_for (std::chrono::seconds(1));
+			}
+		}
 	}
 }
 
diff --git a/DaemonWin32.cpp b/DaemonWin32.cpp
index 4ab65040..bf5f938c 100644
--- a/DaemonWin32.cpp
+++ b/DaemonWin32.cpp
@@ -68,7 +68,14 @@ namespace i2p
 			SetConsoleOutputCP(1251);
 			setlocale(LC_ALL, "Russian");
 
-			return Daemon_Singleton::start();
+			bool ret = Daemon_Singleton::start();
+			if (ret && IsLogToFile ())
+			{	
+				// TODO: find out where this garbage to console comes from
+				SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
+				SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
+			}
+			return ret;
 		}
 
 		bool DaemonWin32::stop()
diff --git a/Log.h b/Log.h
index 5b07e2c9..363a23b5 100644
--- a/Log.h
+++ b/Log.h
@@ -45,6 +45,7 @@ class Log: public i2p::util::MsgQueue<LogMsg>
 		std::shared_ptr<std::ostream> GetLogStream () const { return m_LogStream; };	
 		const std::string& GetTimestamp ();
 		LogLevel GetLogLevel () { return m_MinLevel; };
+		const std::string& GetFullFilePath () const { return m_FullFilePath; };
 
 	private:
 
@@ -110,6 +111,11 @@ inline void ReopenLogFile ()
 		g_Log->ReopenLogFile ();
 }
 
+inline bool IsLogToFile ()
+{
+	return g_Log ? !g_Log->GetFullFilePath ().empty () : false;
+}	
+
 template<typename TValue>
 void LogPrint (std::stringstream& s, TValue arg) 
 {
diff --git a/Makefile b/Makefile
index 09cf2ace..ef0dec46 100644
--- a/Makefile
+++ b/Makefile
@@ -1,95 +1,101 @@
-UNAME := $(shell uname -s)
-SHLIB := libi2pd.so
-ARLIB := libi2pd.a
-SHLIB_CLIENT := libi2pdclient.so
-ARLIB_CLIENT := libi2pdclient.a
-I2PD  := i2pd
-GREP := fgrep
-DEPS := obj/make.dep
-
-include filelist.mk
-
-USE_AESNI  := yes
-USE_STATIC := no
-
-ifeq ($(UNAME),Darwin)
-	DAEMON_SRC += DaemonLinux.cpp
-	include Makefile.osx
-else ifeq ($(shell echo $(UNAME) | $(GREP) -c FreeBSD),1)
-	DAEMON_SRC += DaemonLinux.cpp
-	include Makefile.bsd
-else ifeq ($(UNAME),Linux)
-	DAEMON_SRC += DaemonLinux.cpp
-	include Makefile.linux
-else # win32 mingw
-	DAEMON_SRC += DaemonWin32.cpp Win32/Win32Service.cpp
-	WINDIR := True
-	include Makefile.mingw
-endif
-
-all: mk_build_dir $(ARLIB) $(ARLIB_CLIENT) $(I2PD)
-
-mk_build_dir:
-	mkdir -p obj
-     ifeq ($(WINDIR),True)
-	mkdir -p obj/Win32
-     endif
-
-api: mk_build_dir $(SHLIB) $(ARLIB)
-api_client: mk_build_dir $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
-
-## NOTE: The NEEDED_CXXFLAGS are here so that CXXFLAGS can be specified at build time
-## **without** overwriting the CXXFLAGS which we need in order to build.
-## For example, when adding 'hardening flags' to the build
-## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove
-## -std=c++11. If you want to remove this variable please do so in a way that allows setting
-## custom FLAGS to work at build-time.
-
-deps:
-	@mkdir -p obj
-	$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) -MM *.cpp > $(DEPS)
-	@sed -i -e '/\.o:/ s/^/obj\//' $(DEPS)
-
-obj/%.o : %.cpp
-	@mkdir -p obj
-	$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(CPU_FLAGS) -c -o $@ $<
-
-# '-' is 'ignore if missing' on first run
--include $(DEPS)
-
-$(I2PD):  $(patsubst %.cpp,obj/%.o,$(DAEMON_SRC)) $(ARLIB) $(ARLIB_CLIENT)
-	$(CXX) -o $@ $^ $(LDLIBS) $(LDFLAGS)
-
-$(SHLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
-ifneq ($(USE_STATIC),yes)
-	$(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^
-endif
-
-$(SHLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
-	$(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^
-
-$(ARLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
-	ar -r $@ $^
-
-$(ARLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
-	ar -r $@ $^
-
-clean:
-	rm -rf obj
-	$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
-
-strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB)
-	strip $^
-
-LATEST_TAG=$(shell git describe --tags --abbrev=0 master)
-dist:
-	git archive --format=tar.gz -9 --worktree-attributes \
-	    --prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz
-
-.PHONY: all
-.PHONY: clean
-.PHONY: deps
-.PHONY: dist
-.PHONY: api
-.PHONY: api_client
-.PHONY: mk_build_dir
+UNAME := $(shell uname -s)
+SHLIB := libi2pd.so
+ARLIB := libi2pd.a
+SHLIB_CLIENT := libi2pdclient.so
+ARLIB_CLIENT := libi2pdclient.a
+I2PD  := i2pd
+GREP := fgrep
+DEPS := obj/make.dep
+
+include filelist.mk
+
+USE_AESNI  := yes
+USE_STATIC := no
+
+ifeq ($(UNAME),Darwin)
+	DAEMON_SRC += DaemonLinux.cpp
+	include Makefile.osx
+else ifeq ($(shell echo $(UNAME) | $(GREP) -c FreeBSD),1)
+	DAEMON_SRC += DaemonLinux.cpp
+	include Makefile.bsd
+else ifeq ($(UNAME),Linux)
+	DAEMON_SRC += DaemonLinux.cpp
+	include Makefile.linux
+else # win32 mingw
+	DAEMON_SRC += DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp
+	DAEMON_RC += Win32/Resource.rc
+	WINDIR := True
+	include Makefile.mingw
+endif
+
+all: mk_build_dir $(ARLIB) $(ARLIB_CLIENT) $(I2PD)
+
+mk_build_dir:
+	mkdir -p obj
+     ifeq ($(WINDIR),True)
+	mkdir -p obj/Win32
+     endif
+
+api: mk_build_dir $(SHLIB) $(ARLIB)
+api_client: mk_build_dir $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
+
+## NOTE: The NEEDED_CXXFLAGS are here so that CXXFLAGS can be specified at build time
+## **without** overwriting the CXXFLAGS which we need in order to build.
+## For example, when adding 'hardening flags' to the build
+## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove
+## -std=c++11. If you want to remove this variable please do so in a way that allows setting
+## custom FLAGS to work at build-time.
+
+deps:
+	@mkdir -p obj
+	$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) -MM *.cpp > $(DEPS)
+	@sed -i -e '/\.o:/ s/^/obj\//' $(DEPS)
+
+obj/%.o : %.cpp
+	@mkdir -p obj
+	$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(CPU_FLAGS) -c -o $@ $<
+
+obj/%.o : %.rc 
+	$(WINDRES) -i $< -o $@
+
+# '-' is 'ignore if missing' on first run
+-include $(DEPS)
+
+DAEMON_OBJS = $(patsubst %.cpp,obj/%.o,$(DAEMON_SRC)) 
+DAEMON_RES_OBJS = $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) 
+$(I2PD): $(DAEMON_OBJS) $(DAEMON_RES_OBJS) $(ARLIB) $(ARLIB_CLIENT)
+	$(CXX) -o $@ $^ $(LDLIBS) $(LDFLAGS)
+
+$(SHLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
+ifneq ($(USE_STATIC),yes)
+	$(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^
+endif
+
+$(SHLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
+	$(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^
+
+$(ARLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
+	ar -r $@ $^
+
+$(ARLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
+	ar -r $@ $^
+
+clean:
+	rm -rf obj
+	$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
+
+strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB)
+	strip $^
+
+LATEST_TAG=$(shell git describe --tags --abbrev=0 master)
+dist:
+	git archive --format=tar.gz -9 --worktree-attributes \
+	    --prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz
+
+.PHONY: all
+.PHONY: clean
+.PHONY: deps
+.PHONY: dist
+.PHONY: api
+.PHONY: api_client
+.PHONY: mk_build_dir
diff --git a/Makefile.mingw b/Makefile.mingw
index 24f33a11..632eca0c 100644
--- a/Makefile.mingw
+++ b/Makefile.mingw
@@ -1,9 +1,10 @@
 CXX = g++
+WINDRES = windres
 CXXFLAGS = -O2 -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
 NEEDED_CXXFLAGS = -std=c++11
 BOOST_SUFFIX = -mt
 INCFLAGS = -I/usr/include/ -I/usr/local/include/
-LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/c/dev/openssl -L/c/dev/boost/lib
+LDFLAGS = -mwindows -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/c/dev/openssl -L/c/dev/boost/lib
 LDLIBS = -Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_regex$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) -Wl,-Bstatic -lssl -Wl,-Bstatic -lcrypto -Wl,-Bstatic -lz -Wl,-Bstatic -lwsock32 -Wl,-Bstatic -lws2_32 -Wl,-Bstatic -lgdi32 -Wl,-Bstatic -liphlpapi -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -Wl,-Bstatic -lpthread
 
 ifeq ($(USE_AESNI),1)
diff --git a/NTCPSession.cpp b/NTCPSession.cpp
index 0ac2e74b..2584f584 100644
--- a/NTCPSession.cpp
+++ b/NTCPSession.cpp
@@ -25,7 +25,6 @@ namespace transport
 		m_TerminationTimer (m_Server.GetService ()), m_IsEstablished (false), m_IsTerminated (false),
 		m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_IsSending (false)
 	{		
-		m_DHKeysPair = transports.GetNextDHKeysPair ();
 		m_Establisher = new Establisher;
 	}
 	
diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp
new file mode 100644
index 00000000..b039c9b3
--- /dev/null
+++ b/Win32/Win32App.cpp
@@ -0,0 +1,168 @@
+#include <string.h>
+#include <windows.h>
+#include <shellapi.h>
+//#include "../Daemon.h"
+#include "resource.h"
+#include "Win32App.h"
+
+#define ID_ABOUT 2000
+#define ID_EXIT 2001
+
+#define ID_TRAY_ICON 2050
+#define WM_TRAYICON (WM_USER + 1)
+
+void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem)
+{
+    HMENU hPopup = CreatePopupMenu();
+    InsertMenu (hPopup, 0, MF_BYPOSITION | MF_STRING, ID_ABOUT, "About...");
+    InsertMenu (hPopup, 1, MF_BYPOSITION | MF_STRING, ID_EXIT , "Exit");
+    SetMenuDefaultItem (hPopup, ID_ABOUT, FALSE);
+    SetFocus (hWnd);
+    SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0);
+
+    POINT p;
+    if (!curpos)
+    {
+        GetCursorPos (&p);
+        curpos = &p;
+    }
+
+    WORD cmd = TrackPopupMenu (hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, curpos->x, curpos->y, 0, hWnd, NULL);
+    SendMessage (hWnd, WM_COMMAND, cmd, 0);
+
+    DestroyMenu(hPopup);
+}
+
+void AddTrayIcon (HWND hWnd)
+{
+    NOTIFYICONDATA nid;
+    memset(&nid, 0, sizeof(nid));
+    nid.cbSize = sizeof(nid);
+    nid.hWnd = hWnd;
+    nid.uID = ID_TRAY_ICON;
+    nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+    nid.uCallbackMessage = WM_TRAYICON;
+    // TODO: must set correct icon
+   // nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (IDI_ICON1));
+    {
+        char    szIconFile[512];
+
+        GetSystemDirectory( szIconFile, sizeof( szIconFile ) );
+        if ( szIconFile[ strlen( szIconFile ) - 1 ] != '\\' )
+            strcat( szIconFile, "\\" );
+        strcat( szIconFile, "shell32.dll" );
+        //  Icon #23 (0-indexed) in shell32.dll is a "help" icon.
+        ExtractIconEx( szIconFile, 23, NULL, &(nid.hIcon), 1 );
+    }
+    strcpy (nid.szTip, "i2pd");
+    Shell_NotifyIcon(NIM_ADD, &nid );
+}
+
+void RemoveTrayIcon (HWND hWnd)
+{
+    NOTIFYICONDATA nid;
+    nid.hWnd = hWnd;
+    nid.uID = ID_TRAY_ICON;
+    Shell_NotifyIcon (NIM_DELETE, &nid);
+}
+
+static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    switch (uMsg)
+    {
+        case WM_CREATE:
+        {
+            AddTrayIcon (hWnd);
+            break;
+        }
+        case WM_CLOSE:
+        {
+            RemoveTrayIcon (hWnd);
+            PostQuitMessage (0);
+            break;
+        }
+        case WM_COMMAND:
+        {
+            switch (LOWORD(wParam))
+            {
+                case ID_ABOUT:
+                {
+                    MessageBox( hWnd, TEXT("i2pd"), TEXT("About"), MB_ICONINFORMATION | MB_OK );
+                    return 0;
+                }
+                case ID_EXIT:
+                {
+                    PostMessage (hWnd, WM_CLOSE, 0, 0);
+                    return 0;
+                }
+            }
+            break;
+        }
+        case WM_TRAYICON:
+        {
+            SetForegroundWindow (hWnd);
+            switch (lParam)
+            {
+                case WM_RBUTTONUP:
+                {
+                    SetForegroundWindow (hWnd);
+                    ShowPopupMenu(hWnd, NULL, -1);
+                    PostMessage (hWnd, WM_APP + 1, 0, 0);
+                    break;
+                }
+            }
+            break;
+        }
+    }
+    return DefWindowProc( hWnd, uMsg, wParam, lParam);
+}
+
+ int WINAPI WinMain (HINSTANCE hInst, HINSTANCE prev, LPSTR cmdline, int show)
+ {
+    // check if tunning already
+    if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")))
+    {
+        MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK);
+        return 0;
+    }
+    // register main window
+    WNDCLASSEX wclx;
+    memset (&wclx, 0, sizeof(wclx));
+    wclx.cbSize = sizeof(wclx);
+    wclx.style = 0;
+    wclx.lpfnWndProc = WndProc;
+    wclx.cbClsExtra = 0;
+    wclx.cbWndExtra = 0;
+    wclx.hInstance = hInst;
+    wclx.hIcon = LoadIcon (hInst, MAKEINTRESOURCE (IDI_ICON1));
+    wclx.hIconSm = LoadIcon (hInst, MAKEINTRESOURCE (IDI_ICON1));
+    wclx.hCursor = LoadCursor (NULL, IDC_ARROW);
+    wclx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+    wclx.lpszMenuName = NULL;
+    wclx.lpszClassName = I2PD_WIN32_CLASSNAME;
+    RegisterClassEx (&wclx);
+    // create new window
+    if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 150, NULL, NULL, hInst, NULL))
+    {
+        MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
+        return 1;
+    }
+
+  /*  // init
+    char * argv[] = { (char *)"i2pd" };
+    Daemon.init(sizeof (argv)/sizeof (argv[0]), argv);
+    // start
+    Daemon.start ();*/
+    // main loop
+    MSG msg;
+    while (GetMessage (&msg, NULL, 0, 0 ))
+    {
+        TranslateMessage (&msg);
+        DispatchMessage (&msg);
+    }
+   /* // atop
+    Daemon.stop ();*/
+    // terminate
+    UnregisterClass (I2PD_WIN32_CLASSNAME, hInst);
+    return msg.wParam;
+ }
diff --git a/Win32/Win32App.h b/Win32/Win32App.h
new file mode 100644
index 00000000..8b14ae1b
--- /dev/null
+++ b/Win32/Win32App.h
@@ -0,0 +1,6 @@
+#ifndef WIN32APP_H__
+#define WIN32APP_H__
+
+#define I2PD_WIN32_CLASSNAME "i2pd main window"
+
+#endif // WIN32APP_H__
diff --git a/i2pd.cpp b/i2pd.cpp
index 32749d16..6167f10e 100644
--- a/i2pd.cpp
+++ b/i2pd.cpp
@@ -1,4 +1,3 @@
-#include <thread>
 #include <stdlib.h>
 #include "Daemon.h"
 
@@ -6,12 +5,7 @@ int main( int argc, char* argv[] )
 {
 	Daemon.init(argc, argv);
 	if (Daemon.start())
-	{
-		while (Daemon.running)
-		{
-			std::this_thread::sleep_for (std::chrono::seconds(1));
-		}
-	}
+		Daemon.run ();
 	Daemon.stop();
 	return EXIT_SUCCESS;
 }