27
27
28
28
29
29
#define THREAD_TIMEOUT 100 // ms
30
- // Global object shared between the 2 threads.
31
- PUNICODE_STRING globalFileName = NULL ;
30
+ #define STATUS_UNSUCCESSFUL ((DWORD)0xC0000001L)
31
+
32
+ typedef struct
33
+ {
34
+ NTSTATUS status ;
35
+ HANDLE hFile ;
36
+ PUNICODE_STRING FileName ;
37
+ ULONG Length ;
38
+ } psutil_query_thread ;
32
39
33
40
34
41
static int
@@ -80,129 +87,105 @@ psutil_enum_handles(PSYSTEM_HANDLE_INFORMATION_EX *handles) {
80
87
return 0 ;
81
88
}
82
89
83
-
84
- static int
90
+ static DWORD
85
91
psutil_get_filename (LPVOID lpvParam ) {
86
- HANDLE hFile = * ((HANDLE * )lpvParam );
87
- NTSTATUS status ;
88
- ULONG bufferSize ;
89
- ULONG attempts = 8 ;
90
-
91
- bufferSize = 0x200 ;
92
- globalFileName = MALLOC_ZERO (bufferSize );
93
- if (globalFileName == NULL ) {
94
- PyErr_NoMemory ();
95
- goto error ;
96
- }
92
+ psutil_query_thread * context = lpvParam ;
93
+
94
+ context -> status = NtQueryObject (
95
+ context -> hFile ,
96
+ ObjectNameInformation ,
97
+ context -> FileName ,
98
+ context -> Length ,
99
+ & context -> Length );
100
+ return 0 ;
101
+ }
97
102
98
103
99
- // Note: also this is supposed to hang, hence why we do it in here.
100
- if (GetFileType (hFile ) != FILE_TYPE_DISK ) {
101
- SetLastError (0 );
102
- globalFileName -> Length = 0 ;
103
- return 0 ;
104
+ static PUNICODE_STRING
105
+ psutil_threaded_get_filename (HANDLE hFile ) {
106
+ DWORD dwWait ;
107
+ HANDLE hThread ;
108
+ DWORD result = 0 ;
109
+ ULONG attempts = 8 ;
110
+ psutil_query_thread threadContext = {
111
+ .status = STATUS_UNSUCCESSFUL ,
112
+ .hFile = hFile ,
113
+ .FileName = NULL ,
114
+ .Length = 0x200 ,
115
+ };
116
+
117
+ threadContext .FileName = MALLOC_ZERO (threadContext .Length );
118
+ if (threadContext .FileName == NULL ) {
119
+ PyErr_NoMemory ();
120
+ return NULL ;
104
121
}
105
122
106
123
// A loop is needed because the I/O subsystem likes to give us the
107
124
// wrong return lengths...
108
125
do {
109
- status = NtQueryObject (
110
- hFile ,
111
- ObjectNameInformation ,
112
- globalFileName ,
113
- bufferSize ,
114
- & bufferSize
115
- );
116
- if (status == STATUS_BUFFER_OVERFLOW ||
117
- status == STATUS_INFO_LENGTH_MISMATCH ||
118
- status == STATUS_BUFFER_TOO_SMALL )
126
+ hThread = CreateThread (
127
+ NULL , 0 , (LPTHREAD_START_ROUTINE )psutil_get_filename ,
128
+ & threadContext , 0 , NULL );
129
+ if (hThread == NULL ) {
130
+ PyErr_SetFromOSErrnoWithSyscall ("CreateThread" );
131
+ FREE (threadContext .FileName );
132
+ return NULL ;
133
+ }
134
+
135
+ // Wait for the worker thread to finish.
136
+ dwWait = WaitForSingleObject (hThread , THREAD_TIMEOUT );
137
+
138
+ // If the thread hangs, kill it and cleanup.
139
+ if (dwWait == WAIT_TIMEOUT ) {
140
+ psutil_debug (
141
+ "get handle name thread timed out after %i ms" , THREAD_TIMEOUT );
142
+ if (TerminateThread (hThread , 0 ) == 0 ) {
143
+ PyErr_SetFromOSErrnoWithSyscall ("TerminateThread" );
144
+ result = 1 ;
145
+ }
146
+ } else if (dwWait == WAIT_FAILED ) {
147
+ psutil_debug ("WaitForSingleObject -> WAIT_FAILED" );
148
+ result = 1 ;
149
+ if (TerminateThread (hThread , 0 ) == 0 ) {
150
+ PyErr_SetFromOSErrnoWithSyscall (
151
+ "WaitForSingleObject -> WAIT_FAILED -> TerminateThread" );
152
+ } else {
153
+ PyErr_SetFromOSErrnoWithSyscall ("WaitForSingleObject" );
154
+ }
155
+ } else if (GetExitCodeThread (hThread , & result ) == 0 ) {
156
+ result = 1 ;
157
+ PyErr_SetFromOSErrnoWithSyscall ("GetExitCodeThread" );
158
+ } else if (threadContext .status == STATUS_BUFFER_OVERFLOW ||
159
+ threadContext .status == STATUS_INFO_LENGTH_MISMATCH ||
160
+ threadContext .status == STATUS_BUFFER_TOO_SMALL )
119
161
{
120
- FREE (globalFileName );
121
- globalFileName = MALLOC_ZERO (bufferSize );
122
- if (globalFileName == NULL ) {
162
+ FREE (threadContext . FileName );
163
+ threadContext . FileName = MALLOC_ZERO (threadContext . Length );
164
+ if (threadContext . FileName == NULL ) {
123
165
PyErr_NoMemory ();
124
- goto error ;
166
+ CloseHandle (hThread );
167
+ return NULL ;
125
168
}
126
- }
127
- else {
169
+ } else {
170
+ CloseHandle ( hThread );
128
171
break ;
129
172
}
130
- } while (-- attempts );
131
-
132
- if (! NT_SUCCESS (status )) {
133
- psutil_SetFromNTStatusErr (status , "NtQuerySystemInformation" );
134
- FREE (globalFileName );
135
- globalFileName = NULL ;
136
- return 1 ;
137
- }
138
-
139
- return 0 ;
140
-
141
- error :
142
- if (globalFileName != NULL ) {
143
- FREE (globalFileName );
144
- globalFileName = NULL ;
145
- }
146
- return 1 ;
147
- }
148
-
149
-
150
- static DWORD
151
- psutil_threaded_get_filename (HANDLE hFile ) {
152
- DWORD dwWait ;
153
- HANDLE hThread ;
154
- DWORD threadRetValue ;
155
-
156
- hThread = CreateThread (
157
- NULL , 0 , (LPTHREAD_START_ROUTINE )psutil_get_filename , & hFile , 0 , NULL );
158
- if (hThread == NULL ) {
159
- PyErr_SetFromOSErrnoWithSyscall ("CreateThread" );
160
- return 1 ;
161
- }
173
+ CloseHandle (hThread );
162
174
163
- // Wait for the worker thread to finish.
164
- dwWait = WaitForSingleObject (hThread , THREAD_TIMEOUT );
175
+ } while (-- attempts && !result );
165
176
166
- // If the thread hangs, kill it and cleanup.
167
- if (dwWait == WAIT_TIMEOUT ) {
168
- psutil_debug (
169
- "get handle name thread timed out after %i ms" , THREAD_TIMEOUT );
170
- if (TerminateThread (hThread , 0 ) == 0 ) {
171
- PyErr_SetFromOSErrnoWithSyscall ("TerminateThread" );
172
- CloseHandle (hThread );
173
- return 1 ;
174
- }
175
- CloseHandle (hThread );
176
- return 0 ;
177
+ if (result ) {
178
+ FREE (threadContext .FileName );
179
+ return NULL ;
177
180
}
178
181
179
- if (dwWait == WAIT_FAILED ) {
180
- psutil_debug ("WaitForSingleObject -> WAIT_FAILED" );
181
- if (TerminateThread (hThread , 0 ) == 0 ) {
182
- PyErr_SetFromOSErrnoWithSyscall (
183
- "WaitForSingleObject -> WAIT_FAILED -> TerminateThread" );
184
- CloseHandle (hThread );
185
- return 1 ;
186
- }
187
- PyErr_SetFromOSErrnoWithSyscall ("WaitForSingleObject" );
188
- CloseHandle (hThread );
189
- return 1 ;
182
+ if (! NT_SUCCESS (threadContext .status )) {
183
+ psutil_SetFromNTStatusErr (threadContext .status , "NtQuerySystemInformation" );
184
+ FREE (threadContext .FileName );
185
+ return NULL ;
190
186
}
191
187
192
- if (GetExitCodeThread (hThread , & threadRetValue ) == 0 ) {
193
- if (TerminateThread (hThread , 0 ) == 0 ) {
194
- PyErr_SetFromOSErrnoWithSyscall (
195
- "GetExitCodeThread (failed) -> TerminateThread" );
196
- CloseHandle (hThread );
197
- return 1 ;
198
- }
199
-
200
- CloseHandle (hThread );
201
- PyErr_SetFromOSErrnoWithSyscall ("GetExitCodeThread" );
202
- return 1 ;
203
- }
204
- CloseHandle (hThread );
205
- return threadRetValue ;
188
+ return threadContext .FileName ;
206
189
}
207
190
208
191
@@ -214,15 +197,12 @@ psutil_get_open_files(DWORD dwPid, HANDLE hProcess) {
214
197
ULONG i = 0 ;
215
198
BOOLEAN errorOccurred = FALSE;
216
199
PyObject * py_path = NULL ;
217
- PyObject * py_retlist = PyList_New (0 );;
200
+ PyObject * py_retlist = PyList_New (0 );
201
+ PUNICODE_STRING fileName = NULL ;
218
202
219
203
if (!py_retlist )
220
204
return NULL ;
221
205
222
- // Due to the use of global variables, ensure only 1 call
223
- // to psutil_get_open_files() is running.
224
- EnterCriticalSection (& PSUTIL_CRITICAL_SECTION );
225
-
226
206
if (psutil_enum_handles (& handlesList ) != 0 )
227
207
goto error ;
228
208
@@ -243,13 +223,20 @@ psutil_get_open_files(DWORD dwPid, HANDLE hProcess) {
243
223
continue ;
244
224
}
245
225
246
- // This will set *globalFileName* global variable.
247
- if (psutil_threaded_get_filename (hFile ) != 0 )
226
+ if (GetFileType (hFile ) != FILE_TYPE_DISK ) {
227
+ SetLastError (0 );
228
+ CloseHandle (hFile );
229
+ hFile = NULL ;
230
+ continue ;
231
+ }
232
+
233
+ fileName = psutil_threaded_get_filename (hFile );
234
+ if (fileName == NULL )
248
235
goto error ;
249
236
250
- if ((globalFileName != NULL ) && (globalFileName -> Length > 0 )) {
251
- py_path = PyUnicode_FromWideChar (globalFileName -> Buffer ,
252
- wcslen (globalFileName -> Buffer ));
237
+ if ((fileName != NULL ) && (fileName -> Length > 0 )) {
238
+ py_path = PyUnicode_FromWideChar (fileName -> Buffer ,
239
+ wcslen (fileName -> Buffer ));
253
240
if (! py_path )
254
241
goto error ;
255
242
if (PyList_Append (py_retlist , py_path ))
@@ -258,9 +245,9 @@ psutil_get_open_files(DWORD dwPid, HANDLE hProcess) {
258
245
}
259
246
260
247
// Loop cleanup section.
261
- if (globalFileName != NULL ) {
262
- FREE (globalFileName );
263
- globalFileName = NULL ;
248
+ if (fileName != NULL ) {
249
+ FREE (fileName );
250
+ fileName = NULL ;
264
251
}
265
252
CloseHandle (hFile );
266
253
hFile = NULL ;
@@ -276,16 +263,13 @@ psutil_get_open_files(DWORD dwPid, HANDLE hProcess) {
276
263
exit :
277
264
if (hFile != NULL )
278
265
CloseHandle (hFile );
279
- if (globalFileName != NULL ) {
280
- FREE (globalFileName );
281
- globalFileName = NULL ;
282
- }
266
+ if (fileName != NULL )
267
+ FREE (fileName );
283
268
if (py_path != NULL )
284
269
Py_DECREF (py_path );
285
270
if (handlesList != NULL )
286
271
FREE (handlesList );
287
272
288
- LeaveCriticalSection (& PSUTIL_CRITICAL_SECTION );
289
273
if (errorOccurred == TRUE)
290
274
return NULL ;
291
275
return py_retlist ;
0 commit comments