7
7
#include "SlimDetours.inl"
8
8
9
9
#define THREAD_ACCESS (THREAD_QUERY_LIMITED_INFORMATION | THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_SET_CONTEXT)
10
- #define INITIAL_THREAD_CAPACITY 128
10
+
11
+ static HANDLE s_Handles [32 ];
11
12
12
13
NTSTATUS
13
14
detour_thread_suspend (
14
15
_Outptr_result_maybenull_ PHANDLE * SuspendedHandles ,
15
16
_Out_ PULONG SuspendedHandleCount )
16
17
{
17
18
NTSTATUS Status ;
18
- PHANDLE Buffer = NULL ;
19
- ULONG BufferCapacity = 0 ;
19
+ PHANDLE Buffer = s_Handles ;
20
+ ULONG BufferCapacity = ARRAYSIZE ( s_Handles ) ;
20
21
ULONG SuspendedCount = 0 ;
22
+ BOOL CurrentThreadSkipped = FALSE;
21
23
HANDLE CurrentTID = (HANDLE )(ULONG_PTR )NtCurrentThreadId ();
22
24
BOOL ClosePrevThread = FALSE;
23
25
HANDLE ThreadHandle = NULL ;
24
26
while (TRUE)
25
27
{
26
- HANDLE hNextThread ;
27
- Status = NtGetNextThread (NtCurrentProcess (), ThreadHandle , THREAD_ACCESS , 0 , 0 , & hNextThread );
28
+ HANDLE NextThreadHandle ;
29
+ Status = NtGetNextThread (NtCurrentProcess (), ThreadHandle , THREAD_ACCESS , 0 , 0 , & NextThreadHandle );
28
30
if (ClosePrevThread )
29
31
{
30
32
NtClose (ThreadHandle );
@@ -39,25 +41,29 @@ detour_thread_suspend(
39
41
break ;
40
42
}
41
43
42
- ThreadHandle = hNextThread ;
44
+ ThreadHandle = NextThreadHandle ;
43
45
ClosePrevThread = TRUE;
44
46
45
- THREAD_BASIC_INFORMATION BasicInformation ;
46
- if (!NT_SUCCESS (NtQueryInformationThread (
47
- ThreadHandle ,
48
- ThreadBasicInformation ,
49
- & BasicInformation ,
50
- sizeof (BasicInformation ),
51
- NULL
52
- )))
47
+ if (!CurrentThreadSkipped )
53
48
{
54
- continue ;
55
- }
49
+ THREAD_BASIC_INFORMATION BasicInformation ;
50
+ if (!NT_SUCCESS (NtQueryInformationThread (
51
+ ThreadHandle ,
52
+ ThreadBasicInformation ,
53
+ & BasicInformation ,
54
+ sizeof (BasicInformation ),
55
+ NULL
56
+ )))
57
+ {
58
+ continue ;
59
+ }
56
60
57
- /* Skip the current thread */
58
- if (BasicInformation .ClientId .UniqueThread == CurrentTID )
59
- {
60
- continue ;
61
+ /* Skip the current thread */
62
+ if (BasicInformation .ClientId .UniqueThread == CurrentTID )
63
+ {
64
+ CurrentThreadSkipped = TRUE;
65
+ continue ;
66
+ }
61
67
}
62
68
63
69
if (!NT_SUCCESS (NtSuspendThread (ThreadHandle , NULL )))
@@ -68,18 +74,19 @@ detour_thread_suspend(
68
74
ClosePrevThread = FALSE;
69
75
70
76
Status = STATUS_SUCCESS ;
71
- if (Buffer == NULL )
77
+ if (SuspendedCount >= BufferCapacity )
72
78
{
73
- BufferCapacity = INITIAL_THREAD_CAPACITY ;
74
- Buffer = (PHANDLE )detour_memory_alloc (BufferCapacity * sizeof (HANDLE ));
75
- if (Buffer == NULL )
79
+ BufferCapacity *= 2 ;
80
+
81
+ PHANDLE p ;
82
+ if (Buffer == s_Handles )
76
83
{
77
- Status = STATUS_NO_MEMORY ;
84
+ p = (PHANDLE )detour_memory_alloc (BufferCapacity * sizeof (HANDLE ));
85
+ } else
86
+ {
87
+ p = (PHANDLE )detour_memory_realloc (Buffer , BufferCapacity * sizeof (HANDLE ));
78
88
}
79
- } else if (SuspendedCount >= BufferCapacity )
80
- {
81
- BufferCapacity *= 2 ;
82
- LPHANDLE p = (PHANDLE )detour_memory_realloc (Buffer , BufferCapacity * sizeof (HANDLE ));
89
+
83
90
if (p )
84
91
{
85
92
Buffer = p ;
@@ -106,17 +113,20 @@ detour_thread_suspend(
106
113
Buffer [SuspendedCount ++ ] = ThreadHandle ;
107
114
}
108
115
109
- if (!NT_SUCCESS (Status ) && Buffer != NULL )
116
+ if (!NT_SUCCESS (Status ))
110
117
{
111
118
for (UINT i = 0 ; i < SuspendedCount ; ++ i )
112
119
{
113
120
NtResumeThread (Buffer [i ], NULL );
114
121
NtClose (Buffer [i ]);
115
122
}
116
123
117
- detour_memory_free (Buffer );
118
- Buffer = NULL ;
124
+ if (Buffer != s_Handles )
125
+ {
126
+ detour_memory_free (Buffer );
127
+ }
119
128
129
+ Buffer = NULL ;
120
130
SuspendedCount = 0 ;
121
131
}
122
132
@@ -138,7 +148,11 @@ detour_thread_resume(
138
148
NtResumeThread (SuspendedHandles [i ], NULL );
139
149
NtClose (SuspendedHandles [i ]);
140
150
}
141
- detour_memory_free (SuspendedHandles );
151
+
152
+ if (SuspendedHandles != s_Handles )
153
+ {
154
+ detour_memory_free (SuspendedHandles );
155
+ }
142
156
}
143
157
144
158
NTSTATUS
0 commit comments