Index: third_party/psutil/psutil/_psutil_mswindows.c |
diff --git a/third_party/psutil/psutil/_psutil_mswindows.c b/third_party/psutil/psutil/_psutil_mswindows.c |
deleted file mode 100644 |
index 3964179ab97273ed3d401a1fab9bab55760a4767..0000000000000000000000000000000000000000 |
--- a/third_party/psutil/psutil/_psutil_mswindows.c |
+++ /dev/null |
@@ -1,1897 +0,0 @@ |
-/* |
- * $Id: _psutil_mswindows.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. |
- * |
- * Windows platform-specific module methods for _psutil_mswindows |
- */ |
- |
-#include <Python.h> |
-#include <windows.h> |
-#include <Psapi.h> |
-#include <time.h> |
-#include <lm.h> |
-#include <tchar.h> |
-#include <tlhelp32.h> |
-#include <iphlpapi.h> |
- |
-#include "_psutil_mswindows.h" |
-#include "_psutil_common.h" |
-#include "arch/mswindows/security.h" |
-#include "arch/mswindows/process_info.h" |
-#include "arch/mswindows/process_handles.h" |
-#include "arch/mswindows/ntextapi.h" |
- |
- |
-/* |
- * Return a Python float representing the system uptime expressed in seconds |
- * since the epoch. |
- */ |
-static PyObject* |
-get_system_uptime(PyObject* self, PyObject* args) |
-{ |
- double uptime; |
- time_t pt; |
- FILETIME fileTime; |
- long long ll; |
- |
- GetSystemTimeAsFileTime(&fileTime); |
- |
- /* |
- HUGE thanks to: |
- http://johnstewien.spaces.live.com/blog/cns!E6885DB5CEBABBC8!831.entry |
- |
- This function converts the FILETIME structure to the 32 bit |
- Unix time structure. |
- The time_t is a 32-bit value for the number of seconds since |
- January 1, 1970. A FILETIME is a 64-bit for the number of |
- 100-nanosecond periods since January 1, 1601. Convert by |
- subtracting the number of 100-nanosecond period betwee 01-01-1970 |
- and 01-01-1601, from time_t the divide by 1e+7 to get to the same |
- base granularity. |
- */ |
- ll = (((LONGLONG)(fileTime.dwHighDateTime)) << 32) + fileTime.dwLowDateTime; |
- pt = (time_t)((ll - 116444736000000000ull) / 10000000ull); |
- |
- // XXX - By using GetTickCount() time will wrap around to zero if the |
- // system is run continuously for 49.7 days. |
- uptime = GetTickCount() / 1000.00f; |
- return Py_BuildValue("d", (double)pt - uptime); |
-} |
- |
- |
-/* |
- * Return 1 if PID exists in the current process list, else 0. |
- */ |
-static PyObject* |
-pid_exists(PyObject* self, PyObject* args) |
-{ |
- long pid; |
- int status; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- status = pid_is_running(pid); |
- if (-1 == status) { |
- return NULL; // exception raised in pid_is_running() |
- } |
- return PyBool_FromLong(status); |
-} |
- |
- |
-/* |
- * Return a Python list of all the PIDs running on the system. |
- */ |
-static PyObject* |
-get_pid_list(PyObject* self, PyObject* args) |
-{ |
- DWORD *proclist = NULL; |
- DWORD numberOfReturnedPIDs; |
- DWORD i; |
- PyObject* pid = NULL; |
- PyObject* retlist = PyList_New(0); |
- |
- proclist = get_pids(&numberOfReturnedPIDs); |
- if (NULL == proclist) { |
- Py_DECREF(retlist); |
- return NULL; |
- } |
- |
- for (i = 0; i < numberOfReturnedPIDs; i++) { |
- pid = Py_BuildValue("I", proclist[i]); |
- PyList_Append(retlist, pid); |
- Py_XDECREF(pid); |
- } |
- |
- // free C array allocated for PIDs |
- free(proclist); |
- |
- return retlist; |
-} |
- |
- |
-/* |
- * Kill a process given its PID. |
- */ |
-static PyObject* |
-kill_process(PyObject* self, PyObject* args) |
-{ |
- HANDLE hProcess; |
- long pid; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- if (pid == 0) { |
- return AccessDenied(); |
- } |
- |
- hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); |
- if (hProcess == NULL) { |
- if (GetLastError() == ERROR_INVALID_PARAMETER) { |
- // see http://code.google.com/p/psutil/issues/detail?id=24 |
- NoSuchProcess(); |
- } |
- else { |
- PyErr_SetFromWindowsErr(0); |
- } |
- return NULL; |
- } |
- |
- // kill the process |
- if (! TerminateProcess(hProcess, 0)) { |
- PyErr_SetFromWindowsErr(0); |
- CloseHandle(hProcess); |
- return NULL; |
- } |
- |
- CloseHandle(hProcess); |
- Py_INCREF(Py_None); |
- return Py_None; |
-} |
- |
- |
-/* |
- * Wait for process to terminate and return its exit code. |
- */ |
-static PyObject* |
-process_wait(PyObject* self, PyObject* args) |
-{ |
- HANDLE hProcess; |
- DWORD ExitCode; |
- DWORD retVal; |
- long pid; |
- long timeout; |
- |
- if (! PyArg_ParseTuple(args, "ll", &pid, &timeout)) { |
- return NULL; |
- } |
- if (pid == 0) { |
- return AccessDenied(); |
- } |
- |
- hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid); |
- if (hProcess == NULL) { |
- if (GetLastError() == ERROR_INVALID_PARAMETER) { |
- // no such process; we do not want to raise NSP but |
- // return None instead. |
- Py_INCREF(Py_None); |
- return Py_None; |
- } |
- else { |
- PyErr_SetFromWindowsErr(0); |
- return NULL; |
- } |
- } |
- |
- // wait until the process has terminated |
- Py_BEGIN_ALLOW_THREADS |
- retVal = WaitForSingleObject(hProcess, timeout); |
- Py_END_ALLOW_THREADS |
- |
- if (retVal == WAIT_FAILED) { |
- CloseHandle(hProcess); |
- return PyErr_SetFromWindowsErr(GetLastError()); |
- } |
- if (retVal == WAIT_TIMEOUT) { |
- CloseHandle(hProcess); |
- return Py_BuildValue("l", WAIT_TIMEOUT); |
- } |
- |
- // get the exit code; note: subprocess module (erroneously?) uses |
- // what returned by WaitForSingleObject |
- if (GetExitCodeProcess(hProcess, &ExitCode) == 0) { |
- CloseHandle(hProcess); |
- return PyErr_SetFromWindowsErr(GetLastError()); |
- } |
- CloseHandle(hProcess); |
-#if PY_MAJOR_VERSION >= 3 |
- return PyLong_FromLong((long) ExitCode); |
-#else |
- return PyInt_FromLong((long) ExitCode); |
-#endif |
-} |
- |
- |
-/* |
- * Return a Python tuple (user_time, kernel_time) |
- */ |
-static PyObject* |
-get_process_cpu_times(PyObject* self, PyObject* args) |
-{ |
- long pid; |
- HANDLE hProcess; |
- FILETIME ftCreate, ftExit, ftKernel, ftUser; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- // special case for PID 0 |
- if (0 == pid){ |
- return Py_BuildValue("(dd)", 0.0, 0.0); |
- } |
- |
- hProcess = handle_from_pid(pid); |
- if (hProcess == NULL) { |
- return NULL; |
- } |
- |
- if (! GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) { |
- CloseHandle(hProcess); |
- if (GetLastError() == ERROR_ACCESS_DENIED) { |
- // usually means the process has died so we throw a NoSuchProcess |
- // here |
- return NoSuchProcess(); |
- } |
- else { |
- PyErr_SetFromWindowsErr(0); |
- return NULL; |
- } |
- } |
- |
- CloseHandle(hProcess); |
- |
- /* |
- user and kernel times are represented as a FILETIME structure wich contains |
- a 64-bit value representing the number of 100-nanosecond intervals since |
- January 1, 1601 (UTC). |
- http://msdn.microsoft.com/en-us/library/ms724284(VS.85).aspx |
- |
- To convert it into a float representing the seconds that the process has |
- executed in user/kernel mode I borrowed the code below from Python's |
- Modules/posixmodule.c |
- */ |
- |
- return Py_BuildValue( |
- "(dd)", |
- (double)(ftUser.dwHighDateTime*429.4967296 + \ |
- ftUser.dwLowDateTime*1e-7), |
- (double)(ftKernel.dwHighDateTime*429.4967296 + \ |
- ftKernel.dwLowDateTime*1e-7) |
- ); |
-} |
- |
- |
-/* |
- * Return a Python float indicating the process create time expressed in |
- * seconds since the epoch. |
- */ |
-static PyObject* |
-get_process_create_time(PyObject* self, PyObject* args) |
-{ |
- long pid; |
- long long unix_time; |
- HANDLE hProcess; |
- FILETIME ftCreate, ftExit, ftKernel, ftUser; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- // special case for PIDs 0 and 4 |
- if ( (0 == pid) || (4 == pid) ){ |
- return Py_BuildValue("d", 0.0); |
- } |
- |
- hProcess = handle_from_pid(pid); |
- if (hProcess == NULL) { |
- return NULL; |
- } |
- |
- if (! GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) { |
- CloseHandle(hProcess); |
- if (GetLastError() == ERROR_ACCESS_DENIED) { |
- // usually means the process has died so we throw a NoSuchProcess here |
- return NoSuchProcess(); |
- } |
- else { |
- PyErr_SetFromWindowsErr(0); |
- return NULL; |
- } |
- } |
- |
- CloseHandle(hProcess); |
- |
- /* |
- Convert the FILETIME structure to a Unix time. |
- It's the best I could find by googling and borrowing code here and there. |
- The time returned has a precision of 1 second. |
- */ |
- unix_time = ((LONGLONG)ftCreate.dwHighDateTime) << 32; |
- unix_time += ftCreate.dwLowDateTime - 116444736000000000LL; |
- unix_time /= 10000000; |
- return Py_BuildValue("d", (double)unix_time); |
-} |
- |
- |
-/* |
- * Return a Python integer indicating the number of CPUs on the system. |
- */ |
-static PyObject* |
-get_num_cpus(PyObject* self, PyObject* args) |
-{ |
- SYSTEM_INFO system_info; |
- system_info.dwNumberOfProcessors = 0; |
- |
- GetSystemInfo(&system_info); |
- if (system_info.dwNumberOfProcessors == 0){ |
- // GetSystemInfo failed for some reason; return 1 as default |
- return Py_BuildValue("I", 1); |
- } |
- return Py_BuildValue("I", system_info.dwNumberOfProcessors); |
-} |
- |
-/* |
- * Return process name as a Python string. |
- */ |
-static PyObject* |
-get_process_name(PyObject* self, PyObject* args) { |
- long pid; |
- int pid_return; |
- PyObject* name; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- if (pid == 0) { |
- return Py_BuildValue("s", "System Idle Process"); |
- } |
- else if (pid == 4) { |
- return Py_BuildValue("s", "System"); |
- } |
- |
- pid_return = pid_is_running(pid); |
- if (pid_return == 0) { |
- return NoSuchProcess(); |
- } |
- if (pid_return == -1) { |
- return NULL; |
- } |
- |
- name = get_name(pid); |
- if (name == NULL) { |
- return NULL; // exception set in get_name() |
- } |
- return name; |
-} |
- |
- |
-/* |
- * Return process parent pid as a Python integer. |
- */ |
-static PyObject* |
-get_process_ppid(PyObject* self, PyObject* args) { |
- long pid; |
- int pid_return; |
- PyObject* ppid; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- if ((pid == 0) || (pid == 4)) { |
- return Py_BuildValue("l", 0); |
- } |
- |
- pid_return = pid_is_running(pid); |
- if (pid_return == 0) { |
- return NoSuchProcess(); |
- } |
- if (pid_return == -1) { |
- return NULL; |
- } |
- |
- ppid = get_ppid(pid); |
- if (ppid == NULL) { |
- return NULL; // exception set in get_ppid() |
- } |
- return ppid; |
-} |
- |
-/* |
- * Return process cmdline as a Python list of cmdline arguments. |
- */ |
-static PyObject* |
-get_process_cmdline(PyObject* self, PyObject* args) { |
- long pid; |
- int pid_return; |
- PyObject* arglist; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- if ((pid == 0) || (pid == 4)) { |
- return Py_BuildValue("[]"); |
- } |
- |
- pid_return = pid_is_running(pid); |
- if (pid_return == 0) { |
- return NoSuchProcess(); |
- } |
- if (pid_return == -1) { |
- return NULL; |
- } |
- |
- // May fail any of several ReadProcessMemory calls etc. and not indicate |
- // a real problem so we ignore any errors and just live without commandline |
- arglist = get_arg_list(pid); |
- if ( NULL == arglist ) { |
- // carry on anyway, clear any exceptions too |
- PyErr_Clear(); |
- return Py_BuildValue("[]"); |
- } |
- |
- return arglist; |
-} |
- |
- |
-/* |
- * Return the RSS and VMS as a Python tuple. |
- */ |
-static PyObject* |
-get_memory_info(PyObject* self, PyObject* args) |
-{ |
- HANDLE hProcess; |
- PROCESS_MEMORY_COUNTERS counters; |
- DWORD pid; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- hProcess = handle_from_pid(pid); |
- if (NULL == hProcess) { |
- return NULL; |
- } |
- |
- if (! GetProcessMemoryInfo(hProcess, &counters, sizeof(counters)) ) { |
- CloseHandle(hProcess); |
- return PyErr_SetFromWindowsErr(0); |
- } |
- |
- CloseHandle(hProcess); |
- return Py_BuildValue("(nn)", counters.WorkingSetSize, counters.PagefileUsage); |
-} |
- |
- |
-/* |
- * Return a Python integer indicating the total amount of physical memory |
- * in bytes. |
- */ |
-static PyObject* |
-get_system_phymem(PyObject* self, PyObject* args) |
-{ |
- MEMORYSTATUSEX memInfo; |
- memInfo.dwLength = sizeof(MEMORYSTATUSEX); |
- |
- if (! GlobalMemoryStatusEx(&memInfo) ) { |
- return PyErr_SetFromWindowsErr(0); |
- } |
- |
- return Py_BuildValue("(LLLLLLk)", |
- memInfo.ullTotalPhys, // total |
- memInfo.ullAvailPhys, // avail |
- memInfo.ullTotalPageFile, // total page file |
- memInfo.ullAvailPageFile, // avail page file |
- memInfo.ullTotalVirtual, // total virtual |
- memInfo.ullAvailVirtual, // avail virtual |
- memInfo.dwMemoryLoad // percent |
- ); |
-} |
- |
- |
-#define LO_T ((float)1e-7) |
-#define HI_T (LO_T*4294967296.0) |
- |
- |
-/* |
- * Return a Python list of tuples representing user, kernel and idle |
- * CPU times for every CPU on the system. |
- */ |
-static PyObject* |
-get_system_cpu_times(PyObject* self, PyObject* args) |
-{ |
- float idle, kernel, user; |
- typedef DWORD (_stdcall *NTQSI_PROC) (int, PVOID, ULONG, PULONG); |
- NTQSI_PROC NtQuerySystemInformation; |
- HINSTANCE hNtDll; |
- SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL; |
- SYSTEM_INFO si; |
- UINT i; |
- PyObject *arg = NULL; |
- PyObject *retlist = PyList_New(0); |
- |
- // dynamic linking is mandatory to use NtQuerySystemInformation |
- hNtDll = LoadLibrary(TEXT("ntdll.dll")); |
- if (hNtDll != NULL) { |
- // gets NtQuerySystemInformation address |
- NtQuerySystemInformation = (NTQSI_PROC)GetProcAddress( |
- hNtDll, "NtQuerySystemInformation"); |
- |
- if (NtQuerySystemInformation != NULL) |
- { |
- // retrives number of processors |
- GetSystemInfo(&si); |
- |
- // allocates an array of SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION |
- // structures, one per processor |
- sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \ |
- malloc(si.dwNumberOfProcessors * \ |
- sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); |
- if (sppi != NULL) |
- { |
- // gets cpu time informations |
- if (0 == NtQuerySystemInformation( |
- SystemProcessorPerformanceInformation, |
- sppi, |
- si.dwNumberOfProcessors * sizeof |
- (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), |
- NULL) |
- ) |
- { |
- // computes system global times summing each processor value |
- idle = user = kernel = 0; |
- for (i=0; i<si.dwNumberOfProcessors; i++) { |
- user = (float)((HI_T * sppi[i].UserTime.HighPart) + \ |
- (LO_T * sppi[i].UserTime.LowPart)); |
- idle = (float)((HI_T * sppi[i].IdleTime.HighPart) + \ |
- (LO_T * sppi[i].IdleTime.LowPart)); |
- kernel = (float)((HI_T * sppi[i].KernelTime.HighPart) + \ |
- (LO_T * sppi[i].KernelTime.LowPart)); |
- // kernel time includes idle time on windows |
- // we return only busy kernel time subtracting |
- // idle time from kernel time |
- arg = Py_BuildValue("(ddd)", user, |
- kernel - idle, |
- idle); |
- PyList_Append(retlist, arg); |
- Py_XDECREF(arg); |
- } |
- free(sppi); |
- FreeLibrary(hNtDll); |
- return retlist; |
- |
- } // END NtQuerySystemInformation |
- } // END malloc SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION |
- } // END GetProcAddress |
- } // END LoadLibrary |
- |
- if (sppi) { |
- free(sppi); |
- } |
- if (hNtDll) { |
- FreeLibrary(hNtDll); |
- } |
- PyErr_SetFromWindowsErr(0); |
- return NULL; |
-} |
- |
- |
-/* |
- * Return process current working directory as a Python string. |
- */ |
- |
-static PyObject* |
-get_process_cwd(PyObject* self, PyObject* args) |
-{ |
- long pid; |
- HANDLE processHandle; |
- PVOID pebAddress; |
- PVOID rtlUserProcParamsAddress; |
- UNICODE_STRING currentDirectory; |
- WCHAR *currentDirectoryContent; |
- PyObject *returnPyObj = NULL; |
- PyObject *cwd_from_wchar = NULL; |
- PyObject *cwd = NULL; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- processHandle = handle_from_pid(pid); |
- if (processHandle == NULL) { |
- return NULL; |
- } |
- |
- pebAddress = GetPebAddress(processHandle); |
- |
- /* get the address of ProcessParameters */ |
-#ifdef _WIN64 |
- if (!ReadProcessMemory(processHandle, (PCHAR)pebAddress + 32, |
- &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) |
-#else |
- if (!ReadProcessMemory(processHandle, (PCHAR)pebAddress + 0x10, |
- &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) |
-#endif |
- { |
- CloseHandle(processHandle); |
- |
- if (GetLastError() == ERROR_PARTIAL_COPY) { |
- /* Usually means the process has gone in the meantime */ |
- return NoSuchProcess(); |
- } |
- else { |
- return PyErr_SetFromWindowsErr(0); |
- } |
- |
- } |
- |
- /* read the currentDirectory UNICODE_STRING structure. |
- 0x24 refers to "CurrentDirectoryPath" of RTL_USER_PROCESS_PARAMETERS |
- structure (http://wj32.wordpress.com/2009/01/24/howto-get-the-command-line-of-processes/) |
- */ |
-#ifdef _WIN64 |
- if (!ReadProcessMemory(processHandle, (PCHAR)rtlUserProcParamsAddress + 56, |
- ¤tDirectory, sizeof(currentDirectory), NULL)) |
-#else |
- if (!ReadProcessMemory(processHandle, (PCHAR)rtlUserProcParamsAddress + 0x24, |
- ¤tDirectory, sizeof(currentDirectory), NULL)) |
-#endif |
- { |
- CloseHandle(processHandle); |
- if (GetLastError() == ERROR_PARTIAL_COPY) { |
- /* Usually means the process has gone in the meantime */ |
- return NoSuchProcess(); |
- } |
- else { |
- return PyErr_SetFromWindowsErr(0); |
- } |
- } |
- |
- /* allocate memory to hold the command line */ |
- currentDirectoryContent = (WCHAR *)malloc(currentDirectory.Length+1); |
- |
- /* read the command line */ |
- if (!ReadProcessMemory(processHandle, currentDirectory.Buffer, |
- currentDirectoryContent, currentDirectory.Length, NULL)) |
- { |
- CloseHandle(processHandle); |
- free(currentDirectoryContent); |
- |
- if (GetLastError() == ERROR_PARTIAL_COPY) { |
- /* Usually means the process has gone in the meantime */ |
- return NoSuchProcess(); |
- } |
- else { |
- return PyErr_SetFromWindowsErr(0); |
- } |
- } |
- |
- // null-terminate the string to prevent wcslen from returning incorrect length |
- // the length specifier is in characters, but commandLine.Length is in bytes |
- currentDirectoryContent[(currentDirectory.Length/sizeof(WCHAR))] = '\0'; |
- |
- // convert wchar array to a Python unicode string, and then to UTF8 |
- cwd_from_wchar = PyUnicode_FromWideChar(currentDirectoryContent, |
- wcslen(currentDirectoryContent)); |
- |
- #if PY_MAJOR_VERSION >= 3 |
- cwd = PyUnicode_FromObject(cwd_from_wchar); |
- #else |
- cwd = PyUnicode_AsUTF8String(cwd_from_wchar); |
- #endif |
- |
- // decrement the reference count on our temp unicode str to avoid mem leak |
- Py_XDECREF(cwd_from_wchar); |
- returnPyObj = Py_BuildValue("N", cwd); |
- |
- CloseHandle(processHandle); |
- free(currentDirectoryContent); |
- return returnPyObj; |
-} |
- |
- |
-/* |
- * Resume or suspends a process |
- */ |
-int |
-suspend_resume_process(DWORD pid, int suspend) |
-{ |
- // a huge thanks to http://www.codeproject.com/KB/threads/pausep.aspx |
- HANDLE hThreadSnap = NULL; |
- THREADENTRY32 te32 = {0}; |
- |
- if (pid == 0) { |
- AccessDenied(); |
- return FALSE; |
- } |
- |
- hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); |
- if (hThreadSnap == INVALID_HANDLE_VALUE) { |
- PyErr_SetFromWindowsErr(0); |
- return FALSE; |
- } |
- |
- // Fill in the size of the structure before using it |
- te32.dwSize = sizeof(THREADENTRY32); |
- |
- if (! Thread32First(hThreadSnap, &te32)) { |
- PyErr_SetFromWindowsErr(0); |
- CloseHandle(hThreadSnap); |
- return FALSE; |
- } |
- |
- // Walk the thread snapshot to find all threads of the process. |
- // If the thread belongs to the process, add its information |
- // to the display list. |
- do |
- { |
- if (te32.th32OwnerProcessID == pid) |
- { |
- HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, |
- te32.th32ThreadID); |
- if (hThread == NULL) { |
- PyErr_SetFromWindowsErr(0); |
- CloseHandle(hThread); |
- CloseHandle(hThreadSnap); |
- return FALSE; |
- } |
- if (suspend == 1) |
- { |
- if (SuspendThread(hThread) == (DWORD)-1) { |
- PyErr_SetFromWindowsErr(0); |
- CloseHandle(hThread); |
- CloseHandle(hThreadSnap); |
- return FALSE; |
- } |
- } |
- else |
- { |
- if (ResumeThread(hThread) == (DWORD)-1) { |
- PyErr_SetFromWindowsErr(0); |
- CloseHandle(hThread); |
- CloseHandle(hThreadSnap); |
- return FALSE; |
- } |
- } |
- CloseHandle(hThread); |
- } |
- } while (Thread32Next(hThreadSnap, &te32)); |
- |
- return TRUE; |
-} |
- |
- |
-static PyObject* |
-suspend_process(PyObject* self, PyObject* args) |
-{ |
- long pid; |
- int suspend = 1; |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- if (! suspend_resume_process(pid, suspend)) { |
- return NULL; |
- } |
- Py_INCREF(Py_None); |
- return Py_None; |
-} |
- |
- |
-static PyObject* |
-resume_process(PyObject* self, PyObject* args) |
-{ |
- long pid; |
- int suspend = 0; |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- if (! suspend_resume_process(pid, suspend)) { |
- return NULL; |
- } |
- Py_INCREF(Py_None); |
- return Py_None; |
-} |
- |
- |
-static PyObject* |
-get_process_num_threads(PyObject* self, PyObject* args) |
-{ |
- DWORD pid; |
- PSYSTEM_PROCESS_INFORMATION process; |
- PVOID buffer; |
- int num; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- if (get_process_info(pid, &process, &buffer) != 1) { |
- free(buffer); |
- return NULL; |
- } |
- if (pid_is_running(pid) == 0) { |
- free(buffer); |
- return NoSuchProcess(); |
- } |
- |
- num = (int)process->NumberOfThreads; |
- free(buffer); |
- return Py_BuildValue("i", num); |
-} |
- |
- |
-static PyObject* |
-get_process_threads(PyObject* self, PyObject* args) |
-{ |
- PyObject* retList = PyList_New(0); |
- PyObject* pyTuple = NULL; |
- HANDLE hThreadSnap = NULL; |
- THREADENTRY32 te32 = {0}; |
- long pid; |
- int pid_return; |
- int rc; |
- FILETIME ftDummy, ftKernel, ftUser; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- if (pid == 0) { |
- // raise AD instead of returning 0 as procexp is able to |
- // retrieve useful information somehow |
- return AccessDenied(); |
- } |
- |
- pid_return = pid_is_running(pid); |
- if (pid_return == 0) { |
- return NoSuchProcess(); |
- } |
- if (pid_return == -1) { |
- return NULL; |
- } |
- |
- hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); |
- if (hThreadSnap == INVALID_HANDLE_VALUE) { |
- PyErr_SetFromWindowsErr(0); |
- return NULL; |
- } |
- |
- // Fill in the size of the structure before using it |
- te32.dwSize = sizeof(THREADENTRY32); |
- |
- if (! Thread32First(hThreadSnap, &te32)) { |
- PyErr_SetFromWindowsErr(0); |
- CloseHandle(hThreadSnap); |
- return NULL; |
- } |
- |
- // Walk the thread snapshot to find all threads of the process. |
- // If the thread belongs to the process, increase the counter. |
- do |
- { |
- if (te32.th32OwnerProcessID == pid) |
- { |
- HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, |
- FALSE, te32.th32ThreadID); |
- if (hThread == NULL) { |
- // thread has disappeared on us |
- continue; |
- } |
- |
- rc = GetThreadTimes(hThread, &ftDummy, &ftDummy, &ftKernel, &ftUser); |
- if (rc == 0) { |
- PyErr_SetFromWindowsErr(0); |
- CloseHandle(hThread); |
- CloseHandle(hThreadSnap); |
- return NULL; |
- } |
- |
- /* |
- user and kernel times are represented as a FILETIME structure |
- wich contains a 64-bit value representing the number of |
- 100-nanosecond intervals since January 1, 1601 (UTC). |
- http://msdn.microsoft.com/en-us/library/ms724284(VS.85).aspx |
- |
- To convert it into a float representing the seconds that the |
- process has executed in user/kernel mode I borrowed the code |
- below from Python's Modules/posixmodule.c |
- */ |
- pyTuple = Py_BuildValue("kdd", |
- te32.th32ThreadID, |
- (double)(ftUser.dwHighDateTime*429.4967296 + \ |
- ftUser.dwLowDateTime*1e-7), |
- (double)(ftKernel.dwHighDateTime*429.4967296 + \ |
- ftKernel.dwLowDateTime*1e-7) |
- ); |
- PyList_Append(retList, pyTuple); |
- Py_XDECREF(pyTuple); |
- |
- CloseHandle(hThread); |
- } |
- } while (Thread32Next(hThreadSnap, &te32)); |
- |
- CloseHandle(hThreadSnap); |
- return retList; |
-} |
- |
- |
- |
-static PyObject* |
-get_process_open_files(PyObject* self, PyObject* args) |
-{ |
- long pid; |
- HANDLE processHandle; |
- DWORD access = PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; |
- PyObject* filesList; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- processHandle = handle_from_pid_waccess(pid, access); |
- if (processHandle == NULL) { |
- return NULL; |
- } |
- |
- filesList = get_open_files(pid, processHandle); |
- CloseHandle(processHandle); |
- if (filesList == NULL) { |
- return PyErr_SetFromWindowsErr(0); |
- } |
- return filesList; |
-} |
- |
- |
-/* |
- Accept a filename's drive in native format like "\Device\HarddiskVolume1\" |
- and return the corresponding drive letter (e.g. "C:\\"). |
- If no match is found return an empty string. |
-*/ |
-static PyObject* |
-win32_QueryDosDevice(PyObject* self, PyObject* args) |
-{ |
- LPCTSTR lpDevicePath; |
- TCHAR d = TEXT('A'); |
- TCHAR szBuff[5]; |
- |
- if (!PyArg_ParseTuple(args, "s", &lpDevicePath)) { |
- return NULL; |
- } |
- |
- while(d <= TEXT('Z')) |
- { |
- TCHAR szDeviceName[3] = {d,TEXT(':'),TEXT('\0')}; |
- TCHAR szTarget[512] = {0}; |
- if (QueryDosDevice(szDeviceName, szTarget, 511) != 0){ |
- //_tprintf (TEXT("%c:\\ => %s\n"), d, szTarget); |
- if(_tcscmp(lpDevicePath, szTarget) == 0) { |
- _stprintf(szBuff, TEXT("%c:"), d); |
- return Py_BuildValue("s", szBuff); |
- } |
- } |
- d++; |
- } |
- return Py_BuildValue("s", ""); |
-} |
- |
-/* |
- * Return process username as a "DOMAIN//USERNAME" string. |
- */ |
-static PyObject* |
-get_process_username(PyObject* self, PyObject* args) |
-{ |
- long pid; |
- HANDLE processHandle; |
- HANDLE tokenHandle; |
- PTOKEN_USER user; |
- ULONG bufferSize; |
- PTSTR name; |
- ULONG nameSize; |
- PTSTR domainName; |
- ULONG domainNameSize; |
- SID_NAME_USE nameUse; |
- PTSTR fullName; |
- PyObject* returnObject; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- processHandle = handle_from_pid_waccess(pid, PROCESS_QUERY_INFORMATION); |
- if (processHandle == NULL) { |
- return NULL; |
- } |
- |
- if (!OpenProcessToken(processHandle, TOKEN_QUERY, &tokenHandle)) { |
- CloseHandle(processHandle); |
- return PyErr_SetFromWindowsErr(0); |
- } |
- |
- CloseHandle(processHandle); |
- |
- /* Get the user SID. */ |
- |
- bufferSize = 0x100; |
- user = malloc(bufferSize); |
- |
- if (!GetTokenInformation(tokenHandle, |
- TokenUser, |
- user, |
- bufferSize, |
- &bufferSize)) |
- { |
- free(user); |
- user = malloc(bufferSize); |
- |
- if (!GetTokenInformation(tokenHandle, |
- TokenUser, |
- user, |
- bufferSize, |
- &bufferSize)) |
- { |
- free(user); |
- CloseHandle(tokenHandle); |
- return PyErr_SetFromWindowsErr(0); |
- } |
- } |
- |
- CloseHandle(tokenHandle); |
- |
- /* Resolve the SID to a name. */ |
- |
- nameSize = 0x100; |
- domainNameSize = 0x100; |
- |
- name = malloc(nameSize * sizeof(TCHAR)); |
- domainName = malloc(domainNameSize * sizeof(TCHAR)); |
- |
- if (!LookupAccountSid(NULL, user->User.Sid, name, &nameSize, domainName, |
- &domainNameSize, &nameUse)) |
- { |
- free(name); |
- free(domainName); |
- name = malloc(nameSize * sizeof(TCHAR)); |
- domainName = malloc(domainNameSize * sizeof(TCHAR)); |
- |
- if (!LookupAccountSid(NULL, user->User.Sid, name, &nameSize, domainName, |
- &domainNameSize, &nameUse)) |
- { |
- free(name); |
- free(domainName); |
- free(user); |
- |
- return PyErr_SetFromWindowsErr(0); |
- } |
- } |
- |
- nameSize = _tcslen(name); |
- domainNameSize = _tcslen(domainName); |
- |
- /* Build the full username string. */ |
- fullName = malloc((domainNameSize + 1 + nameSize + 1) * sizeof(TCHAR)); |
- memcpy(fullName, domainName, domainNameSize); |
- fullName[domainNameSize] = '\\'; |
- memcpy(&fullName[domainNameSize + 1], name, nameSize); |
- fullName[domainNameSize + 1 + nameSize] = '\0'; |
- |
- returnObject = Py_BuildValue("s", fullName); |
- |
- free(fullName); |
- free(name); |
- free(domainName); |
- free(user); |
- |
- return returnObject; |
-} |
- |
-#define BYTESWAP_USHORT(x) ((((USHORT)(x) << 8) | ((USHORT)(x) >> 8)) & 0xffff) |
- |
-#ifndef AF_INET6 |
-#define AF_INET6 23 |
-#endif |
- |
-static char *state_to_string(ULONG state) |
-{ |
- switch (state) |
- { |
- case MIB_TCP_STATE_CLOSED: |
- return "CLOSE"; |
- case MIB_TCP_STATE_LISTEN: |
- return "LISTEN"; |
- case MIB_TCP_STATE_SYN_SENT: |
- return "SYN_SENT"; |
- case MIB_TCP_STATE_SYN_RCVD: |
- return "SYN_RECV"; |
- case MIB_TCP_STATE_ESTAB: |
- return "ESTABLISHED"; |
- case MIB_TCP_STATE_FIN_WAIT1: |
- return "FIN_WAIT1"; |
- case MIB_TCP_STATE_FIN_WAIT2: |
- return "FIN_WAIT2"; |
- case MIB_TCP_STATE_CLOSE_WAIT: |
- return "CLOSE_WAIT"; |
- case MIB_TCP_STATE_CLOSING: |
- return "CLOSING"; |
- case MIB_TCP_STATE_LAST_ACK: |
- return "LAST_ACK"; |
- case MIB_TCP_STATE_TIME_WAIT: |
- return "TIME_WAIT"; |
- case MIB_TCP_STATE_DELETE_TCB: |
- return "DELETE_TCB"; |
- default: |
- return ""; |
- } |
-} |
- |
-/* mingw support */ |
-#ifndef _IPRTRMIB_H |
-typedef struct _MIB_TCP6ROW_OWNER_PID |
-{ |
- UCHAR ucLocalAddr[16]; |
- DWORD dwLocalScopeId; |
- DWORD dwLocalPort; |
- UCHAR ucRemoteAddr[16]; |
- DWORD dwRemoteScopeId; |
- DWORD dwRemotePort; |
- DWORD dwState; |
- DWORD dwOwningPid; |
-} MIB_TCP6ROW_OWNER_PID, *PMIB_TCP6ROW_OWNER_PID; |
- |
-typedef struct _MIB_TCP6TABLE_OWNER_PID |
-{ |
- DWORD dwNumEntries; |
- MIB_TCP6ROW_OWNER_PID table[ANY_SIZE]; |
-} MIB_TCP6TABLE_OWNER_PID, *PMIB_TCP6TABLE_OWNER_PID; |
-#endif |
- |
-#ifndef __IPHLPAPI_H__ |
-typedef struct in6_addr { |
- union { |
- UCHAR Byte[16]; |
- USHORT Word[8]; |
- } u; |
-} IN6_ADDR, *PIN6_ADDR, FAR *LPIN6_ADDR; |
- |
- |
-typedef enum _UDP_TABLE_CLASS { |
- UDP_TABLE_BASIC, |
- UDP_TABLE_OWNER_PID, |
- UDP_TABLE_OWNER_MODULE |
-} UDP_TABLE_CLASS, *PUDP_TABLE_CLASS; |
- |
- |
-typedef struct _MIB_UDPROW_OWNER_PID { |
- DWORD dwLocalAddr; |
- DWORD dwLocalPort; |
- DWORD dwOwningPid; |
-} MIB_UDPROW_OWNER_PID, *PMIB_UDPROW_OWNER_PID; |
- |
-typedef struct _MIB_UDPTABLE_OWNER_PID |
-{ |
- DWORD dwNumEntries; |
- MIB_UDPROW_OWNER_PID table[ANY_SIZE]; |
-} MIB_UDPTABLE_OWNER_PID, *PMIB_UDPTABLE_OWNER_PID; |
-#endif |
-/* end of mingw support */ |
- |
-typedef struct _MIB_UDP6ROW_OWNER_PID { |
- UCHAR ucLocalAddr[16]; |
- DWORD dwLocalScopeId; |
- DWORD dwLocalPort; |
- DWORD dwOwningPid; |
-} MIB_UDP6ROW_OWNER_PID, *PMIB_UDP6ROW_OWNER_PID; |
- |
-typedef struct _MIB_UDP6TABLE_OWNER_PID |
-{ |
- DWORD dwNumEntries; |
- MIB_UDP6ROW_OWNER_PID table[ANY_SIZE]; |
-} MIB_UDP6TABLE_OWNER_PID, *PMIB_UDP6TABLE_OWNER_PID; |
- |
- |
-/* |
- * Return a list of network connections opened by a process |
- */ |
-static PyObject* |
-get_process_connections(PyObject* self, PyObject* args) |
-{ |
- static long null_address[4] = { 0, 0, 0, 0 }; |
- |
- unsigned long pid; |
- PyObject* connectionsList; |
- PyObject* connectionTuple; |
- typedef PSTR (NTAPI *_RtlIpv4AddressToStringA)(struct in_addr *, |
- PSTR /* __out_ecount(16) */); |
- _RtlIpv4AddressToStringA rtlIpv4AddressToStringA; |
- typedef PSTR (NTAPI *_RtlIpv6AddressToStringA)(struct in6_addr *, |
- PSTR /* __out_ecount(65) */); |
- _RtlIpv6AddressToStringA rtlIpv6AddressToStringA; |
- typedef DWORD (WINAPI *_GetExtendedTcpTable)(PVOID, PDWORD, BOOL, ULONG, |
- TCP_TABLE_CLASS, ULONG); |
- _GetExtendedTcpTable getExtendedTcpTable; |
- typedef DWORD (WINAPI *_GetExtendedUdpTable)(PVOID, PDWORD, BOOL, ULONG, |
- UDP_TABLE_CLASS, ULONG); |
- _GetExtendedUdpTable getExtendedUdpTable; |
- PVOID table; |
- DWORD tableSize; |
- PMIB_TCPTABLE_OWNER_PID tcp4Table; |
- PMIB_UDPTABLE_OWNER_PID udp4Table; |
- PMIB_TCP6TABLE_OWNER_PID tcp6Table; |
- PMIB_UDP6TABLE_OWNER_PID udp6Table; |
- ULONG i; |
- CHAR addressBufferLocal[65]; |
- PyObject* addressTupleLocal; |
- CHAR addressBufferRemote[65]; |
- PyObject* addressTupleRemote; |
- |
- if (!PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- if (pid_is_running(pid) == 0) { |
- return NoSuchProcess(); |
- } |
- |
- /* Import some functions. */ |
- { |
- HMODULE ntdll; |
- HMODULE iphlpapi; |
- |
- ntdll = LoadLibrary(TEXT("ntdll.dll")); |
- rtlIpv4AddressToStringA = (_RtlIpv4AddressToStringA)GetProcAddress(ntdll, |
- "RtlIpv4AddressToStringA"); |
- rtlIpv6AddressToStringA = (_RtlIpv6AddressToStringA)GetProcAddress(ntdll, |
- "RtlIpv6AddressToStringA"); |
- /* TODO: Check these two function pointers */ |
- |
- iphlpapi = LoadLibrary(TEXT("iphlpapi.dll")); |
- getExtendedTcpTable = (_GetExtendedTcpTable)GetProcAddress(iphlpapi, |
- "GetExtendedTcpTable"); |
- getExtendedUdpTable = (_GetExtendedUdpTable)GetProcAddress(iphlpapi, |
- "GetExtendedUdpTable"); |
- } |
- |
- if ((getExtendedTcpTable == NULL) || (getExtendedUdpTable == NULL)) { |
- PyErr_SetString(PyExc_NotImplementedError, |
- "feature not supported on this Windows version"); |
- return NULL; |
- } |
- |
- connectionsList = PyList_New(0); |
- |
- /* TCP IPv4 */ |
- |
- tableSize = 0; |
- getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET, |
- TCP_TABLE_OWNER_PID_ALL, 0); |
- |
- table = malloc(tableSize); |
- |
- if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET, |
- TCP_TABLE_OWNER_PID_ALL, 0) == 0) |
- { |
- tcp4Table = table; |
- |
- for (i = 0; i < tcp4Table->dwNumEntries; i++) |
- { |
- if (tcp4Table->table[i].dwOwningPid != pid) { |
- continue; |
- } |
- |
- if (tcp4Table->table[i].dwLocalAddr != 0 || |
- tcp4Table->table[i].dwLocalPort != 0) |
- { |
- struct in_addr addr; |
- |
- addr.S_un.S_addr = tcp4Table->table[i].dwLocalAddr; |
- rtlIpv4AddressToStringA(&addr, addressBufferLocal); |
- addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal, |
- BYTESWAP_USHORT(tcp4Table->table[i].dwLocalPort)); |
- } |
- else |
- { |
- addressTupleLocal = PyTuple_New(0); |
- } |
- |
- // On Windows <= XP, remote addr is filled even if socket |
- // is in LISTEN mode in which case we just ignore it. |
- if ((tcp4Table->table[i].dwRemoteAddr != 0 || |
- tcp4Table->table[i].dwRemotePort != 0) && |
- (tcp4Table->table[i].dwState != MIB_TCP_STATE_LISTEN)) |
- { |
- struct in_addr addr; |
- |
- addr.S_un.S_addr = tcp4Table->table[i].dwRemoteAddr; |
- rtlIpv4AddressToStringA(&addr, addressBufferRemote); |
- addressTupleRemote = Py_BuildValue("(si)", addressBufferRemote, |
- BYTESWAP_USHORT(tcp4Table->table[i].dwRemotePort)); |
- } |
- else |
- { |
- addressTupleRemote = PyTuple_New(0); |
- } |
- |
- connectionTuple = Py_BuildValue("(iiiNNs)", |
- -1, |
- AF_INET, |
- SOCK_STREAM, |
- addressTupleLocal, |
- addressTupleRemote, |
- state_to_string(tcp4Table->table[i].dwState) |
- ); |
- PyList_Append(connectionsList, connectionTuple); |
- } |
- } |
- |
- free(table); |
- |
- /* TCP IPv6 */ |
- |
- tableSize = 0; |
- getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET6, |
- TCP_TABLE_OWNER_PID_ALL, 0); |
- |
- table = malloc(tableSize); |
- |
- if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET6, |
- TCP_TABLE_OWNER_PID_ALL, 0) == 0) |
- { |
- tcp6Table = table; |
- |
- for (i = 0; i < tcp6Table->dwNumEntries; i++) |
- { |
- if (tcp6Table->table[i].dwOwningPid != pid) { |
- continue; |
- } |
- |
- if (memcmp(tcp6Table->table[i].ucLocalAddr, null_address, 16) != 0 || |
- tcp6Table->table[i].dwLocalPort != 0) |
- { |
- struct in6_addr addr; |
- |
- memcpy(&addr, tcp6Table->table[i].ucLocalAddr, 16); |
- rtlIpv6AddressToStringA(&addr, addressBufferLocal); |
- addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal, |
- BYTESWAP_USHORT(tcp6Table->table[i].dwLocalPort)); |
- } |
- else |
- { |
- addressTupleLocal = PyTuple_New(0); |
- } |
- |
- // On Windows <= XP, remote addr is filled even if socket |
- // is in LISTEN mode in which case we just ignore it. |
- if ((memcmp(tcp6Table->table[i].ucRemoteAddr, null_address, 16) != 0 || |
- tcp6Table->table[i].dwRemotePort != 0) && |
- (tcp6Table->table[i].dwState != MIB_TCP_STATE_LISTEN)) |
- { |
- struct in6_addr addr; |
- |
- memcpy(&addr, tcp6Table->table[i].ucRemoteAddr, 16); |
- rtlIpv6AddressToStringA(&addr, addressBufferRemote); |
- addressTupleRemote = Py_BuildValue("(si)", addressBufferRemote, |
- BYTESWAP_USHORT(tcp6Table->table[i].dwRemotePort)); |
- } |
- else |
- { |
- addressTupleRemote = PyTuple_New(0); |
- } |
- |
- connectionTuple = Py_BuildValue("(iiiNNs)", |
- -1, |
- AF_INET6, |
- SOCK_STREAM, |
- addressTupleLocal, |
- addressTupleRemote, |
- state_to_string(tcp6Table->table[i].dwState) |
- ); |
- PyList_Append(connectionsList, connectionTuple); |
- } |
- } |
- |
- free(table); |
- |
- /* UDP IPv4 */ |
- |
- tableSize = 0; |
- getExtendedUdpTable(NULL, &tableSize, FALSE, AF_INET, |
- UDP_TABLE_OWNER_PID, 0); |
- |
- table = malloc(tableSize); |
- |
- if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET, |
- UDP_TABLE_OWNER_PID, 0) == 0) |
- { |
- udp4Table = table; |
- |
- for (i = 0; i < udp4Table->dwNumEntries; i++) |
- { |
- if (udp4Table->table[i].dwOwningPid != pid) { |
- continue; |
- } |
- |
- if (udp4Table->table[i].dwLocalAddr != 0 || |
- udp4Table->table[i].dwLocalPort != 0) |
- { |
- struct in_addr addr; |
- |
- addr.S_un.S_addr = udp4Table->table[i].dwLocalAddr; |
- rtlIpv4AddressToStringA(&addr, addressBufferLocal); |
- addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal, |
- BYTESWAP_USHORT(udp4Table->table[i].dwLocalPort)); |
- } |
- else |
- { |
- addressTupleLocal = PyTuple_New(0); |
- } |
- |
- connectionTuple = Py_BuildValue("(iiiNNs)", |
- -1, |
- AF_INET, |
- SOCK_DGRAM, |
- addressTupleLocal, |
- PyTuple_New(0), |
- "" |
- ); |
- PyList_Append(connectionsList, connectionTuple); |
- } |
- } |
- |
- free(table); |
- |
- /* UDP IPv6 */ |
- |
- tableSize = 0; |
- getExtendedUdpTable(NULL, &tableSize, FALSE, AF_INET6, UDP_TABLE_OWNER_PID, 0); |
- |
- table = malloc(tableSize); |
- |
- if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET6, UDP_TABLE_OWNER_PID, 0) == 0) |
- { |
- udp6Table = table; |
- |
- for (i = 0; i < udp6Table->dwNumEntries; i++) |
- { |
- if (udp6Table->table[i].dwOwningPid != pid) { |
- continue; |
- } |
- |
- if (memcmp(udp6Table->table[i].ucLocalAddr, null_address, 16) != 0 || |
- udp6Table->table[i].dwLocalPort != 0) |
- { |
- struct in6_addr addr; |
- |
- memcpy(&addr, udp6Table->table[i].ucLocalAddr, 16); |
- rtlIpv6AddressToStringA(&addr, addressBufferLocal); |
- addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal, |
- BYTESWAP_USHORT(udp6Table->table[i].dwLocalPort)); |
- } |
- else |
- { |
- addressTupleLocal = PyTuple_New(0); |
- } |
- |
- connectionTuple = Py_BuildValue("(iiiNNs)", |
- -1, |
- AF_INET6, |
- SOCK_DGRAM, |
- addressTupleLocal, |
- PyTuple_New(0), |
- "" |
- ); |
- PyList_Append(connectionsList, connectionTuple); |
- } |
- } |
- |
- free(table); |
- |
- return connectionsList; |
-} |
- |
- |
-/* |
- * Get process priority as a Python integer. |
- */ |
-static PyObject* |
-get_process_priority(PyObject* self, PyObject* args) |
-{ |
- long pid; |
- DWORD priority; |
- HANDLE hProcess; |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- |
- hProcess = handle_from_pid(pid); |
- if (hProcess == NULL) { |
- return NULL; |
- } |
- |
- priority = GetPriorityClass(hProcess); |
- CloseHandle(hProcess); |
- if (priority == 0) { |
- PyErr_SetFromWindowsErr(0); |
- return NULL; |
- } |
- return Py_BuildValue("i", priority); |
-} |
- |
- |
-/* |
- * Set process priority. |
- */ |
-static PyObject* |
-set_process_priority(PyObject* self, PyObject* args) |
-{ |
- long pid; |
- int priority; |
- int retval; |
- HANDLE hProcess; |
- DWORD dwDesiredAccess = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION; |
- if (! PyArg_ParseTuple(args, "li", &pid, &priority)) { |
- return NULL; |
- } |
- |
- hProcess = handle_from_pid_waccess(pid, dwDesiredAccess); |
- if (hProcess == NULL) { |
- return NULL; |
- } |
- |
- retval = SetPriorityClass(hProcess, priority); |
- CloseHandle(hProcess); |
- if (retval == 0) { |
- PyErr_SetFromWindowsErr(0); |
- return NULL; |
- } |
- Py_INCREF(Py_None); |
- return Py_None; |
-} |
- |
- |
-/* |
- * Return a Python tuple referencing process I/O counters. |
- */ |
-static PyObject* |
-get_process_io_counters(PyObject* self, PyObject* args) |
-{ |
- DWORD pid; |
- HANDLE hProcess; |
- IO_COUNTERS IoCounters; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- if (pid == 0) { |
- return AccessDenied(); |
- } |
- hProcess = handle_from_pid(pid); |
- if (NULL == hProcess) { |
- return NULL; |
- } |
- if (! GetProcessIoCounters(hProcess, &IoCounters)) { |
- CloseHandle(hProcess); |
- return PyErr_SetFromWindowsErr(0); |
- } |
- CloseHandle(hProcess); |
- return Py_BuildValue("(KKKK)", IoCounters.ReadOperationCount, |
- IoCounters.WriteOperationCount, |
- IoCounters.ReadTransferCount, |
- IoCounters.WriteTransferCount); |
-} |
- |
- |
-/* |
- * Return True if one of the process threads is in a waiting or |
- * suspended status. |
- */ |
-static PyObject* |
-is_process_suspended(PyObject* self, PyObject* args) |
-{ |
- DWORD pid; |
- ULONG i; |
- PSYSTEM_PROCESS_INFORMATION process; |
- PVOID buffer; |
- |
- if (! PyArg_ParseTuple(args, "l", &pid)) { |
- return NULL; |
- } |
- if (get_process_info(pid, &process, &buffer) != 1) { |
- free(buffer); |
- return NULL; |
- } |
- if (pid_is_running(pid) == 0) { |
- free(buffer); |
- return NoSuchProcess(); |
- } |
- |
- for (i = 0; i < process->NumberOfThreads; i++) { |
- if (process->Threads[i].ThreadState != Waiting || |
- process->Threads[i].WaitReason != Suspended) |
- { |
- free(buffer); |
- Py_RETURN_FALSE; |
- } |
- } |
- free(buffer); |
- Py_RETURN_TRUE; |
-} |
- |
- |
-/* |
- * Return path's disk total and free as a Python tuple. |
- */ |
-static PyObject* |
-get_disk_usage(PyObject* self, PyObject* args) |
-{ |
- BOOL retval; |
- ULARGE_INTEGER _, total, free; |
- LPCTSTR path; |
- |
- if (! PyArg_ParseTuple(args, "s", &path)) { |
- return NULL; |
- } |
- |
- Py_BEGIN_ALLOW_THREADS |
- retval = GetDiskFreeSpaceEx(path, &_, &total, &free); |
- Py_END_ALLOW_THREADS |
- if (retval == 0) { |
- return PyErr_SetFromWindowsErr(0); |
- } |
- |
- return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); |
-} |
- |
- |
-/* |
- * Return disk partitions as a list of namedtuples. |
- */ |
-static PyObject* |
-win32_GetLogicalDriveStrings(PyObject* self, PyObject* args) |
-{ |
- DWORD num_bytes; |
- char drive_strings[255]; |
- char* drive_letter = drive_strings; |
- PyObject* py_retlist = PyList_New(0); |
- |
- Py_BEGIN_ALLOW_THREADS |
- num_bytes = GetLogicalDriveStrings(254, drive_letter); |
- Py_END_ALLOW_THREADS |
- |
- if (num_bytes == 0) { |
- return PyErr_SetFromWindowsErr(0); |
- } |
- |
- while (*drive_letter != 0) { |
- PyList_Append(py_retlist, Py_BuildValue("s", drive_letter)); |
- drive_letter = strchr(drive_letter, 0) +1; |
- } |
- |
- return py_retlist; |
-} |
- |
- |
-static PyObject* |
-win32_GetDriveType(PyObject* self, PyObject* args) |
-{ |
- LPCTSTR drive_letter; |
- int type; |
- char* type_str; |
- |
- if (! PyArg_ParseTuple(args, "s", &drive_letter)) { |
- return NULL; |
- } |
- |
- Py_BEGIN_ALLOW_THREADS |
- type = GetDriveType(drive_letter); |
- Py_END_ALLOW_THREADS |
- |
- switch (type) { |
- case DRIVE_UNKNOWN: |
- type_str = "unknown"; |
- break; |
- case DRIVE_NO_ROOT_DIR: |
- type_str = "unmounted"; |
- case DRIVE_REMOVABLE: |
- type_str = "removable"; |
- break; |
- case DRIVE_FIXED: |
- type_str = "fixed"; |
- break; |
- case DRIVE_REMOTE: |
- type_str = "remote"; |
- break; |
- case DRIVE_CDROM: |
- type_str = "cdrom"; |
- break; |
- case DRIVE_RAMDISK: |
- type_str = "ramdisk"; |
- break; |
- default: |
- type_str = "?"; |
- break; |
- } |
- |
- return Py_BuildValue("s", type_str); |
-} |
- |
- |
-// ------------------------ Python init --------------------------- |
- |
-static PyMethodDef |
-PsutilMethods[] = |
-{ |
- // --- per-process functions |
- |
- {"get_process_name", get_process_name, METH_VARARGS, |
- "Return process name"}, |
- {"get_process_cmdline", get_process_cmdline, METH_VARARGS, |
- "Return process cmdline as a list of cmdline arguments"}, |
- {"get_process_ppid", get_process_ppid, METH_VARARGS, |
- "Return process ppid as an integer"}, |
- {"kill_process", kill_process, METH_VARARGS, |
- "Kill the process identified by the given PID"}, |
- {"get_process_cpu_times", get_process_cpu_times, METH_VARARGS, |
- "Return tuple of user/kern time for the given PID"}, |
- {"get_process_create_time", get_process_create_time, METH_VARARGS, |
- "Return a float indicating the process create time expressed in " |
- "seconds since the epoch"}, |
- {"get_memory_info", get_memory_info, METH_VARARGS, |
- "Return a tuple of RSS/VMS memory information"}, |
- {"get_process_cwd", get_process_cwd, METH_VARARGS, |
- "Return process current working directory"}, |
- {"suspend_process", suspend_process, METH_VARARGS, |
- "Suspend a process"}, |
- {"resume_process", resume_process, METH_VARARGS, |
- "Resume a process"}, |
- {"get_process_open_files", get_process_open_files, METH_VARARGS, |
- "Return files opened by process"}, |
- {"get_process_username", get_process_username, METH_VARARGS, |
- "Return the username of a process"}, |
- {"get_process_connections", get_process_connections, METH_VARARGS, |
- "Return the network connections of a process"}, |
- {"get_process_num_threads", get_process_num_threads, METH_VARARGS, |
- "Return the network connections of a process"}, |
- {"get_process_threads", get_process_threads, METH_VARARGS, |
- "Return process threads information as a list of tuple"}, |
- {"process_wait", process_wait, METH_VARARGS, |
- "Wait for process to terminate and return its exit code."}, |
- {"get_process_priority", get_process_priority, METH_VARARGS, |
- "Return process priority."}, |
- {"set_process_priority", set_process_priority, METH_VARARGS, |
- "Set process priority."}, |
- {"get_process_io_counters", get_process_io_counters, METH_VARARGS, |
- "Get process I/O counters."}, |
- {"is_process_suspended", is_process_suspended, METH_VARARGS, |
- "Return True if one of the process threads is in a suspended state"}, |
- |
- // --- system-related functions |
- |
- {"get_pid_list", get_pid_list, METH_VARARGS, |
- "Returns a list of PIDs currently running on the system"}, |
- {"pid_exists", pid_exists, METH_VARARGS, |
- "Determine if the process exists in the current process list."}, |
- {"get_num_cpus", get_num_cpus, METH_VARARGS, |
- "Returns the number of CPUs on the system"}, |
- {"get_system_uptime", get_system_uptime, METH_VARARGS, |
- "Return system uptime"}, |
- {"get_system_phymem", get_system_phymem, METH_VARARGS, |
- "Return the total amount of physical memory, in bytes"}, |
- {"get_system_cpu_times", get_system_cpu_times, METH_VARARGS, |
- "Return system per-cpu times as a list of tuples"}, |
- {"get_disk_usage", get_disk_usage, METH_VARARGS, |
- "Return path's disk total and free as a Python tuple."}, |
- |
- // --- windows API bindings |
- {"win32_GetLogicalDriveStrings", win32_GetLogicalDriveStrings, METH_VARARGS, |
- "GetLogicalDriveStrings binding"}, |
- {"win32_GetDriveType", win32_GetDriveType, METH_VARARGS, |
- "GetDriveType binding"}, |
- {"win32_QueryDosDevice", win32_QueryDosDevice, METH_VARARGS, |
- "QueryDosDevice binding"}, |
- |
- {NULL, NULL, 0, NULL} |
-}; |
- |
- |
-struct module_state { |
- PyObject *error; |
-}; |
- |
-#if PY_MAJOR_VERSION >= 3 |
- #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) |
-#else |
- #define GETSTATE(m) (&_state) |
- static struct module_state _state; |
-#endif |
- |
-#if PY_MAJOR_VERSION >= 3 |
- |
- static int psutil_mswindows_traverse(PyObject *m, visitproc visit, void *arg) { |
- Py_VISIT(GETSTATE(m)->error); |
- return 0; |
- } |
- |
- static int psutil_mswindows_clear(PyObject *m) { |
- Py_CLEAR(GETSTATE(m)->error); |
- return 0; |
- } |
- |
- static struct PyModuleDef moduledef = { |
- PyModuleDef_HEAD_INIT, |
- "psutil_mswindows", |
- NULL, |
- sizeof(struct module_state), |
- PsutilMethods, |
- NULL, |
- psutil_mswindows_traverse, |
- psutil_mswindows_clear, |
- NULL |
- }; |
- |
-#define INITERROR return NULL |
- |
- PyObject* PyInit__psutil_mswindows(void) |
- |
-#else |
- #define INITERROR return |
- void init_psutil_mswindows(void) |
-#endif |
-{ |
- struct module_state *st = NULL; |
-#if PY_MAJOR_VERSION >= 3 |
- PyObject *module = PyModule_Create(&moduledef); |
-#else |
- PyObject *module = Py_InitModule("_psutil_mswindows", PsutilMethods); |
-#endif |
- |
- if (module == NULL) { |
- INITERROR; |
- } |
- |
- st = GETSTATE(module); |
- st->error = PyErr_NewException("_psutil_mswindow.Error", NULL, NULL); |
- if (st->error == NULL) { |
- Py_DECREF(module); |
- INITERROR; |
- } |
- |
- // Public constants |
- // http://msdn.microsoft.com/en-us/library/ms683211(v=vs.85).aspx |
- PyModule_AddIntConstant(module, "ABOVE_NORMAL_PRIORITY_CLASS", |
- ABOVE_NORMAL_PRIORITY_CLASS); |
- PyModule_AddIntConstant(module, "BELOW_NORMAL_PRIORITY_CLASS", |
- BELOW_NORMAL_PRIORITY_CLASS); |
- PyModule_AddIntConstant(module, "HIGH_PRIORITY_CLASS", |
- HIGH_PRIORITY_CLASS); |
- PyModule_AddIntConstant(module, "IDLE_PRIORITY_CLASS", |
- IDLE_PRIORITY_CLASS); |
- PyModule_AddIntConstant(module, "NORMAL_PRIORITY_CLASS", |
- NORMAL_PRIORITY_CLASS); |
- PyModule_AddIntConstant(module, "REALTIME_PRIORITY_CLASS", |
- REALTIME_PRIORITY_CLASS); |
- // private constants |
- PyModule_AddIntConstant(module, "INFINITE", INFINITE); |
- SetSeDebug(); |
- |
-#if PY_MAJOR_VERSION >= 3 |
- return module; |
-#endif |
-} |
- |
- |
- |