@@ -5694,24 +5694,37 @@ namespace Detours {
56945694		// Suspender
56955695		// ----------------------------------------------------------------
56965696
5697+ 		
56975698		Suspender::~Suspender() {
5699+ 			if (m_Mutex.Lock()) {
5700+ 				if (m_unSuspendDepth > 0) {
5701+ 					m_unSuspendDepth = 1;
5702+ 				}
5703+ 
5704+ 				m_Mutex.UnLock();
5705+ 			}
5706+ 
56985707			Resume();
56995708		}
57005709
5701- 		bool Suspender::Suspend() {
5710+ 		bool Suspender::Suspend(bool bSweepThreads ) {
57025711			if (!m_Mutex.Lock()) {
57035712				return false;
57045713			}
57055714
5706- 			const auto& hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, NULL);
5715+ 			if (m_unSuspendDepth > 0) {
5716+ 				++m_unSuspendDepth;
5717+ 				m_Mutex.UnLock();
5718+ 				return true;
5719+ 			}
5720+ 
5721+ 			const auto& hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
57075722			if (!hSnap || (hSnap == INVALID_HANDLE_VALUE)) {
57085723				m_Mutex.UnLock();
57095724				return false;
57105725			}
57115726
5712- 			THREADENTRY32 te;
5713- 			memset(&te, 0, sizeof(te));
5714- 
5727+ 			THREADENTRY32 te {};
57155728			te.dwSize = sizeof(THREADENTRY32);
57165729
57175730			if (!Thread32First(hSnap, &te)) {
@@ -5727,19 +5740,19 @@ namespace Detours {
57275740				return false;
57285741			}
57295742
5743+ 			m_SuspendedTIDs.clear();
5744+ 
57305745			do {
57315746				if ((pTEB->ClientId.UniqueProcess == te.th32OwnerProcessID) && (pTEB->ClientId.UniqueThread != te.th32ThreadID)) {
57325747					HANDLE hThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION | THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, FALSE, te.th32ThreadID);
57335748					if (hThread && (hThread != INVALID_HANDLE_VALUE)) {
57345749						if (SuspendThread(hThread) == static_cast<DWORD>(-1)) {
5750+ 							CloseHandle(hThread);
57355751							continue;
57365752						}
57375753
5738- 						CONTEXT ctx;
5739- 						memset(&ctx, 0, sizeof(CONTEXT));
5740- 
5754+ 						CONTEXT ctx {};
57415755						ctx.ContextFlags = CONTEXT_FULL;
5742- 
57435756						if (!GetThreadContext(hThread, &ctx)) {
57445757							ResumeThread(hThread);
57455758							CloseHandle(hThread);
@@ -5753,14 +5766,40 @@ namespace Detours {
57535766
57545767			CloseHandle(hSnap);
57555768
5756- 			if (!m_Mutex.UnLock()) {
5757- 				return false;
5769+ 			if (bSweepThreads) {
5770+ 				const DWORD64 unStartTick = GetTickCount64();
5771+ 
5772+ 				while (true) {
5773+ 					size_t unAdded = SuspendNewThreadsSnapshot();
5774+ 
5775+ 					if (GetTickCount64() - unStartTick >= 1000) {
5776+ 						break;
5777+ 					}
5778+ 
5779+ 					if (unAdded == 0) {
5780+ 						Sleep(50);
5781+ 					}
5782+ 				}
57585783			}
57595784
5785+ 			m_unSuspendDepth = 1;
5786+ 			m_Mutex.UnLock();
57605787			return true;
57615788		}
57625789
57635790		void Suspender::Resume() {
5791+ 			if (!m_Mutex.Lock())
5792+ 				return;
5793+ 
5794+ 			if (m_unSuspendDepth == 0) {
5795+ 				m_Mutex.UnLock();
5796+ 				return;
5797+ 			}
5798+ 
5799+ 			if (--m_unSuspendDepth > 0) {
5800+ 				m_Mutex.UnLock();
5801+ 				return;
5802+ 			}
57645803
57655804			for (auto& thread : m_Threads) {
57665805				SetThreadContext(thread.m_hHandle, &thread.m_CTX);
@@ -5769,6 +5808,9 @@ namespace Detours {
57695808			}
57705809
57715810			m_Threads.clear();
5811+ 			m_SuspendedTIDs.clear();
5812+ 
5813+ 			m_Mutex.UnLock();
57725814		}
57735815
57745816		bool Suspender::IsRegionExecuting(void* pAddress, size_t unSize) {
@@ -5817,7 +5859,7 @@ namespace Detours {
58175859		}
58185860
58195861		void Suspender::FixExecutionAddress(void* pAddress, void* pNewAddress) {
5820- 			if (!pAddress || pNewAddress) {
5862+ 			if (!pAddress || ! pNewAddress) {
58215863				return;
58225864			}
58235865
@@ -5844,6 +5886,56 @@ namespace Detours {
58445886			}
58455887		}
58465888
5889+ 		size_t Suspender::SuspendNewThreadsSnapshot() {
5890+ 			size_t unAdded = 0;
5891+ 
5892+ 			const auto& pTEB = GetTEB();
5893+ 			if (!pTEB) {
5894+ 				return 0;
5895+ 			}
5896+ 
5897+ 			const auto& hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
5898+ 			if (!hSnap || (hSnap == INVALID_HANDLE_VALUE)) {
5899+ 				return 0;
5900+ 			}
5901+ 
5902+ 			THREADENTRY32 te {};
5903+ 			te.dwSize = sizeof(THREADENTRY32);
5904+ 
5905+ 			if (!Thread32First(hSnap, &te)) {
5906+ 				CloseHandle(hSnap);
5907+ 				return 0;
5908+ 			}
5909+ 
5910+ 			do {
5911+ 				if ((pTEB->ClientId.UniqueProcess == te.th32OwnerProcessID) && (pTEB->ClientId.UniqueThread != te.th32ThreadID) && (m_SuspendedTIDs.find(te.th32ThreadID) == m_SuspendedTIDs.end())) {
5912+ 					HANDLE hThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION | THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, FALSE, te.th32ThreadID);
5913+ 					if (!hThread || (hThread == INVALID_HANDLE_VALUE))
5914+ 						continue;
5915+ 
5916+ 					if (SuspendThread(hThread) == static_cast<DWORD>(-1)) {
5917+ 						CloseHandle(hThread);
5918+ 						continue;
5919+ 					}
5920+ 
5921+ 					CONTEXT ctx {};
5922+ 					ctx.ContextFlags = CONTEXT_FULL;
5923+ 					if (!GetThreadContext(hThread, &ctx)) {
5924+ 						ResumeThread(hThread);
5925+ 						CloseHandle(hThread);
5926+ 						continue;
5927+ 					}
5928+ 
5929+ 					m_Threads.emplace_back(te.th32ThreadID, hThread, ctx);
5930+ 					m_SuspendedTIDs.insert(te.th32ThreadID);
5931+ 					++unAdded;
5932+ 				}
5933+ 			} while (Thread32Next(hSnap, &te));
5934+ 
5935+ 			CloseHandle(hSnap);
5936+ 			return unAdded;
5937+ 		}
5938+ 
58475939		Suspender g_Suspender;
58485940	} // namespace Sync
58495941
0 commit comments