diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2020-01-31 15:28:45 -0800 |
---|---|---|
committer | Giampaolo Rodola <g.rodola@gmail.com> | 2020-01-31 15:28:45 -0800 |
commit | 607a8a831935b38e2625e749761aec2e530df764 (patch) | |
tree | 9477ed65e74b9ea29be82c6b4abb99d04c5c73d8 | |
parent | f4e337aa04dac93347118f488491941026ec7e4f (diff) | |
download | psutil-607a8a831935b38e2625e749761aec2e530df764.tar.gz |
win / exe(): use NtQuerySystemInformation (no AD)
-rw-r--r-- | psutil/_psutil_windows.c | 60 | ||||
-rw-r--r-- | psutil/_pswindows.py | 2 | ||||
-rw-r--r-- | psutil/arch/windows/ntextapi.h | 8 |
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() // ==================================================================== |