diff --git a/Win32/.gitignore b/Win32/.gitignore
index d62f96f6..4952e30b 100644
--- a/Win32/.gitignore
+++ b/Win32/.gitignore
@@ -6,3 +6,5 @@
 !*.vcxproj
 !*.vcxproj.filters
 !.gitignore
+!*.cpp
+!*.h
diff --git a/Win32/Win32Service.cpp b/Win32/Win32Service.cpp
new file mode 100644
index 00000000..4fd53361
--- /dev/null
+++ b/Win32/Win32Service.cpp
@@ -0,0 +1,502 @@
+#include "Win32Service.h"
+#include <assert.h>
+#include <strsafe.h>
+#include <windows.h>
+
+#include "Transports.h"
+#include "NTCPSession.h"
+#include "Tunnel.h"
+#include "NetDb.h"
+#include "util.h"
+
+I2PService *I2PService::s_service = NULL;
+
+
+BOOL I2PService::Run(I2PService &service)
+{
+	s_service = &service;
+
+	SERVICE_TABLE_ENTRY serviceTable[] =
+	{
+		{ service.m_name, ServiceMain },
+		{ NULL, NULL }
+	};
+
+	return StartServiceCtrlDispatcher(serviceTable);
+}
+
+
+void WINAPI I2PService::ServiceMain(DWORD dwArgc, PSTR *pszArgv)
+{
+	assert(s_service != NULL);
+
+	s_service->m_statusHandle = RegisterServiceCtrlHandler(
+		s_service->m_name, ServiceCtrlHandler);
+	if (s_service->m_statusHandle == NULL)
+	{
+		throw GetLastError();
+	}
+
+	s_service->Start(dwArgc, pszArgv);
+}
+
+
+void WINAPI I2PService::ServiceCtrlHandler(DWORD dwCtrl)
+{
+	switch (dwCtrl)
+	{
+	case SERVICE_CONTROL_STOP: s_service->Stop(); break;
+	case SERVICE_CONTROL_PAUSE: s_service->Pause(); break;
+	case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break;
+	case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break;
+	case SERVICE_CONTROL_INTERROGATE: break;
+	default: break;
+	}
+}
+
+
+I2PService::I2PService(PSTR pszServiceName,
+	BOOL fCanStop,
+	BOOL fCanShutdown,
+	BOOL fCanPauseContinue) : _httpServer(nullptr)
+{
+	m_name = (pszServiceName == NULL) ? "" : pszServiceName;
+
+	m_statusHandle = NULL;
+
+	m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+
+	m_status.dwCurrentState = SERVICE_START_PENDING;
+
+	DWORD dwControlsAccepted = 0;
+	if (fCanStop)
+		dwControlsAccepted |= SERVICE_ACCEPT_STOP;
+	if (fCanShutdown)
+		dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
+	if (fCanPauseContinue)
+		dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
+	m_status.dwControlsAccepted = dwControlsAccepted;
+
+	m_status.dwWin32ExitCode = NO_ERROR;
+	m_status.dwServiceSpecificExitCode = 0;
+	m_status.dwCheckPoint = 0;
+	m_status.dwWaitHint = 0;
+
+	m_fStopping = FALSE;
+
+	// Create a manual-reset event that is not signaled at first to indicate 
+	// the stopped signal of the service.
+	m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+	if (m_hStoppedEvent == NULL)
+	{
+		throw GetLastError();
+	}
+}
+
+
+I2PService::~I2PService(void)
+{
+	if (m_hStoppedEvent)
+	{
+		CloseHandle(m_hStoppedEvent);
+		m_hStoppedEvent = NULL;
+	}
+}
+
+
+void I2PService::Start(DWORD dwArgc, PSTR *pszArgv)
+{
+	try
+	{
+		SetServiceStatus(SERVICE_START_PENDING);
+
+		OnStart(dwArgc, pszArgv);
+
+		SetServiceStatus(SERVICE_RUNNING);
+	}
+	catch (DWORD dwError)
+	{
+		WriteErrorLogEntry("Service Start", dwError);
+
+		SetServiceStatus(SERVICE_STOPPED, dwError);
+	}
+	catch (...)
+	{
+		WriteEventLogEntry("Service failed to start.", EVENTLOG_ERROR_TYPE);
+
+		SetServiceStatus(SERVICE_STOPPED);
+	}
+}
+
+
+void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv)
+{
+	WriteEventLogEntry("CppWindowsService in OnStart",
+		EVENTLOG_INFORMATION_TYPE);
+
+	i2p::util::config::OptionParser(dwArgc, pszArgv);
+	i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs);
+	i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"),
+		i2p::util::config::GetArg("-port", 17070));
+
+	_httpServer = new i2p::util::HTTPServer(i2p::util::config::GetArg("-httpport", 7070));
+	_httpServer->Start();
+	WriteEventLogEntry("HTTPServer started",
+		EVENTLOG_INFORMATION_TYPE);
+	i2p::data::netdb.Start();
+	WriteEventLogEntry("NetDB started",
+		EVENTLOG_INFORMATION_TYPE);
+	i2p::transports.Start();
+	WriteEventLogEntry("Transports started",
+		EVENTLOG_INFORMATION_TYPE);
+	i2p::tunnel::tunnels.Start();
+	WriteEventLogEntry("Tunnels started",
+		EVENTLOG_INFORMATION_TYPE);
+	_worker = new std::thread(std::bind(&I2PService::WorkerThread, this));
+}
+
+
+void I2PService::WorkerThread()
+{
+	while (!m_fStopping)
+	{
+		::Sleep(1000);  // Simulate some lengthy operations.
+	}
+
+	// Signal the stopped event.
+	SetEvent(m_hStoppedEvent);
+}
+
+
+void I2PService::Stop()
+{
+	DWORD dwOriginalState = m_status.dwCurrentState;
+	try
+	{
+		SetServiceStatus(SERVICE_STOP_PENDING);
+
+		OnStop();
+
+		SetServiceStatus(SERVICE_STOPPED);
+	}
+	catch (DWORD dwError)
+	{
+		WriteErrorLogEntry("Service Stop", dwError);
+
+		SetServiceStatus(dwOriginalState);
+	}
+	catch (...)
+	{
+		WriteEventLogEntry("Service failed to stop.", EVENTLOG_ERROR_TYPE);
+
+		SetServiceStatus(dwOriginalState);
+	}
+}
+
+
+void I2PService::OnStop()
+{
+	// Log a service stop message to the Application log.
+	WriteEventLogEntry("CppWindowsService in OnStop",
+		EVENTLOG_INFORMATION_TYPE);
+
+	i2p::tunnel::tunnels.Stop();
+	WriteEventLogEntry("Tunnels stoped",
+		EVENTLOG_INFORMATION_TYPE);
+	i2p::transports.Stop();
+	WriteEventLogEntry("Transports stoped",
+		EVENTLOG_INFORMATION_TYPE);
+	i2p::data::netdb.Stop();
+	WriteEventLogEntry("NetDB stoped",
+		EVENTLOG_INFORMATION_TYPE);
+	_httpServer->Stop();
+	WriteEventLogEntry("HTTPServer stoped",
+		EVENTLOG_INFORMATION_TYPE);
+	delete _httpServer;
+
+	m_fStopping = TRUE;
+	if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
+	{
+		throw GetLastError();
+	}
+	_worker->join();
+	delete _worker;
+}
+
+
+void I2PService::Pause()
+{
+	try
+	{
+		SetServiceStatus(SERVICE_PAUSE_PENDING);
+
+		OnPause();
+
+		SetServiceStatus(SERVICE_PAUSED);
+	}
+	catch (DWORD dwError)
+	{
+		WriteErrorLogEntry("Service Pause", dwError);
+
+		SetServiceStatus(SERVICE_RUNNING);
+	}
+	catch (...)
+	{
+		WriteEventLogEntry("Service failed to pause.", EVENTLOG_ERROR_TYPE);
+
+		SetServiceStatus(SERVICE_RUNNING);
+	}
+}
+
+
+void I2PService::OnPause()
+{
+}
+
+
+void I2PService::Continue()
+{
+	try
+	{
+		SetServiceStatus(SERVICE_CONTINUE_PENDING);
+
+		OnContinue();
+
+		SetServiceStatus(SERVICE_RUNNING);
+	}
+	catch (DWORD dwError)
+	{
+		WriteErrorLogEntry("Service Continue", dwError);
+
+		SetServiceStatus(SERVICE_PAUSED);
+	}
+	catch (...)
+	{
+		WriteEventLogEntry("Service failed to resume.", EVENTLOG_ERROR_TYPE);
+
+		SetServiceStatus(SERVICE_PAUSED);
+	}
+}
+
+
+void I2PService::OnContinue()
+{
+}
+
+
+void I2PService::Shutdown()
+{
+	try
+	{
+		OnShutdown();
+
+		SetServiceStatus(SERVICE_STOPPED);
+	}
+	catch (DWORD dwError)
+	{
+		WriteErrorLogEntry("Service Shutdown", dwError);
+	}
+	catch (...)
+	{
+		WriteEventLogEntry("Service failed to shut down.", EVENTLOG_ERROR_TYPE);
+	}
+}
+
+
+void I2PService::OnShutdown()
+{
+}
+
+
+void I2PService::SetServiceStatus(DWORD dwCurrentState,
+	DWORD dwWin32ExitCode,
+	DWORD dwWaitHint)
+{
+	static DWORD dwCheckPoint = 1;
+
+
+	m_status.dwCurrentState = dwCurrentState;
+	m_status.dwWin32ExitCode = dwWin32ExitCode;
+	m_status.dwWaitHint = dwWaitHint;
+
+	m_status.dwCheckPoint =
+		((dwCurrentState == SERVICE_RUNNING) ||
+		(dwCurrentState == SERVICE_STOPPED)) ?
+		0 : dwCheckPoint++;
+
+	::SetServiceStatus(m_statusHandle, &m_status);
+}
+
+
+void I2PService::WriteEventLogEntry(PSTR pszMessage, WORD wType)
+{
+	HANDLE hEventSource = NULL;
+	LPCSTR lpszStrings[2] = { NULL, NULL };
+
+	hEventSource = RegisterEventSource(NULL, m_name);
+	if (hEventSource)
+	{
+		lpszStrings[0] = m_name;
+		lpszStrings[1] = pszMessage;
+
+		ReportEvent(hEventSource,  // Event log handle
+			wType,                 // Event type
+			0,                     // Event category
+			0,                     // Event identifier
+			NULL,                  // No security identifier
+			2,                     // Size of lpszStrings array
+			0,                     // No binary data
+			lpszStrings,           // Array of strings
+			NULL                   // No binary data
+			);
+
+		DeregisterEventSource(hEventSource);
+	}
+}
+
+
+void I2PService::WriteErrorLogEntry(PSTR pszFunction, DWORD dwError)
+{
+	char szMessage[260];
+	StringCchPrintf(szMessage, ARRAYSIZE(szMessage),
+		"%s failed w/err 0x%08lx", pszFunction, dwError);
+	WriteEventLogEntry(szMessage, EVENTLOG_ERROR_TYPE);
+}
+
+//*****************************************************************************
+
+void FreeHandles(SC_HANDLE schSCManager, SC_HANDLE schService)
+{
+	if (schSCManager)
+	{
+		CloseServiceHandle(schSCManager);
+		schSCManager = NULL;
+	}
+	if (schService)
+	{
+		CloseServiceHandle(schService);
+		schService = NULL;
+	}
+}
+
+void InstallService(PSTR pszServiceName,
+	PSTR pszDisplayName,
+	DWORD dwStartType,
+	PSTR pszDependencies,
+	PSTR pszAccount,
+	PSTR pszPassword)
+{
+	char szPath[MAX_PATH];
+	SC_HANDLE schSCManager = NULL;
+	SC_HANDLE schService = NULL;
+
+	if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) == 0)
+	{
+		printf("GetModuleFileName failed w/err 0x%08lx\n", GetLastError());
+		FreeHandles(schSCManager, schService);
+		return;
+	}
+
+	// Open the local default service control manager database
+	schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT |
+		SC_MANAGER_CREATE_SERVICE);
+	if (schSCManager == NULL)
+	{
+		printf("OpenSCManager failed w/err 0x%08lx\n", GetLastError());
+		FreeHandles(schSCManager, schService);
+		return;
+	}
+
+	// Install the service into SCM by calling CreateService
+	schService = CreateService(
+		schSCManager,                   // SCManager database
+		pszServiceName,                 // Name of service
+		pszDisplayName,                 // Name to display
+		SERVICE_QUERY_STATUS,           // Desired access
+		SERVICE_WIN32_OWN_PROCESS,      // Service type
+		dwStartType,                    // Service start type
+		SERVICE_ERROR_NORMAL,           // Error control type
+		szPath,                         // Service's binary
+		NULL,                           // No load ordering group
+		NULL,                           // No tag identifier
+		pszDependencies,                // Dependencies
+		pszAccount,                     // Service running account
+		pszPassword                     // Password of the account
+		);
+	if (schService == NULL)
+	{
+		printf("CreateService failed w/err 0x%08lx\n", GetLastError());
+		FreeHandles(schSCManager, schService);
+		return;
+	}
+
+	printf("%s is installed.\n", pszServiceName);
+
+	// Centralized cleanup for all allocated resources.
+	FreeHandles(schSCManager, schService);
+}
+
+void UninstallService(PSTR pszServiceName)
+{
+	SC_HANDLE schSCManager = NULL;
+	SC_HANDLE schService = NULL;
+	SERVICE_STATUS ssSvcStatus = {};
+
+	// Open the local default service control manager database
+	schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+	if (schSCManager == NULL)
+	{
+		printf("OpenSCManager failed w/err 0x%08lx\n", GetLastError());
+		FreeHandles(schSCManager, schService);
+		return;
+	}
+
+	// Open the service with delete, stop, and query status permissions
+	schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP |
+		SERVICE_QUERY_STATUS | DELETE);
+	if (schService == NULL)
+	{
+		printf("OpenService failed w/err 0x%08lx\n", GetLastError());
+		FreeHandles(schSCManager, schService);
+		return;
+	}
+
+	// Try to stop the service
+	if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus))
+	{
+		printf("Stopping %s.", pszServiceName);
+		Sleep(1000);
+
+		while (QueryServiceStatus(schService, &ssSvcStatus))
+		{
+			if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
+			{
+				printf(".");
+				Sleep(1000);
+			}
+			else break;
+		}
+
+		if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED)
+		{
+			printf("\n%s is stopped.\n", pszServiceName);
+		}
+		else
+		{
+			printf("\n%s failed to stop.\n", pszServiceName);
+		}
+	}
+
+	// Now remove the service by calling DeleteService.
+	if (!DeleteService(schService))
+	{
+		printf("DeleteService failed w/err 0x%08lx\n", GetLastError());
+		FreeHandles(schSCManager, schService);
+		return;
+	}
+
+	printf("%s is removed.\n", pszServiceName);
+
+	// Centralized cleanup for all allocated resources.
+	FreeHandles(schSCManager, schService);
+}
\ No newline at end of file
diff --git a/Win32/Win32Service.h b/Win32/Win32Service.h
new file mode 100644
index 00000000..1fb8fa50
--- /dev/null
+++ b/Win32/Win32Service.h
@@ -0,0 +1,66 @@
+#ifndef WIN_32_SERVICE_H__
+#define WIN_32_SERVICE_H__
+
+#include "HTTPServer.h"
+#include <thread>
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+class I2PService
+{
+public:
+
+	I2PService(PSTR pszServiceName,
+		BOOL fCanStop = TRUE,
+		BOOL fCanShutdown = TRUE,
+		BOOL fCanPauseContinue = FALSE);
+
+	virtual ~I2PService(void);
+
+	static BOOL Run(I2PService &service);
+	void Stop();
+
+protected:
+
+	virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
+	virtual void OnStop();
+	virtual void OnPause();
+	virtual void OnContinue();
+	virtual void OnShutdown();
+	void SetServiceStatus(DWORD dwCurrentState,
+		DWORD dwWin32ExitCode = NO_ERROR,
+		DWORD dwWaitHint = 0);
+	void WriteEventLogEntry(PSTR pszMessage, WORD wType);
+	void WriteErrorLogEntry(PSTR pszFunction,
+		DWORD dwError = GetLastError());
+
+private:
+
+	static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
+	static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
+	void WorkerThread();
+	void Start(DWORD dwArgc, PSTR *pszArgv);
+	void Pause();
+	void Continue();
+	void Shutdown();
+	static I2PService* s_service;
+	PSTR m_name;
+	SERVICE_STATUS m_status;
+	SERVICE_STATUS_HANDLE m_statusHandle;
+
+	BOOL m_fStopping;
+	HANDLE m_hStoppedEvent;
+	i2p::util::HTTPServer* _httpServer;
+	std::thread* _worker;
+};
+
+void InstallService(PSTR pszServiceName,
+	PSTR pszDisplayName,
+	DWORD dwStartType,
+	PSTR pszDependencies,
+	PSTR pszAccount,
+	PSTR pszPassword);
+
+void UninstallService(PSTR pszServiceName);
+
+#endif // WIN_32_SERVICE_H__
\ No newline at end of file
diff --git a/Win32/i2pd.sln b/Win32/i2pd.sln
index af0c8110..1f9a8d7c 100644
--- a/Win32/i2pd.sln
+++ b/Win32/i2pd.sln
@@ -8,13 +8,19 @@ EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
 		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|Win32.ActiveCfg = Debug|Win32
 		{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|Win32.Build.0 = Debug|Win32
+		{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|x64.ActiveCfg = Debug|x64
+		{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|x64.Build.0 = Debug|x64
 		{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|Win32.ActiveCfg = Release|Win32
 		{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|Win32.Build.0 = Release|Win32
+		{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|x64.ActiveCfg = Release|x64
+		{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/Win32/i2pd.vcxproj b/Win32/i2pd.vcxproj
index c6f95ed7..e5903630 100644
--- a/Win32/i2pd.vcxproj
+++ b/Win32/i2pd.vcxproj
@@ -5,10 +5,18 @@
       <Configuration>Debug</Configuration>
       <Platform>Win32</Platform>
     </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
     <ProjectConfiguration Include="Release|Win32">
       <Configuration>Release</Configuration>
       <Platform>Win32</Platform>
     </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\base64.cpp" />
@@ -33,6 +41,7 @@
     <ClCompile Include="..\TunnelEndpoint.cpp" />
     <ClCompile Include="..\TunnelGateway.cpp" />
     <ClCompile Include="..\util.cpp" />
+    <ClCompile Include="Win32Service.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\base64.h" />
@@ -63,6 +72,7 @@
     <ClInclude Include="..\TunnelEndpoint.h" />
     <ClInclude Include="..\TunnelGateway.h" />
     <ClInclude Include="..\util.h" />
+    <ClInclude Include="Win32Service.h" />
   </ItemGroup>
   <PropertyGroup Label="Globals">
     <ProjectGuid>{930568EC-31C9-406A-AD1C-9636DF5D8FAA}</ProjectGuid>
@@ -75,6 +85,12 @@
     <PlatformToolset>v120</PlatformToolset>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v120</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
@@ -82,25 +98,47 @@
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v120</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <IncludePath>./..;$(BOOST);$(CRYPTOPP);$(IncludePath)</IncludePath>
     <LibraryPath>$(BOOST)\stage\lib;$(CRYPTOPP)\cryptopp\Win32\Output\$(Configuration)\;$(LibraryPath)</LibraryPath>
     <SourcePath>./..;$(VC_SourcePath);</SourcePath>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <IncludePath>./..;$(BOOST);$(CRYPTOPP);$(IncludePath)</IncludePath>
+    <LibraryPath>$(BOOST)\stage\lib;$(CRYPTOPP)\cryptopp\Win32\Output\$(Configuration)\;$(LibraryPath)</LibraryPath>
+    <SourcePath>./..;$(VC_SourcePath);</SourcePath>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <IncludePath>.\boost;.\cryptopp;$(IncludePath)</IncludePath>
     <LibraryPath>.\stage-x86\lib;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <IncludePath>.\boost;.\cryptopp;$(IncludePath)</IncludePath>
+    <LibraryPath>.\stage-x86\lib;$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <WarningLevel>Level3</WarningLevel>
@@ -114,6 +152,19 @@
       <AdditionalDependencies>cryptlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PreprocessorDefinitions>_MBCS;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>cryptlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
       <WarningLevel>Level3</WarningLevel>
@@ -128,6 +179,20 @@
       <OptimizeReferences>true</OptimizeReferences>
     </Link>
   </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
diff --git a/Win32/i2pd.vcxproj.filters b/Win32/i2pd.vcxproj.filters
index 0eb7dc3d..dbb228cd 100644
--- a/Win32/i2pd.vcxproj.filters
+++ b/Win32/i2pd.vcxproj.filters
@@ -81,6 +81,9 @@
     <ClCompile Include="..\Reseed.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Win32Service.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\Identity.h">
@@ -167,5 +170,8 @@
     <ClInclude Include="..\Reseed.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Win32Service.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/i2p.cpp b/i2p.cpp
index 97914b5e..d50f3d44 100644
--- a/i2p.cpp
+++ b/i2p.cpp
@@ -11,6 +11,8 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
+#else
+#include "./Win32/Win32Service.h"
 #endif
 
 #include "Log.h"
@@ -25,6 +27,26 @@
 #include "util.h"
 
 
+#ifdef _WIN32
+// Internal name of the service
+#define SERVICE_NAME             "i2pService"
+
+// Displayed name of the service
+#define SERVICE_DISPLAY_NAME     "i2p router service"
+
+// Service start options.
+#define SERVICE_START_TYPE       SERVICE_DEMAND_START
+
+// List of service dependencies - "dep1\0dep2\0\0"
+#define SERVICE_DEPENDENCIES     ""
+
+// The name of the account under which the service should run
+#define SERVICE_ACCOUNT          "NT AUTHORITY\\LocalService"
+
+// The password to the service account name
+#define SERVICE_PASSWORD         NULL
+#endif
+
 // Global
 int running = 1;
 int isDaemon;
@@ -60,7 +82,7 @@ void handle_signal(int sig)
 int main( int argc, char* argv[] )
 {
   i2p::util::config::OptionParser(argc,argv);
-  isDaemon = i2p::util::config::GetArg("-daemon", 0);
+  isDaemon = i2p::util::config::GetArg("-daemon", 1);
 #ifdef _WIN32
   setlocale(LC_CTYPE, "");
   SetConsoleCP(1251);
@@ -139,6 +161,40 @@ int main( int argc, char* argv[] )
   sigaction(SIGABRT,&sa,0);
   sigaction(SIGTERM,&sa,0);
   sigaction(SIGINT,&sa,0);
+#else
+  std::string serviceControl = i2p::util::config::GetArg("-service", "none");
+  if (serviceControl == "install")
+  {
+	  InstallService(
+		  SERVICE_NAME,               // Name of service
+		  SERVICE_DISPLAY_NAME,       // Name to display
+		  SERVICE_START_TYPE,         // Service start type
+		  SERVICE_DEPENDENCIES,       // Dependencies
+		  SERVICE_ACCOUNT,            // Service running account
+		  SERVICE_PASSWORD            // Password of the account
+		  );
+	  return 0;
+  }
+  else if (serviceControl == "remove")
+  {
+	  UninstallService(SERVICE_NAME);
+	  return 0;
+  }
+  else if (serviceControl != "none")
+  {
+	  LogPrint(" --service=install  to install the service.");
+	  LogPrint(" --service=remove   to remove the service.");
+	  return -1;
+  }
+  else if (isDaemon)
+  {
+	  I2PService service(SERVICE_NAME);
+	  if (!I2PService::Run(service))
+	  {
+		  LogPrint("Service failed to run w/err 0x%08lx\n", GetLastError());
+	  }
+	  return 0;
+  }
 #endif
 
   //TODO: This is an ugly workaround. fix it.
diff --git a/portable_endian.h b/portable_endian.h
new file mode 100644
index 00000000..3355d2b9
--- /dev/null
+++ b/portable_endian.h
@@ -0,0 +1,115 @@
+#ifndef PORTABLE_ENDIAN_H__
+#define PORTABLE_ENDIAN_H__
+ 
+#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
+ 
+#	define __WINDOWS__
+ 
+#endif
+ 
+#if defined(__linux__) || defined(__CYGWIN__)
+ 
+#	include <endian.h>
+ 
+#elif defined(__APPLE__)
+ 
+#	include <libkern/OSByteOrder.h>
+ 
+#	define htobe16 OSSwapHostToBigInt16
+#	define htole16 OSSwapHostToLittleInt16
+#	define be16toh OSSwapBigToHostInt16
+#	define le16toh OSSwapLittleToHostInt16
+ 
+#	define htobe32 OSSwapHostToBigInt32
+#	define htole32 OSSwapHostToLittleInt32
+#	define be32toh OSSwapBigToHostInt32
+#	define le32toh OSSwapLittleToHostInt32
+ 
+#	define htobe64 OSSwapHostToBigInt64
+#	define htole64 OSSwapHostToLittleInt64
+#	define be64toh OSSwapBigToHostInt64
+#	define le64toh OSSwapLittleToHostInt64
+ 
+#	define __BYTE_ORDER    BYTE_ORDER
+#	define __BIG_ENDIAN    BIG_ENDIAN
+#	define __LITTLE_ENDIAN LITTLE_ENDIAN
+#	define __PDP_ENDIAN    PDP_ENDIAN
+ 
+#elif defined(__OpenBSD__)
+ 
+#	include <sys/endian.h>
+ 
+#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+ 
+#	include <sys/endian.h>
+ 
+#	define be16toh betoh16
+#	define le16toh letoh16
+ 
+#	define be32toh betoh32
+#	define le32toh letoh32
+ 
+#	define be64toh betoh64
+#	define le64toh letoh64
+ 
+#elif defined(__WINDOWS__)
+
+#define INCL_EXTRA_HTON_FUNCTIONS
+#define NOMINMAX
+#	include <winsock2.h>
+#undef NOMINMAX
+//#	include <sys/param.h>
+ 
+#	if BYTE_ORDER == LITTLE_ENDIAN
+ 
+#		define htobe16 htons
+#		define htole16(x) (x)
+#		define be16toh ntohs
+#		define le16toh(x) (x)
+ 
+#		define htobe32 htonl
+#		define htole32(x) (x)
+#		define be32toh ntohl
+#		define le32toh(x) (x)
+ 
+#		define htobe64 htonll
+#		define htole64(x) (x)
+#		define be64toh ntohll
+#		define le64toh(x) (x)
+ 
+#	elif BYTE_ORDER == BIG_ENDIAN
+ 
+		/* that would be xbox 360 */
+#		define htobe16(x) (x)
+#		define htole16(x) __builtin_bswap16(x)
+#		define be16toh(x) (x)
+#		define le16toh(x) __builtin_bswap16(x)
+ 
+#		define htobe32(x) (x)
+#		define htole32(x) __builtin_bswap32(x)
+#		define be32toh(x) (x)
+#		define le32toh(x) __builtin_bswap32(x)
+ 
+#		define htobe64(x) (x)
+#		define htole64(x) __builtin_bswap64(x)
+#		define be64toh(x) (x)
+#		define le64toh(x) __builtin_bswap64(x)
+ 
+#	else
+ 
+#		error byte order not supported
+ 
+#	endif
+ 
+#	define __BYTE_ORDER    BYTE_ORDER
+#	define __BIG_ENDIAN    BIG_ENDIAN
+#	define __LITTLE_ENDIAN LITTLE_ENDIAN
+#	define __PDP_ENDIAN    PDP_ENDIAN
+ 
+#else
+ 
+#	error platform not supported
+ 
+#endif
+ 
+#endif
\ No newline at end of file