| Index: third_party/psutil/psutil/arch/mswindows/process_info.c
|
| diff --git a/third_party/psutil/psutil/arch/mswindows/process_info.c b/third_party/psutil/psutil/arch/mswindows/process_info.c
|
| deleted file mode 100644
|
| index 53b14803d39bf87f9a94179418005ab0a8b4de9c..0000000000000000000000000000000000000000
|
| --- a/third_party/psutil/psutil/arch/mswindows/process_info.c
|
| +++ /dev/null
|
| @@ -1,490 +0,0 @@
|
| -/*
|
| - * $Id: process_info.c 1142 2011-10-05 18:45:49Z g.rodola $
|
| - *
|
| - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
|
| - * Use of this source code is governed by a BSD-style license that can be
|
| - * found in the LICENSE file.
|
| - *
|
| - * Helper functions related to fetching process information. Used by
|
| - * _psutil_mswindows module methods.
|
| - */
|
| -
|
| -#include <Python.h>
|
| -#include <windows.h>
|
| -#include <Psapi.h>
|
| -#include <tlhelp32.h>
|
| -
|
| -#include "security.h"
|
| -#include "process_info.h"
|
| -#include "ntextapi.h"
|
| -
|
| -/*
|
| - * NtQueryInformationProcess code taken from
|
| - * http://wj32.wordpress.com/2009/01/24/howto-get-the-command-line-of-processes/
|
| - * typedefs needed to compile against ntdll functions not exposted in the API
|
| - */
|
| -typedef LONG NTSTATUS;
|
| -
|
| -typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)(
|
| - HANDLE ProcessHandle,
|
| - DWORD ProcessInformationClass,
|
| - PVOID ProcessInformation,
|
| - DWORD ProcessInformationLength,
|
| - PDWORD ReturnLength
|
| - );
|
| -
|
| -typedef struct _PROCESS_BASIC_INFORMATION
|
| -{
|
| - PVOID Reserved1;
|
| - PVOID PebBaseAddress;
|
| - PVOID Reserved2[2];
|
| - ULONG_PTR UniqueProcessId;
|
| - PVOID Reserved3;
|
| -} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
|
| -
|
| -
|
| -/*
|
| - * A wrapper around OpenProcess setting NSP exception if process
|
| - * no longer exists.
|
| - * "pid" is the process pid, "dwDesiredAccess" is the first argument
|
| - * exptected by OpenProcess.
|
| - * Return a process handle or NULL.
|
| - */
|
| -HANDLE
|
| -handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess)
|
| -{
|
| - HANDLE hProcess;
|
| - DWORD processExitCode = 0;
|
| -
|
| - hProcess = OpenProcess(dwDesiredAccess, FALSE, pid);
|
| - if (hProcess == NULL) {
|
| - if (GetLastError() == ERROR_INVALID_PARAMETER) {
|
| - NoSuchProcess();
|
| - }
|
| - else {
|
| - PyErr_SetFromWindowsErr(0);
|
| - }
|
| - return NULL;
|
| - }
|
| -
|
| - /* make sure the process is running */
|
| - GetExitCodeProcess(hProcess, &processExitCode);
|
| - if (processExitCode == 0) {
|
| - NoSuchProcess();
|
| - CloseHandle(hProcess);
|
| - return NULL;
|
| - }
|
| - return hProcess;
|
| -}
|
| -
|
| -
|
| -/*
|
| - * Same as handle_from_pid_waccess but implicitly uses
|
| - * PROCESS_QUERY_INFORMATION | PROCESS_VM_READ as dwDesiredAccess
|
| - * parameter for OpenProcess.
|
| - */
|
| -HANDLE
|
| -handle_from_pid(DWORD pid) {
|
| - DWORD dwDesiredAccess = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
|
| - return handle_from_pid_waccess(pid, dwDesiredAccess);
|
| -}
|
| -
|
| -
|
| -// fetch the PEB base address from NtQueryInformationProcess()
|
| -PVOID
|
| -GetPebAddress(HANDLE ProcessHandle)
|
| -{
|
| - _NtQueryInformationProcess NtQueryInformationProcess =
|
| - (_NtQueryInformationProcess)GetProcAddress(
|
| - GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
|
| - PROCESS_BASIC_INFORMATION pbi;
|
| -
|
| - NtQueryInformationProcess(ProcessHandle, 0, &pbi, sizeof(pbi), NULL);
|
| - return pbi.PebBaseAddress;
|
| -}
|
| -
|
| -
|
| -DWORD*
|
| -get_pids(DWORD *numberOfReturnedPIDs) {
|
| - int procArraySz = 1024;
|
| -
|
| - /* Win32 SDK says the only way to know if our process array
|
| - * wasn't large enough is to check the returned size and make
|
| - * sure that it doesn't match the size of the array.
|
| - * If it does we allocate a larger array and try again*/
|
| -
|
| - /* Stores the actual array */
|
| - DWORD *procArray = NULL;
|
| - DWORD procArrayByteSz;
|
| -
|
| - /* Stores the byte size of the returned array from enumprocesses */
|
| - DWORD enumReturnSz = 0;
|
| -
|
| - do {
|
| - free(procArray);
|
| - procArrayByteSz = procArraySz * sizeof(DWORD);
|
| - procArray = malloc(procArrayByteSz);
|
| -
|
| - if (! EnumProcesses(procArray, procArrayByteSz, &enumReturnSz)) {
|
| - free(procArray);
|
| - PyErr_SetFromWindowsErr(0);
|
| - return NULL;
|
| - }
|
| - else if (enumReturnSz == procArrayByteSz) {
|
| - /* Process list was too large. Allocate more space*/
|
| - procArraySz += 1024;
|
| - }
|
| -
|
| - /* else we have a good list */
|
| -
|
| - } while(enumReturnSz == procArraySz * sizeof(DWORD));
|
| -
|
| - /* The number of elements is the returned size / size of each element */
|
| - *numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD);
|
| -
|
| - return procArray;
|
| -}
|
| -
|
| -
|
| -int
|
| -pid_is_running(DWORD pid)
|
| -{
|
| - HANDLE hProcess;
|
| - DWORD exitCode;
|
| -
|
| - // Special case for PID 0 System Idle Process
|
| - if (pid == 0) {
|
| - return 1;
|
| - }
|
| -
|
| - if (pid < 0) {
|
| - return 0;
|
| - }
|
| -
|
| - hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
| - FALSE, pid);
|
| - if (NULL == hProcess) {
|
| - // invalid parameter is no such process
|
| - if (GetLastError() == ERROR_INVALID_PARAMETER) {
|
| - CloseHandle(hProcess);
|
| - return 0;
|
| - }
|
| -
|
| - // access denied obviously means there's a process to deny access to...
|
| - if (GetLastError() == ERROR_ACCESS_DENIED) {
|
| - CloseHandle(hProcess);
|
| - return 1;
|
| - }
|
| -
|
| - CloseHandle(hProcess);
|
| - PyErr_SetFromWindowsErr(0);
|
| - return -1;
|
| - }
|
| -
|
| - if (GetExitCodeProcess(hProcess, &exitCode)) {
|
| - CloseHandle(hProcess);
|
| - return (exitCode == STILL_ACTIVE);
|
| - }
|
| -
|
| - // access denied means there's a process there so we'll assume it's running
|
| - if (GetLastError() == ERROR_ACCESS_DENIED) {
|
| - CloseHandle(hProcess);
|
| - return 1;
|
| - }
|
| -
|
| - PyErr_SetFromWindowsErr(0);
|
| - CloseHandle(hProcess);
|
| - return -1;
|
| -}
|
| -
|
| -
|
| -int
|
| -pid_in_proclist(DWORD pid)
|
| -{
|
| - DWORD *proclist = NULL;
|
| - DWORD numberOfReturnedPIDs;
|
| - DWORD i;
|
| -
|
| - proclist = get_pids(&numberOfReturnedPIDs);
|
| - if (NULL == proclist) {
|
| - return -1;
|
| - }
|
| -
|
| - for (i = 0; i < numberOfReturnedPIDs; i++) {
|
| - if (pid == proclist[i]) {
|
| - free(proclist);
|
| - return 1;
|
| - }
|
| - }
|
| -
|
| - free(proclist);
|
| - return 0;
|
| -}
|
| -
|
| -
|
| -// Check exit code from a process handle. Return FALSE on an error also
|
| -BOOL is_running(HANDLE hProcess)
|
| -{
|
| - DWORD dwCode;
|
| -
|
| - if (NULL == hProcess) {
|
| - return FALSE;
|
| - }
|
| -
|
| - if (GetExitCodeProcess(hProcess, &dwCode)) {
|
| - return (dwCode == STILL_ACTIVE);
|
| - }
|
| - return FALSE;
|
| -}
|
| -
|
| -
|
| -// Return None to represent NoSuchProcess, else return NULL for
|
| -// other exception or the name as a Python string
|
| -PyObject*
|
| -get_name(long pid)
|
| -{
|
| - HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
| - PROCESSENTRY32 pe = { 0 };
|
| - pe.dwSize = sizeof(PROCESSENTRY32);
|
| -
|
| - if( Process32First(h, &pe)) {
|
| - do {
|
| - if (pe.th32ProcessID == pid) {
|
| - CloseHandle(h);
|
| - return Py_BuildValue("s", pe.szExeFile);
|
| - }
|
| - } while(Process32Next(h, &pe));
|
| -
|
| - // the process was never found, set NoSuchProcess exception
|
| - NoSuchProcess();
|
| - CloseHandle(h);
|
| - return NULL;
|
| - }
|
| -
|
| - CloseHandle(h);
|
| - return PyErr_SetFromWindowsErr(0);
|
| -}
|
| -
|
| -
|
| -/* returns parent pid (as a Python int) for given pid or None on failure */
|
| -PyObject*
|
| -get_ppid(long pid)
|
| -{
|
| - HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
| - PROCESSENTRY32 pe = { 0 };
|
| - pe.dwSize = sizeof(PROCESSENTRY32);
|
| -
|
| - if( Process32First(h, &pe)) {
|
| - do {
|
| - if (pe.th32ProcessID == pid) {
|
| - ////printf("PID: %i; PPID: %i\n", pid, pe.th32ParentProcessID);
|
| - CloseHandle(h);
|
| - return Py_BuildValue("I", pe.th32ParentProcessID);
|
| - }
|
| - } while(Process32Next(h, &pe));
|
| -
|
| - // the process was never found, set NoSuchProcess exception
|
| - NoSuchProcess();
|
| - CloseHandle(h);
|
| - return NULL;
|
| - }
|
| -
|
| - CloseHandle(h);
|
| - return PyErr_SetFromWindowsErr(0);
|
| -}
|
| -
|
| -
|
| -
|
| -/*
|
| - * returns a Python list representing the arguments for the process
|
| - * with given pid or NULL on error.
|
| - */
|
| -PyObject*
|
| -get_arg_list(long pid)
|
| -{
|
| - int nArgs, i;
|
| - LPWSTR *szArglist;
|
| - HANDLE hProcess;
|
| - PVOID pebAddress;
|
| - PVOID rtlUserProcParamsAddress;
|
| - UNICODE_STRING commandLine;
|
| - WCHAR *commandLineContents;
|
| - PyObject *arg = NULL;
|
| - PyObject *arg_from_wchar = NULL;
|
| - PyObject *argList = NULL;
|
| -
|
| - hProcess = handle_from_pid(pid);
|
| - if(hProcess == NULL) {
|
| - return NULL;
|
| - }
|
| -
|
| - pebAddress = GetPebAddress(hProcess);
|
| -
|
| - /* get the address of ProcessParameters */
|
| -#ifdef _WIN64
|
| - if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 32,
|
| - &rtlUserProcParamsAddress, sizeof(PVOID), NULL))
|
| -#else
|
| - if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 0x10,
|
| - &rtlUserProcParamsAddress, sizeof(PVOID), NULL))
|
| -#endif
|
| - {
|
| - ////printf("Could not read the address of ProcessParameters!\n");
|
| - PyErr_SetFromWindowsErr(0);
|
| - CloseHandle(hProcess);
|
| - return NULL;
|
| - }
|
| -
|
| - /* read the CommandLine UNICODE_STRING structure */
|
| -#ifdef _WIN64
|
| - if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 112,
|
| - &commandLine, sizeof(commandLine), NULL))
|
| -#else
|
| - if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 0x40,
|
| - &commandLine, sizeof(commandLine), NULL))
|
| -#endif
|
| - {
|
| - ////printf("Could not read CommandLine!\n");
|
| - CloseHandle(hProcess);
|
| - PyErr_SetFromWindowsErr(0);
|
| - return NULL;
|
| - }
|
| -
|
| -
|
| - /* allocate memory to hold the command line */
|
| - commandLineContents = (WCHAR *)malloc(commandLine.Length+1);
|
| -
|
| - /* read the command line */
|
| - if (!ReadProcessMemory(hProcess, commandLine.Buffer,
|
| - commandLineContents, commandLine.Length, NULL))
|
| - {
|
| - ////printf("Could not read the command line string!\n");
|
| - CloseHandle(hProcess);
|
| - PyErr_SetFromWindowsErr(0);
|
| - free(commandLineContents);
|
| - return NULL;
|
| - }
|
| -
|
| - /* print the commandline */
|
| - ////printf("%.*S\n", commandLine.Length / 2, commandLineContents);
|
| -
|
| - // null-terminate the string to prevent wcslen from returning incorrect length
|
| - // the length specifier is in characters, but commandLine.Length is in bytes
|
| - commandLineContents[(commandLine.Length/sizeof(WCHAR))] = '\0';
|
| -
|
| - // attemempt tp parse the command line using Win32 API, fall back on string
|
| - // cmdline version otherwise
|
| - szArglist = CommandLineToArgvW(commandLineContents, &nArgs);
|
| - if (NULL == szArglist) {
|
| - // failed to parse arglist
|
| - // encode as a UTF8 Python string object from WCHAR string
|
| - arg_from_wchar = PyUnicode_FromWideChar(commandLineContents,
|
| - commandLine.Length / 2);
|
| - #if PY_MAJOR_VERSION >= 3
|
| - argList = Py_BuildValue("N", PyUnicode_AsUTF8String(arg_from_wchar));
|
| - #else
|
| - argList = Py_BuildValue("N", PyUnicode_FromObject(arg_from_wchar));
|
| - #endif
|
| - }
|
| - else {
|
| - // arglist parsed as array of UNICODE_STRING, so convert each to Python
|
| - // string object and add to arg list
|
| - argList = Py_BuildValue("[]");
|
| - for(i=0; i<nArgs; i++) {
|
| - ////printf("%d: %.*S (%d characters)\n", i, wcslen(szArglist[i]),
|
| - // szArglist[i], wcslen(szArglist[i]));
|
| - arg_from_wchar = PyUnicode_FromWideChar(szArglist[i],
|
| - wcslen(szArglist[i])
|
| - );
|
| - #if PY_MAJOR_VERSION >= 3
|
| - arg = PyUnicode_FromObject(arg_from_wchar);
|
| - #else
|
| - arg = PyUnicode_AsUTF8String(arg_from_wchar);
|
| - #endif
|
| - Py_XDECREF(arg_from_wchar);
|
| - PyList_Append(argList, arg);
|
| - Py_XDECREF(arg);
|
| - }
|
| - }
|
| -
|
| - LocalFree(szArglist);
|
| - free(commandLineContents);
|
| - CloseHandle(hProcess);
|
| - return argList;
|
| -}
|
| -
|
| -
|
| -#define PH_FIRST_PROCESS(Processes) ((PSYSTEM_PROCESS_INFORMATION)(Processes))
|
| -
|
| -#define PH_NEXT_PROCESS(Process) ( \
|
| - ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset ? \
|
| - (PSYSTEM_PROCESS_INFORMATION)((PCHAR)(Process) + \
|
| - ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset) : \
|
| - NULL \
|
| - )
|
| -
|
| -const STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
|
| -const STATUS_BUFFER_TOO_SMALL = 0xC0000023L;
|
| -
|
| -/*
|
| - * Given a process PID and a PSYSTEM_PROCESS_INFORMATION structure
|
| - * fills the structure with process information.
|
| - * On success return 1, else 0 with Python exception already set.
|
| - */
|
| -int
|
| -get_process_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, PVOID *retBuffer)
|
| -{
|
| - static ULONG initialBufferSize = 0x4000;
|
| - NTSTATUS status;
|
| - PVOID buffer;
|
| - ULONG bufferSize;
|
| - PSYSTEM_PROCESS_INFORMATION process;
|
| -
|
| - // get NtQuerySystemInformation
|
| - typedef DWORD (_stdcall *NTQSI_PROC) (int, PVOID, ULONG, PULONG);
|
| - NTQSI_PROC NtQuerySystemInformation;
|
| - HINSTANCE hNtDll;
|
| - hNtDll = LoadLibrary(TEXT("ntdll.dll"));
|
| - NtQuerySystemInformation = (NTQSI_PROC)GetProcAddress(
|
| - hNtDll, "NtQuerySystemInformation");
|
| -
|
| - bufferSize = initialBufferSize;
|
| - buffer = malloc(bufferSize);
|
| -
|
| - while (TRUE) {
|
| - status = NtQuerySystemInformation(SystemProcessInformation, buffer,
|
| - bufferSize, &bufferSize);
|
| -
|
| - if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INFO_LENGTH_MISMATCH)
|
| - {
|
| - free(buffer);
|
| - buffer = malloc(bufferSize);
|
| - }
|
| - else {
|
| - break;
|
| - }
|
| - }
|
| -
|
| - if (status != 0) {
|
| - PyErr_Format(PyExc_RuntimeError, "NtQuerySystemInformation() failed");
|
| - return 0;
|
| - }
|
| -
|
| - if (bufferSize <= 0x20000) {
|
| - initialBufferSize = bufferSize;
|
| - }
|
| -
|
| - process = PH_FIRST_PROCESS(buffer);
|
| - do {
|
| - if (process->UniqueProcessId == (HANDLE)pid) {
|
| - *retProcess = process;
|
| - *retBuffer = buffer;
|
| - return 1;
|
| - }
|
| - } while ( (process = PH_NEXT_PROCESS(process)) );
|
| -
|
| - NoSuchProcess();
|
| - return 0;
|
| -}
|
| -
|
| -
|
|
|