Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1394 / win / exe: use QueryFullProcessImageNameW to get the exe() #1413

Merged
merged 4 commits into from
Feb 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
*Bug tracker at https://github.com/giampaolo/psutil/issues*

5.5.2
=====

XXXX-XX-XX

**Bug fixes**

- 1394_: [Windows] Process name() and exe() may erronously return "Registry".
QueryFullProcessImageNameW is now used instead of GetProcessImageFileNameW
in order to prevent that.

5.5.1
=====

Expand Down
2 changes: 1 addition & 1 deletion psutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@
]
__all__.extend(_psplatform.__extra__all__)
__author__ = "Giampaolo Rodola'"
__version__ = "5.5.1"
__version__ = "5.5.2"
version_info = tuple([int(num) for num in __version__.split('.')])
AF_LINK = _psplatform.AF_LINK
POWER_TIME_UNLIMITED = _common.POWER_TIME_UNLIMITED
Expand Down
19 changes: 18 additions & 1 deletion psutil/_psutil_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -764,21 +764,38 @@ psutil_proc_exe(PyObject *self, PyObject *args) {
long pid;
HANDLE hProcess;
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;

// 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) {
// https://github.com/giampaolo/psutil/issues/1394
// 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));
}
Expand Down
43 changes: 33 additions & 10 deletions psutil/_pswindows.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,28 @@ class Priority(enum.IntEnum):
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
Expand Down Expand Up @@ -694,16 +716,17 @@ def name(self):

@wrap_exceptions
def exe(self):
# Note: os.path.exists(path) may return False even if the file
# is there, see:
# http://stackoverflow.com/questions/3112546/os-path-exists-lies

# see https://github.com/giampaolo/psutil/issues/414
# see https://github.com/giampaolo/psutil/issues/528
if self.pid in (0, 4):
raise AccessDenied(self.pid, self._name)
exe = cext.proc_exe(self.pid)
exe = convert_dos_path(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
Expand Down