@@ -169,7 +169,8 @@ SlimDetoursTransactionCommit(VOID)
169
169
o = s_pPendingOperations ;
170
170
do
171
171
{
172
- if (o -> dwOperation == DETOUR_OPERATION_REMOVE )
172
+ if (o -> dwOperation == DETOUR_OPERATION_REMOVE ||
173
+ o -> dwOperation == DETOUR_OPERATION_REMOVE_AND_FREE )
173
174
{
174
175
// Check if the jmps still points where we expect, otherwise someone might have hooked us.
175
176
BOOL hookIsStillThere =
@@ -186,12 +187,14 @@ SlimDetoursTransactionCommit(VOID)
186
187
NtFlushInstructionCache (NtCurrentProcess (), o -> pbTarget , o -> pTrampoline -> cbRestore );
187
188
} else
188
189
{
189
- // Don't remove in this case, put in bypass mode and leak trampoline .
190
+ // Don't remove and leak trampoline in this case .
190
191
o -> dwOperation = DETOUR_OPERATION_NONE ;
191
- o -> pTrampoline -> pbDetour = o -> pTrampoline -> rbCode ;
192
192
DETOUR_TRACE ("detours: Leaked hook on pbTarget=%p due to external hooking\n" , o -> pbTarget );
193
193
}
194
194
195
+ // Put hook in bypass mode.
196
+ o -> pTrampoline -> pbDetour = o -> pTrampoline -> rbCode ;
197
+
195
198
* o -> ppbPointer = o -> pbTarget ;
196
199
} else if (o -> dwOperation == DETOUR_OPERATION_ADD )
197
200
{
@@ -260,7 +263,7 @@ SlimDetoursTransactionCommit(VOID)
260
263
pMem = o -> pbTarget ;
261
264
sMem = o -> pTrampoline -> cbRestore ;
262
265
NtProtectVirtualMemory (NtCurrentProcess (), & pMem , & sMem , o -> dwPerm , & dwOld );
263
- if (o -> dwOperation == DETOUR_OPERATION_REMOVE )
266
+ if (o -> dwOperation == DETOUR_OPERATION_REMOVE_AND_FREE )
264
267
{
265
268
detour_free_trampoline (o -> pTrampoline );
266
269
o -> pTrampoline = NULL ;
@@ -496,9 +499,10 @@ SlimDetoursAttach(
496
499
497
500
HRESULT
498
501
NTAPI
499
- SlimDetoursDetach (
502
+ SlimDetoursDetachEx (
500
503
_Inout_ PVOID * ppPointer ,
501
- _In_ PVOID pDetour )
504
+ _In_ PVOID pDetour ,
505
+ _In_ PCDETOUR_DETACH_OPTIONS pOptions )
502
506
{
503
507
NTSTATUS Status ;
504
508
PVOID pMem ;
@@ -546,7 +550,9 @@ SlimDetoursDetach(
546
550
goto fail ;
547
551
}
548
552
549
- o -> dwOperation = DETOUR_OPERATION_REMOVE ;
553
+ o -> dwOperation = pOptions -> fFreeTrampoline
554
+ ? DETOUR_OPERATION_REMOVE_AND_FREE
555
+ : DETOUR_OPERATION_REMOVE ;
550
556
o -> ppbPointer = (PBYTE * )ppPointer ;
551
557
o -> pTrampoline = pTrampoline ;
552
558
o -> pbTarget = pbTarget ;
@@ -557,6 +563,41 @@ SlimDetoursDetach(
557
563
return HRESULT_FROM_NT (STATUS_SUCCESS );
558
564
}
559
565
566
+ HRESULT
567
+ NTAPI
568
+ SlimDetoursFreeTrampoline (
569
+ _In_ PVOID pTrampoline )
570
+ {
571
+ NTSTATUS Status ;
572
+
573
+ // Make sure only one thread can start a transaction.
574
+ if (_InterlockedCompareExchange (& s_nPendingThreadId , NtCurrentThreadId (), 0 ) != 0 )
575
+ {
576
+ return HRESULT_FROM_NT (STATUS_TRANSACTIONAL_CONFLICT );
577
+ }
578
+
579
+ // Make sure the trampoline pages are writable.
580
+ Status = detour_writable_trampoline_regions ();
581
+ if (!NT_SUCCESS (Status ))
582
+ {
583
+ goto fail ;
584
+ }
585
+
586
+ detour_free_trampoline ((PDETOUR_TRAMPOLINE )pTrampoline );
587
+ detour_free_trampoline_region_if_unused ((PDETOUR_TRAMPOLINE )pTrampoline );
588
+
589
+ detour_runnable_trampoline_regions ();
590
+
591
+ fail :
592
+ #ifdef _MSC_VER
593
+ #pragma warning(disable: __WARNING_INTERLOCKED_ACCESS)
594
+ #endif
595
+ s_nPendingThreadId = 0 ;
596
+ #ifdef _MSC_VER
597
+ #pragma warning(default: __WARNING_INTERLOCKED_ACCESS)
598
+ #endif
599
+ }
600
+
560
601
#if (NTDDI_VERSION >= NTDDI_WIN6 )
561
602
562
603
static
0 commit comments