Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/psutil/psutil/arch/mswindows/process_info.c

Issue 8159001: Update third_party/psutil and fix the licence issue with it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove the suppression and unnecessary files. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * $Id: process_info.c 778 2010-11-08 19:59:08Z g.rodola $ 2 * $Id: process_info.c 1142 2011-10-05 18:45:49Z g.rodola $
3 *
4 * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
3 * 7 *
4 * Helper functions related to fetching process information. Used by 8 * Helper functions related to fetching process information. Used by
5 * _psutil_mswindows module methods. 9 * _psutil_mswindows module methods.
6 */ 10 */
7 11
8 #include <Python.h> 12 #include <Python.h>
9 #include <windows.h> 13 #include <windows.h>
10 #include <Psapi.h> 14 #include <Psapi.h>
11 #include <tlhelp32.h> 15 #include <tlhelp32.h>
12 16
13 #include "security.h" 17 #include "security.h"
14 #include "process_info.h" 18 #include "process_info.h"
15 19 #include "ntextapi.h"
16 20
17 /* 21 /*
18 * NtQueryInformationProcess code taken from 22 * NtQueryInformationProcess code taken from
19 * http://wj32.wordpress.com/2009/01/24/howto-get-the-command-line-of-processes/ 23 * http://wj32.wordpress.com/2009/01/24/howto-get-the-command-line-of-processes/
20 * typedefs needed to compile against ntdll functions not exposted in the API 24 * typedefs needed to compile against ntdll functions not exposted in the API
21 */ 25 */
22 typedef LONG NTSTATUS; 26 typedef LONG NTSTATUS;
23 27
24 typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)( 28 typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)(
25 HANDLE ProcessHandle, 29 HANDLE ProcessHandle,
26 DWORD ProcessInformationClass, 30 DWORD ProcessInformationClass,
27 PVOID ProcessInformation, 31 PVOID ProcessInformation,
28 DWORD ProcessInformationLength, 32 DWORD ProcessInformationLength,
29 PDWORD ReturnLength 33 PDWORD ReturnLength
30 ); 34 );
31 35
32 typedef struct _UNICODE_STRING
33 {
34 USHORT Length;
35 USHORT MaximumLength;
36 PWSTR Buffer;
37 } UNICODE_STRING, *PUNICODE_STRING;
38
39 typedef struct _PROCESS_BASIC_INFORMATION 36 typedef struct _PROCESS_BASIC_INFORMATION
40 { 37 {
41 PVOID Reserved1; 38 PVOID Reserved1;
42 PVOID PebBaseAddress; 39 PVOID PebBaseAddress;
43 PVOID Reserved2[2]; 40 PVOID Reserved2[2];
44 ULONG_PTR UniqueProcessId; 41 ULONG_PTR UniqueProcessId;
45 PVOID Reserved3; 42 PVOID Reserved3;
46 } PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; 43 } PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
47 44
48 45
49 /* 46 /*
50 * Set OSError(errno=ESRCH, strerror="No such process") Python exception.
51 */
52 PyObject *
53 NoSuchProcess(void) {
54 PyObject *exc;
55 char *msg = strerror(ESRCH);
56 exc = PyObject_CallFunction(PyExc_OSError, "(is)", ESRCH, msg);
57 PyErr_SetObject(PyExc_OSError, exc);
58 Py_XDECREF(exc);
59 return NULL;
60 }
61
62 /*
63 * Set OSError(errno=EACCES, strerror="No such process") Python exception.
64 */
65 PyObject *
66 AccessDenied(void) {
67 PyObject *exc;
68 char *msg = strerror(EACCES);
69 exc = PyObject_CallFunction(PyExc_OSError, "(is)", EACCES, msg);
70 PyErr_SetObject(PyExc_OSError, exc);
71 Py_XDECREF(exc);
72 return NULL;
73 }
74
75
76 /*
77 * A wrapper around OpenProcess setting NSP exception if process 47 * A wrapper around OpenProcess setting NSP exception if process
78 * no longer exists. 48 * no longer exists.
79 * "pid" is the process pid, "dwDesiredAccess" is the first argument 49 * "pid" is the process pid, "dwDesiredAccess" is the first argument
80 * exptected by OpenProcess. 50 * exptected by OpenProcess.
81 * Return a process handle or NULL. 51 * Return a process handle or NULL.
82 */ 52 */
83 HANDLE 53 HANDLE
84 handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess) 54 handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess)
85 { 55 {
86 HANDLE hProcess; 56 HANDLE hProcess;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 } while(enumReturnSz == procArraySz * sizeof(DWORD)); 140 } while(enumReturnSz == procArraySz * sizeof(DWORD));
171 141
172 /* The number of elements is the returned size / size of each element */ 142 /* The number of elements is the returned size / size of each element */
173 *numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD); 143 *numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD);
174 144
175 return procArray; 145 return procArray;
176 } 146 }
177 147
178 148
179 int 149 int
180 is_system_proc(DWORD pid) {
181 HANDLE hProcess;
182
183 // Special case for PID 0 System Idle Process
184 // and PID 4 (SYSTEM)
185 if ((pid == 0) || (pid == 4)) {
186 return 1;
187 }
188 if (pid < 0) {
189 return 0;
190 }
191
192 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, p id);
193 if (NULL == hProcess) {
194 // invalid parameter is no such process
195 if (GetLastError() == ERROR_INVALID_PARAMETER) {
196 return 0;
197 }
198
199 // access denied obviously means there's a process to deny access to...
200 if (GetLastError() == ERROR_ACCESS_DENIED) {
201 return 1;
202 }
203
204 PyErr_SetFromWindowsErr(0);
205 return -1;
206 }
207
208 return HasSystemPrivilege(hProcess);
209 }
210
211
212 int
213 pid_is_running(DWORD pid) 150 pid_is_running(DWORD pid)
214 { 151 {
215 HANDLE hProcess; 152 HANDLE hProcess;
216 DWORD exitCode; 153 DWORD exitCode;
217 154
218 // Special case for PID 0 System Idle Process 155 // Special case for PID 0 System Idle Process
219 if (pid == 0) { 156 if (pid == 0) {
220 return 1; 157 return 1;
221 } 158 }
222 159
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 200
264 int 201 int
265 pid_in_proclist(DWORD pid) 202 pid_in_proclist(DWORD pid)
266 { 203 {
267 DWORD *proclist = NULL; 204 DWORD *proclist = NULL;
268 DWORD numberOfReturnedPIDs; 205 DWORD numberOfReturnedPIDs;
269 DWORD i; 206 DWORD i;
270 207
271 proclist = get_pids(&numberOfReturnedPIDs); 208 proclist = get_pids(&numberOfReturnedPIDs);
272 if (NULL == proclist) { 209 if (NULL == proclist) {
273 return NULL; 210 return -1;
274 } 211 }
275 212
276 for (i = 0; i < numberOfReturnedPIDs; i++) { 213 for (i = 0; i < numberOfReturnedPIDs; i++) {
277 if (pid == proclist[i]) { 214 if (pid == proclist[i]) {
278 free(proclist); 215 free(proclist);
279 return 1; 216 return 1;
280 } 217 }
281 } 218 }
282 219
283 free(proclist); 220 free(proclist);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 PyObject* 270 PyObject*
334 get_ppid(long pid) 271 get_ppid(long pid)
335 { 272 {
336 HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 273 HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
337 PROCESSENTRY32 pe = { 0 }; 274 PROCESSENTRY32 pe = { 0 };
338 pe.dwSize = sizeof(PROCESSENTRY32); 275 pe.dwSize = sizeof(PROCESSENTRY32);
339 276
340 if( Process32First(h, &pe)) { 277 if( Process32First(h, &pe)) {
341 do { 278 do {
342 if (pe.th32ProcessID == pid) { 279 if (pe.th32ProcessID == pid) {
343 //printf("PID: %i; PPID: %i\n", pid, pe.th32ParentProcessID); 280 ////printf("PID: %i; PPID: %i\n", pid, pe.th32ParentProcessID);
344 CloseHandle(h); 281 CloseHandle(h);
345 return Py_BuildValue("I", pe.th32ParentProcessID); 282 return Py_BuildValue("I", pe.th32ParentProcessID);
346 } 283 }
347 } while(Process32Next(h, &pe)); 284 } while(Process32Next(h, &pe));
348 285
349 // the process was never found, set NoSuchProcess exception 286 // the process was never found, set NoSuchProcess exception
350 NoSuchProcess(); 287 NoSuchProcess();
351 CloseHandle(h); 288 CloseHandle(h);
352 return NULL; 289 return NULL;
353 } 290 }
(...skipping 15 matching lines...) Expand all
369 LPWSTR *szArglist; 306 LPWSTR *szArglist;
370 HANDLE hProcess; 307 HANDLE hProcess;
371 PVOID pebAddress; 308 PVOID pebAddress;
372 PVOID rtlUserProcParamsAddress; 309 PVOID rtlUserProcParamsAddress;
373 UNICODE_STRING commandLine; 310 UNICODE_STRING commandLine;
374 WCHAR *commandLineContents; 311 WCHAR *commandLineContents;
375 PyObject *arg = NULL; 312 PyObject *arg = NULL;
376 PyObject *arg_from_wchar = NULL; 313 PyObject *arg_from_wchar = NULL;
377 PyObject *argList = NULL; 314 PyObject *argList = NULL;
378 315
379
380 hProcess = handle_from_pid(pid); 316 hProcess = handle_from_pid(pid);
381 if(hProcess == NULL) { 317 if(hProcess == NULL) {
382 return NULL; 318 return NULL;
383 } 319 }
384 320
385 pebAddress = GetPebAddress(hProcess); 321 pebAddress = GetPebAddress(hProcess);
386 322
387 /* get the address of ProcessParameters */ 323 /* get the address of ProcessParameters */
388 #ifdef _WIN64 324 #ifdef _WIN64
389 if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 32, 325 if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 32,
390 &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) 326 &rtlUserProcParamsAddress, sizeof(PVOID), NULL))
391 #else 327 #else
392 if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 0x10, 328 if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 0x10,
393 &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) 329 &rtlUserProcParamsAddress, sizeof(PVOID), NULL))
394 #endif 330 #endif
395 { 331 {
396 //printf("Could not read the address of ProcessParameters!\n"); 332 ////printf("Could not read the address of ProcessParameters!\n");
397 PyErr_SetFromWindowsErr(0); 333 PyErr_SetFromWindowsErr(0);
398 CloseHandle(hProcess); 334 CloseHandle(hProcess);
399 return NULL; 335 return NULL;
400 } 336 }
401 337
402 /* read the CommandLine UNICODE_STRING structure */ 338 /* read the CommandLine UNICODE_STRING structure */
403 #ifdef _WIN64 339 #ifdef _WIN64
404 if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 112, 340 if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 112,
405 &commandLine, sizeof(commandLine), NULL)) 341 &commandLine, sizeof(commandLine), NULL))
406 #else 342 #else
407 if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 0x40, 343 if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 0x40,
408 &commandLine, sizeof(commandLine), NULL)) 344 &commandLine, sizeof(commandLine), NULL))
409 #endif 345 #endif
410 { 346 {
411 //printf("Could not read CommandLine!\n"); 347 ////printf("Could not read CommandLine!\n");
348 CloseHandle(hProcess);
412 PyErr_SetFromWindowsErr(0); 349 PyErr_SetFromWindowsErr(0);
413 CloseHandle(hProcess);
414 return NULL; 350 return NULL;
415 } 351 }
416 352
417 353
418 /* allocate memory to hold the command line */ 354 /* allocate memory to hold the command line */
419 commandLineContents = (WCHAR *)malloc(commandLine.Length+1); 355 commandLineContents = (WCHAR *)malloc(commandLine.Length+1);
420 356
421 /* read the command line */ 357 /* read the command line */
422 if (!ReadProcessMemory(hProcess, commandLine.Buffer, 358 if (!ReadProcessMemory(hProcess, commandLine.Buffer,
423 commandLineContents, commandLine.Length, NULL)) 359 commandLineContents, commandLine.Length, NULL))
424 { 360 {
425 //printf("Could not read the command line string!\n"); 361 ////printf("Could not read the command line string!\n");
362 CloseHandle(hProcess);
426 PyErr_SetFromWindowsErr(0); 363 PyErr_SetFromWindowsErr(0);
427 CloseHandle(hProcess);
428 free(commandLineContents); 364 free(commandLineContents);
429 return NULL; 365 return NULL;
430 } 366 }
431 367
432 /* print the commandline */ 368 /* print the commandline */
433 //printf("%.*S\n", commandLine.Length / 2, commandLineContents); 369 ////printf("%.*S\n", commandLine.Length / 2, commandLineContents);
434 370
435 // null-terminate the string to prevent wcslen from returning incorrect leng th 371 // null-terminate the string to prevent wcslen from returning incorrect leng th
436 // the length specifier is in characters, but commandLine.Length is in bytes 372 // the length specifier is in characters, but commandLine.Length is in bytes
437 commandLineContents[(commandLine.Length/sizeof(WCHAR))] = '\0'; 373 commandLineContents[(commandLine.Length/sizeof(WCHAR))] = '\0';
438 374
439 // attemempt tp parse the command line using Win32 API, fall back on string 375 // attemempt tp parse the command line using Win32 API, fall back on string
440 // cmdline version otherwise 376 // cmdline version otherwise
441 szArglist = CommandLineToArgvW(commandLineContents, &nArgs); 377 szArglist = CommandLineToArgvW(commandLineContents, &nArgs);
442 if (NULL == szArglist) { 378 if (NULL == szArglist) {
443 // failed to parse arglist 379 // failed to parse arglist
444 // encode as a UTF8 Python string object from WCHAR string 380 // encode as a UTF8 Python string object from WCHAR string
445 arg_from_wchar = PyUnicode_FromWideChar(commandLineContents, 381 arg_from_wchar = PyUnicode_FromWideChar(commandLineContents,
446 commandLine.Length / 2); 382 commandLine.Length / 2);
447 #if PY_MAJOR_VERSION >= 3 383 #if PY_MAJOR_VERSION >= 3
448 argList = Py_BuildValue("N", PyUnicode_AsUTF8String(arg_from_wchar)) ; 384 argList = Py_BuildValue("N", PyUnicode_AsUTF8String(arg_from_wchar)) ;
449 #else 385 #else
450 argList = Py_BuildValue("N", PyUnicode_FromObject(arg_from_wchar)); 386 argList = Py_BuildValue("N", PyUnicode_FromObject(arg_from_wchar));
451 #endif 387 #endif
452 } 388 }
453 else { 389 else {
454 // arglist parsed as array of UNICODE_STRING, so convert each to Python 390 // arglist parsed as array of UNICODE_STRING, so convert each to Python
455 // string object and add to arg list 391 // string object and add to arg list
456 argList = Py_BuildValue("[]"); 392 argList = Py_BuildValue("[]");
457 for(i=0; i<nArgs; i++) { 393 for(i=0; i<nArgs; i++) {
458 //printf("%d: %.*S (%d characters)\n", i, wcslen(szArglist[i]), 394 ////printf("%d: %.*S (%d characters)\n", i, wcslen(szArglist[i]),
459 // szArglist[i], wcslen(szArglist[i])); 395 // szArglist[i], wcslen(szArglist[i]));
460 arg_from_wchar = PyUnicode_FromWideChar(szArglist[i], 396 arg_from_wchar = PyUnicode_FromWideChar(szArglist[i],
461 wcslen(szArglist[i]) 397 wcslen(szArglist[i])
462 ); 398 );
463 #if PY_MAJOR_VERSION >= 3 399 #if PY_MAJOR_VERSION >= 3
464 arg = PyUnicode_FromObject(arg_from_wchar); 400 arg = PyUnicode_FromObject(arg_from_wchar);
465 #else 401 #else
466 arg = PyUnicode_AsUTF8String(arg_from_wchar); 402 arg = PyUnicode_AsUTF8String(arg_from_wchar);
467 #endif 403 #endif
468 Py_XDECREF(arg_from_wchar); 404 Py_XDECREF(arg_from_wchar);
469 PyList_Append(argList, arg); 405 PyList_Append(argList, arg);
470 Py_XDECREF(arg); 406 Py_XDECREF(arg);
471 } 407 }
472 } 408 }
473 409
474 LocalFree(szArglist); 410 LocalFree(szArglist);
475 free(commandLineContents); 411 free(commandLineContents);
476 CloseHandle(hProcess); 412 CloseHandle(hProcess);
477 return argList; 413 return argList;
478 } 414 }
479 415
416
417 #define PH_FIRST_PROCESS(Processes) ((PSYSTEM_PROCESS_INFORMATION)(Processes))
418
419 #define PH_NEXT_PROCESS(Process) ( \
420 ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset ? \
421 (PSYSTEM_PROCESS_INFORMATION)((PCHAR)(Process) + \
422 ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset) : \
423 NULL \
424 )
425
426 const STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
427 const STATUS_BUFFER_TOO_SMALL = 0xC0000023L;
428
429 /*
430 * Given a process PID and a PSYSTEM_PROCESS_INFORMATION structure
431 * fills the structure with process information.
432 * On success return 1, else 0 with Python exception already set.
433 */
434 int
435 get_process_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, PVOID *retB uffer)
436 {
437 static ULONG initialBufferSize = 0x4000;
438 NTSTATUS status;
439 PVOID buffer;
440 ULONG bufferSize;
441 PSYSTEM_PROCESS_INFORMATION process;
442
443 // get NtQuerySystemInformation
444 typedef DWORD (_stdcall *NTQSI_PROC) (int, PVOID, ULONG, PULONG);
445 NTQSI_PROC NtQuerySystemInformation;
446 HINSTANCE hNtDll;
447 hNtDll = LoadLibrary(TEXT("ntdll.dll"));
448 NtQuerySystemInformation = (NTQSI_PROC)GetProcAddress(
449 hNtDll, "NtQuerySystemInformation");
450
451 bufferSize = initialBufferSize;
452 buffer = malloc(bufferSize);
453
454 while (TRUE) {
455 status = NtQuerySystemInformation(SystemProcessInformation, buffer,
456 bufferSize, &bufferSize);
457
458 if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INFO_LENGTH_MI SMATCH)
459 {
460 free(buffer);
461 buffer = malloc(bufferSize);
462 }
463 else {
464 break;
465 }
466 }
467
468 if (status != 0) {
469 PyErr_Format(PyExc_RuntimeError, "NtQuerySystemInformation() failed");
470 return 0;
471 }
472
473 if (bufferSize <= 0x20000) {
474 initialBufferSize = bufferSize;
475 }
476
477 process = PH_FIRST_PROCESS(buffer);
478 do {
479 if (process->UniqueProcessId == (HANDLE)pid) {
480 *retProcess = process;
481 *retBuffer = buffer;
482 return 1;
483 }
484 } while ( (process = PH_NEXT_PROCESS(process)) );
485
486 NoSuchProcess();
487 return 0;
488 }
489
490
OLDNEW
« no previous file with comments | « third_party/psutil/psutil/arch/mswindows/process_info.h ('k') | third_party/psutil/psutil/arch/mswindows/security.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698