@@ -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