From e5926872ba69cc5de807ac81afd2ba2ccb1a86a0 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Sun, 17 Feb 2019 10:00:58 -0800 Subject: add logic to support windows XP --- psutil/_psutil_windows.c | 21 +++++++++++++++++++-- psutil/_pswindows.py | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c index 7c94b816..30bd96cb 100644 --- a/psutil/_psutil_windows.c +++ b/psutil/_psutil_windows.c @@ -763,22 +763,39 @@ static PyObject * psutil_proc_exe(PyObject *self, PyObject *args) { long pid; HANDLE hProcess; - PDWORD size = MAX_PATH; wchar_t exe[MAX_PATH]; +#if (_WIN32_WINNT >= 0x0600) // >= Vista + PDWORD size = MAX_PATH; +#endif if (! PyArg_ParseTuple(args, "l", &pid)) return NULL; hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); if (NULL == hProcess) return NULL; - // before this was using GetProcessImageFileNameW see: + + // Here we differentiate between XP and Vista+ because + // QueryFullProcessImageNameW is better than GetProcessImageFileNameW + // (avoid using QueryDosDevice on the returned path), see: // https://github.com/giampaolo/psutil/issues/1394 +#if (_WIN32_WINNT >= 0x0600) // Windows >= Vista memset(exe, 0, MAX_PATH); if (QueryFullProcessImageNameW(hProcess, 0, exe, &size) == 0) { PyErr_SetFromWindowsErr(0); CloseHandle(hProcess); return NULL; } +#else // Windows XP + if (GetProcessImageFileNameW(hProcess, exe, MAX_PATH) == 0) { + // see: https://github.com/giampaolo/psutil/issues/1394 + if (GetLastError() == 0) { + PyErr_SetFromWindowsErr(ERROR_ACCESS_DENIED); + else + PyErr_SetFromWindowsErr(0); + CloseHandle(hProcess); + return NULL; + } +#endif CloseHandle(hProcess); return PyUnicode_FromWideChar(exe, wcslen(exe)); } diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py index 8aeb9263..0441b8a1 100644 --- a/psutil/_pswindows.py +++ b/psutil/_pswindows.py @@ -147,6 +147,28 @@ ZombieProcess = None AccessDenied = None TimeoutExpired = None +# More values at: https://stackoverflow.com/a/20804735/376587 +WIN_10 = (10, 0) +WIN_8 = (6, 2) +WIN_7 = (6, 1) +WIN_SERVER_2008 = (6, 0) +WIN_VISTA = (6, 0) +WIN_SERVER_2003 = (5, 2) +WIN_XP = (5, 1) + + +@lru_cache() +def get_winver(): + """Usage: + >>> if get_winver() <= WIN_VISTA: + ... ... + """ + wv = sys.getwindowsversion() + return (wv.major, wv.minor) + + +IS_WIN_XP = get_winver() < WIN_VISTA + # ===================================================================== # --- named tuples @@ -694,10 +716,18 @@ class Process(object): @wrap_exceptions def exe(self): - exe = cext.proc_exe(self.pid) - if not PY3: - exe = py2_strencode(exe) - return exe + # Dual implementation, see: + # https://github.com/giampaolo/psutil/pull/1413 + if not IS_WIN_XP: + exe = cext.proc_exe(self.pid) + else: + if self.pid in (0, 4): + # https://github.com/giampaolo/psutil/issues/414 + # https://github.com/giampaolo/psutil/issues/528 + raise AccessDenied(self.pid, self._name) + exe = cext.proc_exe(self.pid) + exe = convert_dos_path(exe) + return py2_strencode(exe) @wrap_exceptions def cmdline(self): -- cgit v1.2.1