diff --git a/GUI/misc.h b/GUI/misc.h
index 103ed10..29afe99 100644
--- a/GUI/misc.h
+++ b/GUI/misc.h
@@ -2,7 +2,7 @@
 #define MISC_H
 
 #include "qtcommon.h"
-#include "pipe.h"
+#include "types.h"
 
 QString GetFullModuleName(DWORD processId, HMODULE module = NULL);
 QString GetModuleName(DWORD processId, HMODULE module = NULL);
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
index a130c35..cf8d5af 100644
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -1,6 +1,5 @@
 set(vnrhost_src
   host.cc
-  pipe.cc
   textthread.cc
 )
 
diff --git a/host/host.cc b/host/host.cc
index 0ce63c1..27e3536 100644
--- a/host/host.cc
+++ b/host/host.cc
@@ -3,68 +3,157 @@
 // Branch IHF/main.cpp, rev 111
 
 #include "host.h"
-#include "pipe.h"
 #include "const.h"
 #include "defs.h"
 #include "../vnrhook/hijack/texthook.h"
 
-struct ProcessRecord
+namespace
 {
-	HANDLE processHandle;
-	HANDLE sectionMutex;
-	HANDLE section;
-	LPVOID sectionMap;
-	HANDLE hostPipe;
-};
+	struct ProcessRecord
+	{
+		HANDLE processHandle;
+		HANDLE sectionMutex;
+		HANDLE section;
+		LPVOID sectionMap;
+		HANDLE hostPipe;
+	};
 
-// Artikash 5/31/2018: required for unordered_map to work with struct key
-template <> struct std::hash<ThreadParam> { size_t operator()(const ThreadParam& tp) const { return std::hash<__int64>()((tp.pid + tp.hook) ^ (tp.retn + tp.spl)); } };
-bool operator==(const ThreadParam& one, const ThreadParam& two) { return one.pid == two.pid && one.hook == two.hook && one.retn == two.retn && one.spl == two.spl; }
+	ThreadEventCallback OnCreate, OnRemove;
+	ProcessEventCallback OnAttach, OnDetach;
 
-// Artikash 7/20/2018: similar to std::lock guard but use Winapi objects for cross process comms
-class MutexLocker
-{
-	HANDLE mutex;
-public:
-	MutexLocker(HANDLE mutex) : mutex(mutex) { WaitForSingleObject(mutex, 0); }
-	~MutexLocker() { if (mutex != INVALID_HANDLE_VALUE && mutex != nullptr) ReleaseMutex(mutex); }
-};
+	bool operator==(const ThreadParam& one, const ThreadParam& two) { return one.pid == two.pid && one.hook == two.hook && one.retn == two.retn && one.spl == two.spl; }
+	std::unordered_map<ThreadParam, TextThread*> textThreadsByParams;
+	std::unordered_map<DWORD, ProcessRecord> processRecordsByIds;
 
-std::unordered_map<ThreadParam, TextThread*> textThreadsByParams;
-std::unordered_map<DWORD, ProcessRecord> processRecordsByIds;
+	std::recursive_mutex hostMutex;
 
-std::recursive_mutex hostMutex;
+	DWORD DUMMY[100];
+	ThreadParam CONSOLE{ 0, -1ULL, -1ULL, -1ULL };
 
-ThreadEventCallback OnCreate, OnRemove;
-ProcessEventCallback OnAttach, OnDetach;
+	void DispatchText(ThreadParam tp, const BYTE* text, int len)
+	{
+		if (!text || len <= 0) return;
+		LOCK hostLock(hostMutex);
+		TextThread *it;
+		if ((it = textThreadsByParams[tp]) == nullptr)
+			OnCreate(it = textThreadsByParams[tp] = new TextThread(tp, Host::GetHookParam(tp).type));
+		it->AddText(text, len);
+	}
 
-DWORD DUMMY[100];
+	void RemoveThreads(std::function<bool(ThreadParam)> removeIf)
+	{
+		LOCK hostLock(hostMutex);
+		std::vector<ThreadParam> removedThreads;
+		for (auto i : textThreadsByParams)
+			if (removeIf(i.first))
+			{
+				OnRemove(i.second);
+				//delete i.second; // Artikash 7/24/2018: FIXME: Qt GUI updates on another thread, so I can't delete this yet.
+				removedThreads.push_back(i.first);
+			}
+		for (auto i : removedThreads) textThreadsByParams.erase(i);
+	}
 
-ThreadParam CONSOLE{ 0, -1ULL, -1ULL, -1ULL };
+	void RegisterProcess(DWORD pid, HANDLE hostPipe)
+	{
+		LOCK hostLock(hostMutex);
+		ProcessRecord record;
+		record.hostPipe = hostPipe;
+		record.section = OpenFileMappingW(FILE_MAP_READ, FALSE, (ITH_SECTION_ + std::to_wstring(pid)).c_str());
+		record.sectionMap = MapViewOfFile(record.section, FILE_MAP_READ, 0, 0, HOOK_SECTION_SIZE / 2); // jichi 1/16/2015: Changed to half to hook section size
+		record.processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
+		record.sectionMutex = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, (ITH_HOOKMAN_MUTEX_ + std::to_wstring(pid)).c_str());
+		processRecordsByIds[pid] = record;
+		OnAttach(pid);
+	}
 
-#define HOST_LOCK std::lock_guard<std::recursive_mutex> hostLocker(hostMutex) // Synchronized scope for accessing private data
+	void UnregisterProcess(DWORD pid)
+	{
+		LOCK hostLock(hostMutex);
+		ProcessRecord pr = processRecordsByIds[pid];
+		if (!pr.hostPipe) return;
+		CloseHandle(pr.sectionMutex);
+		UnmapViewOfFile(pr.sectionMap);
+		CloseHandle(pr.processHandle);
+		CloseHandle(pr.section);
+		processRecordsByIds[pid] = {};
+		RemoveThreads([=](ThreadParam tp) { return tp.pid == pid; });
+		OnDetach(pid);
+	}
+
+	void StartPipe()
+	{
+		std::thread([]()
+		{
+			HANDLE hookPipe = CreateNamedPipeW(ITH_TEXT_PIPE, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL);
+			HANDLE hostPipe = CreateNamedPipeW(ITH_COMMAND_PIPE, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL);
+			ConnectNamedPipe(hookPipe, nullptr);
+
+			// jichi 9/27/2013: why recursion?
+			// Artikash 5/20/2018: Easy way to create a new pipe for another process
+			StartPipe();
+
+			BYTE buffer[PIPE_BUFFER_SIZE + 1] = {};
+			DWORD bytesRead, processId;
+			ReadFile(hookPipe, &processId, sizeof(processId), &bytesRead, nullptr);
+			RegisterProcess(processId, hostPipe);
+
+			while (ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr))
+				switch (*(int*)buffer)
+				{
+					//case HOST_NOTIFICATION_NEWHOOK:	// Artikash 7/18/2018: Useless for now, but could be used to implement smth later
+					//break;
+				case HOST_NOTIFICATION_RMVHOOK:
+				{
+					auto info = *(HookRemovedNotif*)buffer;
+					RemoveThreads([=](ThreadParam tp) { return tp.pid == processId && tp.hook == info.address; });
+				}
+				break;
+				case HOST_NOTIFICATION_TEXT:
+				{
+					auto info = *(ConsoleOutputNotif*)buffer;
+					USES_CONVERSION;
+					Host::AddConsoleOutput(A2W(info.message));
+				}
+				break;
+				default:
+				{
+					ThreadParam tp = *(ThreadParam*)buffer;
+					DispatchText(tp, buffer + sizeof(tp), bytesRead - sizeof(tp));
+				}
+				break;
+				}
+
+			DisconnectNamedPipe(hookPipe);
+			DisconnectNamedPipe(hostPipe);
+			UnregisterProcess(processId);
+			CloseHandle(hookPipe);
+			CloseHandle(hostPipe);
+		}).detach();
+	}
+}
 
 namespace Host
 {
-	DLLEXPORT void Start(ProcessEventCallback onAttach, ProcessEventCallback onDetach, ThreadEventCallback onCreate, ThreadEventCallback onRemove)
+	void Start(ProcessEventCallback onAttach, ProcessEventCallback onDetach, ThreadEventCallback onCreate, ThreadEventCallback onRemove)
 	{
 		OnAttach = onAttach; OnDetach = onDetach; OnCreate = onCreate; OnRemove = onRemove;
 		OnCreate(textThreadsByParams[CONSOLE] = new TextThread(CONSOLE, USING_UNICODE));
-		CreatePipe();
+		StartPipe();
 	}
 
-	DLLEXPORT void Close()
+	void Close()
 	{
 		// Artikash 7/25/2018: This is only called when NextHooker is closed, at which point Windows should free everything itself...right?
 #ifdef _DEBUG // Check memory leaks
-		HOST_LOCK;
+		LOCK hostLock(hostMutex);
 		OnRemove = [](TextThread* textThread) { delete textThread; };
 		for (auto i : processRecordsByIds) UnregisterProcess(i.first);
 		delete textThreadsByParams[CONSOLE];
 #endif
 	}
 
-	DLLEXPORT bool InjectProcess(DWORD processId, DWORD timeout)
+	bool InjectProcess(DWORD processId, DWORD timeout)
 	{
 		if (processId == GetCurrentProcessId()) return false;
 
@@ -112,48 +201,49 @@ namespace Host
 		return false;
 	}
 
-	DLLEXPORT bool DetachProcess(DWORD processId)
+	bool DetachProcess(DWORD processId)
 	{
 		int command = HOST_COMMAND_DETACH;
 		return WriteFile(processRecordsByIds[processId].hostPipe, &command, sizeof(command), DUMMY, nullptr);
 	}
 
-	DLLEXPORT bool InsertHook(DWORD pid, HookParam hp, std::string name)
+	bool InsertHook(DWORD pid, HookParam hp, std::string name)
 	{
 		auto info = InsertHookCmd(hp, name);
 		return WriteFile(processRecordsByIds[pid].hostPipe, &info, sizeof(info), DUMMY, nullptr);
 	}
 
-	DLLEXPORT bool RemoveHook(DWORD pid, unsigned __int64 addr)
+	bool RemoveHook(DWORD pid, unsigned __int64 addr)
 	{
 		auto info = RemoveHookCmd(addr);
 		return WriteFile(processRecordsByIds[pid].hostPipe, &info, sizeof(info), DUMMY, nullptr);
 	}
 
-	DLLEXPORT HookParam GetHookParam(DWORD pid, unsigned __int64 addr)
+	HookParam GetHookParam(DWORD pid, unsigned __int64 addr)
 	{
-		HOST_LOCK;
+		LOCK hostLock(hostMutex);
 		HookParam ret = {};
 		ProcessRecord pr = processRecordsByIds[pid];
 		if (pr.sectionMap == nullptr) return ret;
-		MutexLocker locker(pr.sectionMutex);
+		WaitForSingleObject(pr.sectionMutex, 0);
 		const TextHook* hooks = (const TextHook*)pr.sectionMap;
 		for (int i = 0; i < MAX_HOOK; ++i)
 			if (hooks[i].Address() == addr)
 				ret = hooks[i].hp;
+		ReleaseMutex(pr.sectionMutex);
 		return ret;
 	}
 
-	DLLEXPORT HookParam GetHookParam(ThreadParam tp) { return GetHookParam(tp.pid, tp.hook); }
+	HookParam GetHookParam(ThreadParam tp) { return GetHookParam(tp.pid, tp.hook); }
 
-	DLLEXPORT std::wstring GetHookName(DWORD pid, unsigned __int64 addr)
+	std::wstring GetHookName(DWORD pid, unsigned __int64 addr)
 	{
 		if (pid == 0) return L"Console";
-		HOST_LOCK;
+		LOCK hostLock(hostMutex);
 		std::string buffer = "";
 		ProcessRecord pr = processRecordsByIds[pid];
 		if (pr.sectionMap == nullptr) return L"";
-		MutexLocker locker(pr.sectionMutex);
+		WaitForSingleObject(pr.sectionMutex, 0);
 		const TextHook* hooks = (const TextHook*)pr.sectionMap;
 		for (int i = 0; i < MAX_HOOK; ++i)
 			if (hooks[i].Address() == addr)
@@ -161,72 +251,22 @@ namespace Host
 				buffer.resize(hooks[i].NameLength());
 				ReadProcessMemory(pr.processHandle, hooks[i].Name(), &buffer[0], hooks[i].NameLength(), nullptr);
 			}
+		ReleaseMutex(pr.sectionMutex);
 		USES_CONVERSION;
 		return std::wstring(A2W(buffer.c_str()));
 	}
 
-	DLLEXPORT TextThread* GetThread(ThreadParam tp)
+	TextThread* GetThread(ThreadParam tp)
 	{
-		HOST_LOCK;
+		LOCK hostLock(hostMutex);
 		return textThreadsByParams[tp];
 	}
 
-	DLLEXPORT void AddConsoleOutput(std::wstring text)
+	void AddConsoleOutput(std::wstring text)
 	{
-		HOST_LOCK;
+		LOCK hostLock(hostMutex);
 		textThreadsByParams[CONSOLE]->AddSentence(std::wstring(text));
 	}
 }
 
-void DispatchText(ThreadParam tp, const BYTE* text, int len)
-{
-	if (!text || len <= 0) return;
-	HOST_LOCK;
-	TextThread *it;
-	if ((it = textThreadsByParams[tp]) == nullptr)
-		OnCreate(it = textThreadsByParams[tp] = new TextThread(tp, Host::GetHookParam(tp).type));
-	it->AddText(text, len);
-}
-
-void RemoveThreads(bool(*RemoveIf)(ThreadParam, ThreadParam), ThreadParam cmp)
-{
-	HOST_LOCK;
-	std::vector<ThreadParam> removedThreads;
-	for (auto i : textThreadsByParams)
-		if (RemoveIf(i.first, cmp))
-		{
-			OnRemove(i.second);
-			//delete i.second; // Artikash 7/24/2018: FIXME: Qt GUI updates on another thread, so I can't delete this yet.
-			removedThreads.push_back(i.first);
-		}
-	for (auto i : removedThreads) textThreadsByParams.erase(i);
-}
-
-void RegisterProcess(DWORD pid, HANDLE hostPipe)
-{
-	HOST_LOCK;
-	ProcessRecord record;
-	record.hostPipe = hostPipe;
-	record.section = OpenFileMappingW(FILE_MAP_READ, FALSE, (ITH_SECTION_ + std::to_wstring(pid)).c_str());
-	record.sectionMap = MapViewOfFile(record.section, FILE_MAP_READ, 0, 0, HOOK_SECTION_SIZE / 2); // jichi 1/16/2015: Changed to half to hook section size
-	record.processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
-	record.sectionMutex = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, (ITH_HOOKMAN_MUTEX_ + std::to_wstring(pid)).c_str());
-	processRecordsByIds[pid] = record;
-	OnAttach(pid);
-}
-
-void UnregisterProcess(DWORD pid)
-{
-	HOST_LOCK;
-	ProcessRecord pr = processRecordsByIds[pid];
-	if (!pr.hostPipe) return;
-	CloseHandle(pr.sectionMutex);
-	UnmapViewOfFile(pr.sectionMap);
-	CloseHandle(pr.processHandle);
-	CloseHandle(pr.section);
-	processRecordsByIds[pid] = {};
-	RemoveThreads([](auto one, auto two) { return one.pid == two.pid; }, { pid, 0, 0, 0 });
-	OnDetach(pid);
-}
-
 // EOF
diff --git a/host/host.h b/host/host.h
index 7cdacc5..d2eb9cb 100644
--- a/host/host.h
+++ b/host/host.h
@@ -7,31 +7,23 @@
 #include "common.h"
 #include "textthread.h"
 
-#define DLLEXPORT __declspec(dllexport)
-
 typedef std::function<void(DWORD)> ProcessEventCallback;
 typedef std::function<void(TextThread*)> ThreadEventCallback;
 
 namespace Host
 {
-	DLLEXPORT void Start(ProcessEventCallback onAttach, ProcessEventCallback onDetach, ThreadEventCallback onCreate, ThreadEventCallback onRemove);
-	DLLEXPORT void Close();
-	DLLEXPORT bool InjectProcess(DWORD pid, DWORD timeout = 5000);
-	DLLEXPORT bool DetachProcess(DWORD pid);
+	void Start(ProcessEventCallback onAttach, ProcessEventCallback onDetach, ThreadEventCallback onCreate, ThreadEventCallback onRemove);
+	void Close();
+	bool InjectProcess(DWORD pid, DWORD timeout = 5000);
+	bool DetachProcess(DWORD pid);
 
-	DLLEXPORT bool InsertHook(DWORD pid, HookParam hp, std::string name = "");
-	DLLEXPORT bool RemoveHook(DWORD pid, unsigned __int64 addr);
-	DLLEXPORT HookParam GetHookParam(DWORD pid, unsigned __int64 addr);
-	DLLEXPORT HookParam GetHookParam(ThreadParam tp);
-	DLLEXPORT std::wstring GetHookName(DWORD pid, unsigned __int64 addr);
+	bool InsertHook(DWORD pid, HookParam hp, std::string name = "");
+	bool RemoveHook(DWORD pid, unsigned __int64 addr);
+	HookParam GetHookParam(DWORD pid, unsigned __int64 addr);
+	HookParam GetHookParam(ThreadParam tp);
+	std::wstring GetHookName(DWORD pid, unsigned __int64 addr);
 
-	DLLEXPORT TextThread* GetThread(ThreadParam tp);
-	DLLEXPORT void AddConsoleOutput(std::wstring text);
+	TextThread* GetThread(ThreadParam tp);
+	void AddConsoleOutput(std::wstring text);
 }
-
-void DispatchText(ThreadParam tp, const BYTE *text, int len);
-void RemoveThreads(bool(*RemoveIf)(ThreadParam, ThreadParam), ThreadParam cmp);
-void RegisterProcess(DWORD pid, HANDLE hostPipe);
-void UnregisterProcess(DWORD pid);
-
 // EOF
diff --git a/host/pipe.cc b/host/pipe.cc
deleted file mode 100644
index acc809e..0000000
--- a/host/pipe.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// pipe.cc
-// 8/24/2013 jichi
-// Branch IHF/pipe.cpp, rev 93
-
-#include "pipe.h"
-#include "host.h"
-#include "defs.h"
-#include "const.h"
-
-void CreatePipe()
-{
-	std::thread([]()
-	{
-		HANDLE hookPipe = CreateNamedPipeW(ITH_TEXT_PIPE, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL);
-		HANDLE hostPipe = CreateNamedPipeW(ITH_COMMAND_PIPE, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL);
-		ConnectNamedPipe(hookPipe, nullptr);
-
-		// jichi 9/27/2013: why recursion?
-		// Artikash 5/20/2018: Easy way to create a new pipe for another process
-		CreatePipe();
-
-		BYTE buffer[PIPE_BUFFER_SIZE + 1] = {};
-		DWORD bytesRead, processId;
-		ReadFile(hookPipe, &processId, sizeof(processId), &bytesRead, nullptr);
-		RegisterProcess(processId, hostPipe);
-
-		while (ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr))
-			switch (*(int*)buffer)
-			{
-			//case HOST_NOTIFICATION_NEWHOOK:	// Artikash 7/18/2018: Useless for now, but could be used to implement smth later
-			//break;
-			case HOST_NOTIFICATION_RMVHOOK:
-			{
-				auto info = *(HookRemovedNotif*)buffer;
-				RemoveThreads([](auto one, auto two) { return one.pid == two.pid && one.hook == two.hook; }, { processId, info.address });
-			}
-			break;
-			case HOST_NOTIFICATION_TEXT:
-			{
-				auto info = *(ConsoleOutputNotif*)buffer;
-				USES_CONVERSION;
-				Host::AddConsoleOutput(A2W(info.message));
-			}
-			break;
-			default:
-			{
-				ThreadParam tp = *(ThreadParam*)buffer;
-				DispatchText(tp, buffer + sizeof(tp), bytesRead - sizeof(tp));
-			}
-			break;
-			}
-
-		DisconnectNamedPipe(hookPipe);
-		DisconnectNamedPipe(hostPipe);
-		UnregisterProcess(processId);
-		CloseHandle(hookPipe);
-		CloseHandle(hostPipe);
-	}).detach();
-}
-
-// EOF
diff --git a/host/textthread.cc b/host/textthread.cc
index b9d5811..d53d41e 100644
--- a/host/textthread.cc
+++ b/host/textthread.cc
@@ -5,8 +5,6 @@
 #include "textthread.h"
 #include "const.h"
 
-#define TT_LOCK std::lock_guard<std::recursive_mutex> ttLocker(ttMutex) // Synchronized scope for accessing private data
-
 TextThread::TextThread(ThreadParam tp, DWORD status) :
 	deletionEvent(CreateEventW(nullptr, FALSE, FALSE, NULL)),
 	flushThread([&]() { while (WaitForSingleObject(deletionEvent, 100) == WAIT_TIMEOUT) Flush(); }),
@@ -25,13 +23,13 @@ TextThread::~TextThread()
 
 std::wstring TextThread::GetStore()
 {
-	TT_LOCK;
+	LOCK ttLock(ttMutex);
 	return storage;
 }
 
 bool TextThread::Flush()
 {
-	TT_LOCK;
+	LOCK ttLock(ttMutex);
 	if (timestamp - GetTickCount() < 250 || buffer.size() == 0) return true; // TODO: let user change delay before sentence is flushed
 	std::wstring sentence;
 	if (status & USING_UNICODE)
@@ -51,14 +49,14 @@ bool TextThread::Flush()
 
 void TextThread::AddSentence(std::wstring sentence)
 {
-	TT_LOCK;
+	LOCK ttLock(ttMutex);
 	if (Output) sentence = Output(this, sentence);
 	storage.append(sentence);
 }
 
 void TextThread::AddText(const BYTE *con, int len)
 {
-	TT_LOCK;
+	LOCK ttLock(ttMutex);
 	buffer.insert(buffer.end(), con, con + len);
 	timestamp = GetTickCount();
 }
diff --git a/host/textthread.h b/host/textthread.h
index 99e4c64..8b8a811 100644
--- a/host/textthread.h
+++ b/host/textthread.h
@@ -5,7 +5,7 @@
 // Branch: ITH/TextThread.h, rev 120
 
 #include "common.h"
-#include "pipe.h"
+#include "types.h"
 
 
 class TextThread
@@ -13,9 +13,9 @@ class TextThread
 	typedef std::function<std::wstring(TextThread*, std::wstring)> ThreadOutputCallback;
 public:
 	TextThread(ThreadParam tp, DWORD status);
-	virtual ~TextThread();
+	~TextThread();
 
-	virtual std::wstring GetStore();
+	std::wstring GetStore();
 	ThreadParam GetThreadParam() { return tp; }
 
 	void RegisterOutputCallBack(ThreadOutputCallback cb) { Output = cb; }
diff --git a/include/pipe.h b/include/types.h
similarity index 86%
rename from include/pipe.h
rename to include/types.h
index 6eb9751..f47f4a6 100644
--- a/include/pipe.h
+++ b/include/types.h
@@ -3,8 +3,6 @@
 #include "common.h"
 #include "const.h"
 
-void CreatePipe();
-
 // jichi 3/7/2014: Add guessed comment
 struct HookParam 
 {
@@ -32,13 +30,16 @@ struct HookParam
 	HANDLE readerHandle; // Artikash 8/4/2018: handle for reader thread
 };
 
-struct ThreadParam // From hook
+
+struct ThreadParam // From hook, used internally by host as well
 {
 	DWORD pid; // jichi: 5/11/2014: The process ID
 	unsigned __int64 hook; // Artikash 6/6/2018: The insertion address of the hook
 	unsigned __int64 retn; // jichi 5/11/2014: The return address of the hook
 	unsigned __int64 spl;  // jichi 5/11/2014: the processed split value of the hook paramete
 };
+// Artikash 5/31/2018: required for unordered_map to work with struct key
+template <> struct std::hash<ThreadParam> { size_t operator()(const ThreadParam& tp) const { return std::hash<__int64>()((tp.pid + tp.hook) ^ (tp.retn + tp.spl)); } };
 
 struct InsertHookCmd // From host
 {
@@ -68,3 +69,5 @@ struct HookRemovedNotif // From hook
 	int command = HOST_NOTIFICATION_RMVHOOK;
 	unsigned __int64 address;
 };
+
+typedef std::lock_guard<std::recursive_mutex> LOCK;
diff --git a/vnrhook/hijack/texthook.h b/vnrhook/hijack/texthook.h
index 8bdac25..86dddec 100644
--- a/vnrhook/hijack/texthook.h
+++ b/vnrhook/hijack/texthook.h
@@ -8,7 +8,7 @@
 // - Clean up this file
 // - Reduce global variables. Use namespaces or singleton classes instead.
 #include "common.h"
-#include "pipe.h"
+#include "types.h"
 
 extern int currentHook;
 extern DWORD trigger;
diff --git a/vnrhook/main.cc b/vnrhook/main.cc
index 399695b..38f8a7e 100644
--- a/vnrhook/main.cc
+++ b/vnrhook/main.cc
@@ -32,6 +32,8 @@ hFile,
 hMutex,
 hmMutex;
 
+void CreatePipe();
+
 BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID unused)
 {
 	switch (fdwReason) 
diff --git a/vnrhook/main.h b/vnrhook/main.h
index 895f239..5e694f7 100644
--- a/vnrhook/main.h
+++ b/vnrhook/main.h
@@ -5,7 +5,7 @@
 // Branch: ITH/IHF_DLL.h, rev 66
 
 #include "common.h"
-#include "pipe.h"
+#include "types.h"
 
 void ConsoleOutput(LPCSTR text); // jichi 12/25/2013: Used to return length of sent text
 void NotifyHookInsert(HookParam hp, LPCSTR name);
diff --git a/vnrhook/pipe.cc b/vnrhook/pipe.cc
index edeb3f4..8dd8cb2 100644
--- a/vnrhook/pipe.cc
+++ b/vnrhook/pipe.cc
@@ -7,7 +7,7 @@
 # pragma warning (disable:4100)   // C4100: unreference formal parameter
 #endif // _MSC_VER
 
-#include "pipe.h"
+#include "types.h"
 #include "main.h"
 #include "hijack/texthook.h"
 #include "engine/match.h"