summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2020-01-31 15:28:45 -0800
committerGiampaolo Rodola <g.rodola@gmail.com>2020-01-31 15:28:45 -0800
commit607a8a831935b38e2625e749761aec2e530df764 (patch)
tree9477ed65e74b9ea29be82c6b4abb99d04c5c73d8
parentf4e337aa04dac93347118f488491941026ec7e4f (diff)
downloadpsutil-607a8a831935b38e2625e749761aec2e530df764.tar.gz
win / exe(): use NtQuerySystemInformation (no AD)
-rw-r--r--psutil/_psutil_windows.c60
-rw-r--r--psutil/_pswindows.py2
-rw-r--r--psutil/arch/windows/ntextapi.h8
3 files changed, 51 insertions, 19 deletions
diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c
index cabfe934..0be92503 100644
--- a/psutil/_psutil_windows.c
+++ b/psutil/_psutil_windows.c
@@ -446,34 +446,58 @@ psutil_proc_environ(PyObject *self, PyObject *args) {
/*
- * Return process executable path.
+ * Return process executable path. Works for all processes regardless of
+ * privilege.
*/
static PyObject *
psutil_proc_exe(PyObject *self, PyObject *args) {
DWORD pid;
- HANDLE hProcess;
- wchar_t exe[MAX_PATH];
- unsigned int size = sizeof(exe);
+ NTSTATUS status;
+ PVOID buffer;
+ ULONG bufferSize = 0x100;
+ SYSTEM_PROCESS_ID_INFORMATION processIdInfo;
+ PyObject *py_exe;
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
- hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION);
- if (NULL == hProcess)
- return NULL;
+ if (pid == 0)
+ return AccessDenied("forced for PID 0");
- memset(exe, 0, MAX_PATH);
- if (QueryFullProcessImageNameW(hProcess, 0, exe, &size) == 0) {
- // https://github.com/giampaolo/psutil/issues/1662
- if (GetLastError() == 0)
- AccessDenied("QueryFullProcessImageNameW (forced EPERM)");
- else
- PyErr_SetFromOSErrnoWithSyscall("QueryFullProcessImageNameW");
- CloseHandle(hProcess);
- return NULL;
+ buffer = MALLOC_ZERO(bufferSize);
+ processIdInfo.ProcessId = (HANDLE)(ULONG_PTR)pid;
+ processIdInfo.ImageName.Length = 0;
+ processIdInfo.ImageName.MaximumLength = (USHORT)bufferSize;
+ processIdInfo.ImageName.Buffer = buffer;
+
+ status = NtQuerySystemInformation(
+ SystemProcessIdInformation,
+ &processIdInfo,
+ sizeof(SYSTEM_PROCESS_ID_INFORMATION),
+ NULL);
+
+ if (status == STATUS_INFO_LENGTH_MISMATCH) {
+ // Required length is stored in MaximumLength.
+ FREE(buffer);
+ buffer = MALLOC_ZERO(processIdInfo.ImageName.MaximumLength);
+ processIdInfo.ImageName.Buffer = buffer;
+
+ status = NtQuerySystemInformation(
+ SystemProcessIdInformation,
+ &processIdInfo,
+ sizeof(SYSTEM_PROCESS_ID_INFORMATION),
+ NULL);
}
- CloseHandle(hProcess);
- return PyUnicode_FromWideChar(exe, wcslen(exe));
+
+ if (! NT_SUCCESS(status)) {
+ FREE(buffer);
+ return psutil_SetFromNTStatusErr(status, "NtQuerySystemInformation");
+ }
+
+ py_exe = PyUnicode_FromWideChar(processIdInfo.ImageName.Buffer,
+ processIdInfo.ImageName.Length / 2);
+ FREE(buffer);
+ return py_exe;
}
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index 3e14bc3c..e851f21e 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -757,7 +757,7 @@ class Process(object):
@wrap_exceptions
def exe(self):
exe = cext.proc_exe(self.pid)
- return py2_strencode(exe)
+ return convert_dos_path(exe)
@wrap_exceptions
@retry_error_partial_copy
diff --git a/psutil/arch/windows/ntextapi.h b/psutil/arch/windows/ntextapi.h
index b7b1c976..8cb00430 100644
--- a/psutil/arch/windows/ntextapi.h
+++ b/psutil/arch/windows/ntextapi.h
@@ -33,6 +33,8 @@ typedef LONG NTSTATUS;
#define ProcessIoPriority 33
#undef ProcessWow64Information
#define ProcessWow64Information 26
+#undef SystemProcessIdInformation
+#define SystemProcessIdInformation 88
// process suspend() / resume()
typedef enum _KTHREAD_STATE {
@@ -362,6 +364,12 @@ typedef struct _PSUTIL_PROCESS_WS_COUNTERS {
SIZE_T NumberOfShareablePages;
} PSUTIL_PROCESS_WS_COUNTERS, *PPSUTIL_PROCESS_WS_COUNTERS;
+// exe()
+typedef struct _SYSTEM_PROCESS_ID_INFORMATION {
+ HANDLE ProcessId;
+ UNICODE_STRING ImageName;
+} SYSTEM_PROCESS_ID_INFORMATION, *PSYSTEM_PROCESS_ID_INFORMATION;
+
// ====================================================================
// PEB structs for cmdline(), cwd(), environ()
// ====================================================================