<commit_before>#ifndef POLYHOOK_H
#define POLYHOOK_H
#include <windows.h>
#include "../Capstone/include/capstone.h"
#include <DbgHelp.h>
#include <string>
#include <vector>
#include <mutex>
#include <algorithm>
#include <utility>
#include <TlHelp32.h>
#pragma comment(lib,"Dbghelp.lib")
#pragma comment(lib,"capstone.lib")
#define PLH_SHOW_DEBUG_MESSAGES 1 //To print messages even in release

namespace PLH {
	namespace Tools
	{
		inline void XTrace(char* fmt, ...)
		{
			va_list args;
			va_start(args, fmt);
#if defined(_DEBUG) || defined(PLH_SHOW_DEBUG_MESSAGES)
			vfprintf_s(stdout, fmt, args);
#endif
			va_end(args);
		}

		class ThreadHandle
		{
		public:
			//Thread ID, OpenThread's AccessFlag 
			ThreadHandle(DWORD ThreadId, DWORD  DesiredAccessFlags) : m_ThreadId(ThreadId), m_IsSuspended(false)
			{
				m_hThread = OpenThread(DesiredAccessFlags, FALSE, ThreadId);
			}

			//false resumes, true suspends
			void ToggleSuspend(bool Suspend)
			{
				if (Suspend && !m_IsSuspended)
				{
					if(SuspendThread(m_hThread) != -1)
						m_IsSuspended = true;
				}else if (!Suspend && m_IsSuspended){
					if(ResumeThread(m_hThread) != -1)
						m_IsSuspended = false;
				}
			}

			~ThreadHandle()
			{
				if (m_IsSuspended)
					ToggleSuspend(false);

				if (m_hThread)
					CloseHandle(m_hThread);
			}
		private:
			bool m_IsSuspended;
			HANDLE m_hThread;
			DWORD m_ThreadId;
		};

		class ThreadManager
		{
		public:
			void SuspendThreads()
			{
				UpdateThreadList(GetCurrentThreadId());
				for (ThreadHandle& ThreadInstance : m_SuspendedThreads)
				{
					ThreadInstance.ToggleSuspend(true);
				}
			}
			void ResumeThreads()
			{
				for (ThreadHandle& ThreadInstance : m_SuspendedThreads)
				{
					ThreadInstance.ToggleSuspend(false);
				}
			}
		private:
			void UpdateThreadList(DWORD CallingThreadId)
			{
				m_SuspendedThreads.clear();
				HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
				if (h == INVALID_HANDLE_VALUE)
					return;

				THREADENTRY32 te;
				te.dwSize = sizeof(te);
				for (Thread32First(h, &te), te.dwSize = sizeof(te); Thread32Next(h, &te); )
				{
					if (te.dwSize < FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID))
						continue;
					<commit_msg>Error checking and copy/move constructors in ThreadHandle class<commit_after>#ifndef POLYHOOK_H
#define POLYHOOK_H
#include <windows.h>
#include "../Capstone/include/capstone.h"
#include <DbgHelp.h>
#include <string>
#include <vector>
#include <mutex>
#include <algorithm>
#include <utility>
#include <TlHelp32.h>
#pragma comment(lib,"Dbghelp.lib")
#pragma comment(lib,"capstone.lib")
#define PLH_SHOW_DEBUG_MESSAGES 1 //To print messages even in release

namespace PLH {
	namespace Tools
	{
		inline void XTrace(char* fmt, ...)
		{
			va_list args;
			va_start(args, fmt);
#if defined(_DEBUG) || defined(PLH_SHOW_DEBUG_MESSAGES)
			vfprintf_s(stdout, fmt, args);
#endif
			va_end(args);
		}

		class ThreadHandle
		{
		public:
			//Thread ID, OpenThread's AccessFlag 
			ThreadHandle(DWORD ThreadId, DWORD  DesiredAccessFlags) : m_ThreadId(ThreadId), m_IsSuspended(false)
			{
				m_hThread = OpenThread(DesiredAccessFlags, FALSE, ThreadId);
				if(m_hThread == NULL)
					throw "PolyHook: Failed to open thread in class ThreadHandle";
			}

			//Only allow once instance to control a handle
			ThreadHandle(const ThreadHandle& other) = delete; //copy
			ThreadHandle& operator=(const ThreadHandle& other) = delete; //copy assignment

			//Move
			ThreadHandle(ThreadHandle &&other) noexcept
				: m_IsSuspended(other.m_IsSuspended)
				, m_hThread(other.m_hThread)
				, m_ThreadId(other.m_ThreadId)
			{
				other.m_hThread = nullptr;
				other.m_IsSuspended = false;
			}

			//Move assignment
			ThreadHandle& operator=(ThreadHandle &&other) noexcept
			{
				if (this != &other)
				{
					m_IsSuspended = other.m_IsSuspended;
					m_hThread = other.m_hThread;
					m_ThreadId = other.m_ThreadId;

					other.m_hThread = nullptr;
					other.m_IsSuspended = false;
				}
				return *this;
			}


			//false resumes, true suspends
			void ToggleSuspend(bool Suspend)
			{
				if (Suspend && !m_IsSuspended)
				{
					if(SuspendThread(m_hThread) != -1)
						m_IsSuspended = true;
				}else if (!Suspend && m_IsSuspended){
					if(ResumeThread(m_hThread) != -1)
						m_IsSuspended = false;
				}
			}

			~ThreadHandle()
			{
				if (m_IsSuspended)
					ToggleSuspend(false);

				if (m_hThread)
					CloseHandle(m_hThread);
			}
		private:
			bool m_IsSuspended;
			HANDLE m_hThread;
			DWORD m_ThreadId;
		};

		class ThreadManager
		{
		public:
			void SuspendThreads()
			{
				UpdateThreadList(GetCurrentThreadId());
				for (ThreadHandle& ThreadInstance : m_SuspendedThreads)
				{
					ThreadInstance.ToggleSuspend(true);
				}
			}

			void ResumeThreads()
			{
				for (ThreadHandle& ThreadInstance : m_SuspendedThreads)
				{
					ThreadInstance.ToggleSuspend(false);
				}
			}
		private:
			void UpdateThreadList(DWORD CallingThreadId)
			{
				m_SuspendedThreads.clear();
				HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
				if (h == INVALID_HANDLE_VALUE)
					return;

				THREADENTRY32 te;
				te.dwSize = sizeof(te);
				BOOL Result = FALSE;
				//Loop threads
				for (Result = Thread32First(h, &te), te.dwSize = sizeof(te); Result == TRUE && Thread32Next(h, &te); )
				{
					//Verify size field was set properly
					if (te.dwSize < RTL_SIZEOF_THROUGH_FIELD(THREADENTRY32, th32OwnerProcessID))
						continue;
					
{'fraction_non_alphanumeric': 0.11211901306240929, 'fraction_numerical': 0.007619738751814224, 'mean_word_length': 3.478472786352559, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2086066', 'n_tokens_mistral': 2444, 'n_tokens_neox': 1935, 'n_words': 395}