@@ -177,7 +177,8 @@ SlimDetoursTransactionCommit(VOID)
177
177
o = s_pPendingOperations ;
178
178
do
179
179
{
180
- if (o -> dwOperation == DETOUR_OPERATION_REMOVE )
180
+ if (o -> dwOperation == DETOUR_OPERATION_REMOVE ||
181
+ o -> dwOperation == DETOUR_OPERATION_REMOVE_AND_FREE )
181
182
{
182
183
// Check if the jmps still points where we expect, otherwise someone might have hooked us.
183
184
BOOL hookIsStillThere =
@@ -194,12 +195,14 @@ SlimDetoursTransactionCommit(VOID)
194
195
NtFlushInstructionCache (NtCurrentProcess (), o -> pbTarget , o -> pTrampoline -> cbRestore );
195
196
} else
196
197
{
197
- // Don't remove in this case, put in bypass mode and leak trampoline .
198
+ // Don't remove and leak trampoline in this case .
198
199
o -> dwOperation = DETOUR_OPERATION_NONE ;
199
- o -> pTrampoline -> pbDetour = o -> pTrampoline -> rbCode ;
200
200
DETOUR_TRACE ("detours: Leaked hook on pbTarget=%p due to external hooking\n" , o -> pbTarget );
201
201
}
202
202
203
+ // Put hook in bypass mode.
204
+ o -> pTrampoline -> pbDetour = o -> pTrampoline -> rbCode ;
205
+
203
206
* o -> ppbPointer = o -> pbTarget ;
204
207
} else if (o -> dwOperation == DETOUR_OPERATION_ADD )
205
208
{
@@ -268,7 +271,7 @@ SlimDetoursTransactionCommit(VOID)
268
271
pMem = o -> pbTarget ;
269
272
sMem = o -> pTrampoline -> cbRestore ;
270
273
NtProtectVirtualMemory (NtCurrentProcess (), & pMem , & sMem , o -> dwPerm , & dwOld );
271
- if (o -> dwOperation == DETOUR_OPERATION_REMOVE )
274
+ if (o -> dwOperation == DETOUR_OPERATION_REMOVE_AND_FREE )
272
275
{
273
276
detour_free_trampoline (o -> pTrampoline );
274
277
o -> pTrampoline = NULL ;
@@ -505,9 +508,10 @@ SlimDetoursAttach(
505
508
506
509
HRESULT
507
510
NTAPI
508
- SlimDetoursDetach (
511
+ SlimDetoursDetachEx (
509
512
_Inout_ PVOID * ppPointer ,
510
- _In_ PVOID pDetour )
513
+ _In_ PVOID pDetour ,
514
+ _In_ PCDETOUR_DETACH_OPTIONS pOptions )
511
515
{
512
516
NTSTATUS Status ;
513
517
PVOID pMem ;
@@ -555,7 +559,9 @@ SlimDetoursDetach(
555
559
goto fail ;
556
560
}
557
561
558
- o -> dwOperation = DETOUR_OPERATION_REMOVE ;
562
+ o -> dwOperation = pOptions -> fFreeTrampoline
563
+ ? DETOUR_OPERATION_REMOVE_AND_FREE
564
+ : DETOUR_OPERATION_REMOVE ;
559
565
o -> ppbPointer = (PBYTE * )ppPointer ;
560
566
o -> pTrampoline = pTrampoline ;
561
567
o -> pbTarget = pbTarget ;
@@ -566,6 +572,41 @@ SlimDetoursDetach(
566
572
return HRESULT_FROM_NT (STATUS_SUCCESS );
567
573
}
568
574
575
+ HRESULT
576
+ NTAPI
577
+ SlimDetoursFreeTrampoline (
578
+ _In_ PVOID pTrampoline )
579
+ {
580
+ NTSTATUS Status ;
581
+
582
+ // Make sure only one thread can start a transaction.
583
+ if (_InterlockedCompareExchange (& s_nPendingThreadId , NtCurrentThreadId (), 0 ) != 0 )
584
+ {
585
+ return HRESULT_FROM_NT (STATUS_TRANSACTIONAL_CONFLICT );
586
+ }
587
+
588
+ // Make sure the trampoline pages are writable.
589
+ Status = detour_writable_trampoline_regions ();
590
+ if (!NT_SUCCESS (Status ))
591
+ {
592
+ goto fail ;
593
+ }
594
+
595
+ detour_free_trampoline ((PDETOUR_TRAMPOLINE )pTrampoline );
596
+ detour_free_trampoline_region_if_unused ((PDETOUR_TRAMPOLINE )pTrampoline );
597
+
598
+ detour_runnable_trampoline_regions ();
599
+
600
+ fail :
601
+ #ifdef _MSC_VER
602
+ #pragma warning(disable: __WARNING_INTERLOCKED_ACCESS)
603
+ #endif
604
+ s_nPendingThreadId = 0 ;
605
+ #ifdef _MSC_VER
606
+ #pragma warning(default: __WARNING_INTERLOCKED_ACCESS)
607
+ #endif
608
+ }
609
+
569
610
HRESULT
570
611
NTAPI
571
612
SlimDetoursUninitialize (VOID )
0 commit comments