@@ -192,17 +192,20 @@ namespace Detours {
192192 m_pCallBack = nullptr;
193193 m_pAddress = nullptr;
194194 m_unSize = 0;
195+ m_unActiveThreads = 0;
195196 m_bPendingDeletion = false;
197+ InitializeSRWLock(&m_Lock);
196198 }
197199
198200 fnMemoryHookCallBack m_pCallBack;
199201 void* m_pAddress;
200202 size_t m_unSize;
201203 std::deque<std::unique_ptr<Page>> m_Pages;
204+ std::atomic<DWORD> m_unActiveThreads;
202205 bool m_bPendingDeletion;
203- std::unordered_set<DWORD> m_PendingRestoreThreads ;
206+ SRWLOCK m_Lock ;
204207 } MEMORY_HOOK_RECORD, *PMEMORY_HOOK_RECORD;
205-
208+
206209 // ----------------------------------------------------------------
207210 // INTERRUPT_HOOK_RECORD
208211 // ----------------------------------------------------------------
@@ -217,10 +220,19 @@ namespace Detours {
217220 unsigned char m_unInterrupt;
218221 } INTERRUPT_HOOK_RECORD, *PINTERRUPT_HOOK_RECORD;
219222
223+ // ----------------------------------------------------------------
224+ // Locks
225+ // ----------------------------------------------------------------
226+
227+ static SRWLOCK g_MemoryHookRecordsLock = SRWLOCK_INIT;
228+ static SRWLOCK g_MemoryHookStacksLock = SRWLOCK_INIT;
229+
220230 // ----------------------------------------------------------------
221231 // Storage
222232 // ----------------------------------------------------------------
223233
234+ static std::unordered_map<DWORD, std::vector<PMEMORY_HOOK_RECORD>> g_MemoryHookOpenedStacks;
235+
224236 static std::deque<std::unique_ptr<HARDWARE_HOOK_RECORD>> g_HardwareHookRecords;
225237 static std::deque<std::unique_ptr<MEMORY_HOOK_RECORD>> g_MemoryHookRecords;
226238 static std::deque<std::unique_ptr<INTERRUPT_HOOK_RECORD>> g_InterruptHookRecords;
@@ -7357,39 +7369,69 @@ namespace Detours {
73577369 return false;
73587370 }
73597371
7360- const DWORD unCurrentTID = GetCurrentThreadId();
73617372 auto& eflags = *reinterpret_cast<REGISTER_FLAGS*>(&pCTX->EFlags);
7373+ const DWORD unCurrentTID = GetCurrentThreadId();
73627374
73637375 if (Exception.ExceptionCode == EXCEPTION_SINGLE_STEP) {
7364- for (auto it = g_MemoryHookRecords.begin(); it != g_MemoryHookRecords.end(); ++it) {
7365- const auto& pRecord = *it;
7366- if (!pRecord) {
7367- continue;
7376+ eflags.m_unTF = 0;
7377+
7378+ PMEMORY_HOOK_RECORD pRecord = nullptr;
7379+
7380+ AcquireSRWLockExclusive(&g_MemoryHookStacksLock);
7381+
7382+ {
7383+ auto it = g_MemoryHookOpenedStacks.find(unCurrentTID);
7384+ if (it != g_MemoryHookOpenedStacks.end() && !it->second.empty()) {
7385+ pRecord = it->second.back();
7386+ it->second.pop_back();
7387+ if (it->second.empty()) {
7388+ g_MemoryHookOpenedStacks.erase(it);
7389+ }
73687390 }
7391+ }
7392+
7393+ ReleaseSRWLockExclusive(&g_MemoryHookStacksLock);
7394+
7395+ if (!pRecord) {
7396+ return false;
7397+ }
73697398
7370- auto pit = pRecord->m_PendingRestoreThreads.find(unCurrentTID);
7371- if (pit != pRecord->m_PendingRestoreThreads.end()) {
7372- eflags.m_unTF = 0;
7399+ bool bNeedErase = false;
73737400
7401+ AcquireSRWLockExclusive(&pRecord->m_Lock);
7402+
7403+ {
7404+ const uint32_t unPrev = pRecord->m_unActiveThreads.fetch_sub(1, std::memory_order_acq_rel);
7405+ if (unPrev == 1) {
73747406 if (!pRecord->m_bPendingDeletion) {
73757407 for (const auto& pPage : pRecord->m_Pages) {
73767408 if (!pPage || !pPage->ChangeProtection(PAGE_NOACCESS)) {
7409+ ReleaseSRWLockExclusive(&pRecord->m_Lock);
73777410 return false;
73787411 }
73797412 }
7413+ } else {
7414+ bNeedErase = true;
73807415 }
7416+ }
7417+ }
73817418
7382- pRecord->m_PendingRestoreThreads.erase(pit );
7419+ ReleaseSRWLockExclusive(& pRecord->m_Lock );
73837420
7384- if (pRecord->m_bPendingDeletion && pRecord->m_PendingRestoreThreads.empty()) {
7421+ if (bNeedErase) {
7422+ AcquireSRWLockExclusive(&g_MemoryHookRecordsLock);
7423+
7424+ for (auto it = g_MemoryHookRecords.begin(); it != g_MemoryHookRecords.end(); ++it) {
7425+ if (it->get() == pRecord) {
73857426 g_MemoryHookRecords.erase(it);
7427+ break;
73867428 }
7387-
7388- return true;
73897429 }
7430+
7431+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock);
73907432 }
73917433
7392- return false ;
7434+ return true ;
73937435 }
73947436
73957437 if ((Exception.ExceptionCode != EXCEPTION_ACCESS_VIOLATION) || (Exception.NumberParameters < 2)) {
@@ -7401,12 +7443,12 @@ namespace Detours {
74017443 return false;
74027444 }
74037445
7404- const void* pFaultAddress = reinterpret_cast<void*>(Exception.ExceptionInformation[1]);
7446+ void* pFaultAddress = reinterpret_cast<void*>(Exception.ExceptionInformation[1]);
74057447 if (!pFaultAddress || (pFaultAddress == reinterpret_cast<void*>(-1))) {
74067448 return false;
74077449 }
74087450
7409- const void* pExceptionAddress = reinterpret_cast<void*>(Exception.ExceptionAddress);
7451+ void* pExceptionAddress = reinterpret_cast<void*>(Exception.ExceptionAddress);
74107452
74117453 MEMORY_HOOK_OPERATION unOperation = MEMORY_HOOK_OPERATION::MEMORY_READ;
74127454 if (unAccessType == 1) {
@@ -7416,36 +7458,55 @@ namespace Detours {
74167458 }
74177459
74187460 PMEMORY_HOOK_RECORD pTargetRecord = nullptr;
7419- for (const auto& pRecord : g_MemoryHookRecords) {
7420- if (!pRecord) {
7421- continue;
7422- }
74237461
7424- for (const auto& pPage : pRecord->m_Pages) {
7425- if (pPage && __is_in_range(pPage->GetPageAddress(), pPage->GetPageCapacity(), pFaultAddress)) {
7426- pTargetRecord = pRecord.get();
7427- break;
7462+ AcquireSRWLockShared(&g_MemoryHookRecordsLock);
7463+
7464+ {
7465+ for (const auto& pRecord : g_MemoryHookRecords) {
7466+ if (!pRecord) {
7467+ continue;
74287468 }
7429- }
74307469
7431- if (pTargetRecord) {
7432- break;
7470+ for (const auto& pPage : pRecord->m_Pages) {
7471+ if (pPage && __is_in_range(pPage->GetPageAddress(), pPage->GetPageCapacity(), pFaultAddress)) {
7472+ pTargetRecord = pRecord.get();
7473+ break;
7474+ }
7475+ }
7476+
7477+ if (pTargetRecord) {
7478+ break;
7479+ }
74337480 }
74347481 }
74357482
7483+ ReleaseSRWLockShared(&g_MemoryHookRecordsLock);
7484+
74367485 if (!pTargetRecord) {
74377486 return false;
74387487 }
74397488
7440- pTargetRecord->m_PendingRestoreThreads.insert(unCurrentTID );
7489+ AcquireSRWLockExclusive(& pTargetRecord->m_Lock );
74417490
7442- for (const auto& pPage : pTargetRecord->m_Pages) {
7443- if (!pPage || !pPage->RestoreProtection()) {
7444- pTargetRecord->m_PendingRestoreThreads.erase(unCurrentTID);
7445- return false;
7491+ {
7492+ const uint32_t unPrev = pTargetRecord->m_unActiveThreads.load(std::memory_order_acquire);
7493+ if (unPrev == 0) {
7494+ for (const auto& pPage : pTargetRecord->m_Pages) {
7495+ if (!pPage || !pPage->RestoreProtection()) {
7496+ ReleaseSRWLockExclusive(&pTargetRecord->m_Lock);
7497+ return false;
7498+ }
7499+ }
74467500 }
7501+ pTargetRecord->m_unActiveThreads.fetch_add(1, std::memory_order_acq_rel);
74477502 }
74487503
7504+ ReleaseSRWLockExclusive(&pTargetRecord->m_Lock);
7505+
7506+ AcquireSRWLockExclusive(&g_MemoryHookStacksLock);
7507+ g_MemoryHookOpenedStacks[unCurrentTID].push_back(pTargetRecord);
7508+ ReleaseSRWLockExclusive(&g_MemoryHookStacksLock);
7509+
74497510 eflags.m_unTF = 1;
74507511
74517512 if (__is_in_range(pTargetRecord->m_pAddress, pTargetRecord->m_unSize, pFaultAddress)) {
@@ -84865,62 +84926,74 @@ namespace Detours {
8486584926 return false;
8486684927 }
8486784928
84868- for (auto& pRecord : g_MemoryHookRecords) {
84869- if (pRecord->m_bPendingDeletion) {
84870- continue;
84871- }
84929+ AcquireSRWLockExclusive(&g_MemoryHookRecordsLock);
8487284930
84873- if (pRecord->m_pCallBack == pCallBack) {
84874- g_Suspender.Resume();
84875- return false;
84876- }
84931+ {
84932+ for (auto& pRecord : g_MemoryHookRecords) {
84933+ if (pRecord->m_bPendingDeletion) {
84934+ continue;
84935+ }
8487784936
84878- if (__is_range_in_range(pRecord->m_pAddress, pRecord->m_unSize, pAddress, unSize)) {
84879- g_Suspender.Resume();
84880- return false;
84881- }
84937+ if (pRecord->m_pCallBack == pCallBack) {
84938+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock);
84939+ g_Suspender.Resume();
84940+ return false;
84941+ }
8488284942
84883- auto vecRecordPages = __get_pages_info(pRecord->m_pAddress, pRecord->m_unSize, true);
84884- if (vecRecordPages.empty()) {
84885- continue;
84886- }
84943+ if (__is_range_in_range(pRecord->m_pAddress, pRecord->m_unSize, pAddress, unSize)) {
84944+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock);
84945+ g_Suspender.Resume();
84946+ return false;
84947+ }
8488784948
84888- for (const auto& pPage : vecPages) {
84889- for (const auto& pRecordPage : vecRecordPages) {
84890- if (__is_range_in_range(pRecordPage.m_pBaseAddress, pRecordPage.m_unSize, pPage.m_pBaseAddress, pPage.m_unSize)) {
84891- g_Suspender.Resume();
84892- return false;
84949+ auto vecRecordPages = __get_pages_info(pRecord->m_pAddress, pRecord->m_unSize, true);
84950+ if (vecRecordPages.empty()) {
84951+ continue;
84952+ }
84953+
84954+ for (const auto& pPage : vecPages) {
84955+ for (const auto& pRecordPage : vecRecordPages) {
84956+ if (__is_range_in_range(pRecordPage.m_pBaseAddress, pRecordPage.m_unSize, pPage.m_pBaseAddress, pPage.m_unSize)) {
84957+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock);
84958+ g_Suspender.Resume();
84959+ return false;
84960+ }
8489384961 }
8489484962 }
8489584963 }
84896- }
84897-
84898- auto pRecord = std::make_unique<MEMORY_HOOK_RECORD>();
84899- if (!pRecord) {
84900- g_Suspender.Resume();
84901- return false;
84902- }
84903-
84904- pRecord->m_pCallBack = pCallBack;
84905- pRecord->m_pAddress = pAddress;
84906- pRecord->m_unSize = unSize;
8490784964
84908- for ( auto& pi : vecPages) {
84909- auto pPage = std::make_unique<Page>(pi.m_pBaseAddress, false);
84910- if (!pPage) {
84965+ auto pRecord = std::make_unique<MEMORY_HOOK_RECORD>();
84966+ if (!pRecord) {
84967+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock);
8491184968 g_Suspender.Resume();
8491284969 return false;
8491384970 }
8491484971
84915- if (!pPage->ChangeProtection(PAGE_NOACCESS)) {
84916- g_Suspender.Resume();
84917- return false;
84972+ pRecord->m_pCallBack = pCallBack;
84973+ pRecord->m_pAddress = pAddress;
84974+ pRecord->m_unSize = unSize;
84975+
84976+ for (auto& pi : vecPages) {
84977+ auto pPage = std::make_unique<Page>(pi.m_pBaseAddress, false);
84978+ if (!pPage) {
84979+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock);
84980+ g_Suspender.Resume();
84981+ return false;
84982+ }
84983+
84984+ if (!pPage->ChangeProtection(PAGE_NOACCESS)) {
84985+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock);
84986+ g_Suspender.Resume();
84987+ return false;
84988+ }
84989+
84990+ pRecord->m_Pages.emplace_back(std::move(pPage));
8491884991 }
8491984992
84920- pRecord->m_Pages .emplace_back(std::move(pPage ));
84993+ g_MemoryHookRecords .emplace_back(std::move(pRecord ));
8492184994 }
8492284995
84923- g_MemoryHookRecords.emplace_back(std::move(pRecord) );
84996+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock );
8492484997
8492584998 g_Suspender.Resume();
8492684999 return true;
@@ -84936,34 +85009,52 @@ namespace Detours {
8493685009 return false;
8493785010 }
8493885011
85012+ AcquireSRWLockExclusive(&g_MemoryHookRecordsLock);
85013+
8493985014 for (auto it = g_MemoryHookRecords.begin(); it != g_MemoryHookRecords.end(); ++it) {
84940- if ((*it)->m_pCallBack == pCallBack) {
84941- if ((*it)->m_bPendingDeletion) {
84942- continue;
85015+ auto& pRecord = *it;
85016+ if (pRecord && pRecord->m_pCallBack == pCallBack) {
85017+
85018+ AcquireSRWLockExclusive(&pRecord->m_Lock);
85019+
85020+ if (pRecord->m_bPendingDeletion) {
85021+ ReleaseSRWLockExclusive(&pRecord->m_Lock);
85022+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock);
85023+ g_Suspender.Resume();
85024+ return true;
8494385025 }
8494485026
84945- for (auto& pPage : (*it) ->m_Pages) {
85027+ for (auto& pPage : pRecord ->m_Pages) {
8494685028 if (!pPage || !pPage->RestoreProtection()) {
85029+ ReleaseSRWLockExclusive(&pRecord->m_Lock);
85030+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock);
8494785031 g_Suspender.Resume();
8494885032 return false;
8494985033 }
8495085034 }
8495185035
84952- (*it) ->m_bPendingDeletion = true;
85036+ pRecord ->m_bPendingDeletion = true;
8495385037
84954- if ((*it)->m_PendingRestoreThreads.empty()) {
85038+ if (pRecord->m_unActiveThreads.load(std::memory_order_acquire) == 0) {
85039+ ReleaseSRWLockExclusive(&pRecord->m_Lock);
8495585040 g_MemoryHookRecords.erase(it);
85041+ } else {
85042+ ReleaseSRWLockExclusive(&pRecord->m_Lock);
8495685043 }
8495785044
85045+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock);
8495885046 g_Suspender.Resume();
8495985047 return true;
8496085048 }
8496185049 }
8496285050
85051+ ReleaseSRWLockExclusive(&g_MemoryHookRecordsLock);
85052+
8496385053 g_Suspender.Resume();
8496485054 return false;
8496585055 }
8496685056
85057+
8496785058 // ----------------------------------------------------------------
8496885059 // Interrupt Hook
8496985060 // ----------------------------------------------------------------
0 commit comments