summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2019-02-28 13:43:58 -0800
committerGitHub <noreply@github.com>2019-02-28 13:43:58 -0800
commite414895dc27a84482a2cb35f0c20f2c69530990d (patch)
tree97fb4194fa63dac0dbd82232012e90ad720fbdb3
parent17b9727300cb7dd226d88654315c67f55b172e0c (diff)
downloadpsutil-e414895dc27a84482a2cb35f0c20f2c69530990d.tar.gz
Restore Win-7 support on GIT master (5.5.1 was OK) (#1446)
-rw-r--r--DEVGUIDE.rst2
-rw-r--r--HISTORY.rst3
-rw-r--r--psutil/_psutil_windows.c8
-rw-r--r--psutil/_pswindows.py17
-rw-r--r--psutil/arch/windows/global.c2
-rw-r--r--psutil/arch/windows/process_info.c77
-rwxr-xr-xpsutil/tests/test_windows.py2
-rwxr-xr-xscripts/internal/winmake.py19
8 files changed, 68 insertions, 62 deletions
diff --git a/DEVGUIDE.rst b/DEVGUIDE.rst
index 1d1baf1f..df031bde 100644
--- a/DEVGUIDE.rst
+++ b/DEVGUIDE.rst
@@ -82,7 +82,7 @@ On Windows:
.. code-block:: bat
- set TSCRIPT=foo.py && make test
+ make test foo.py
Adding a new feature
====================
diff --git a/HISTORY.rst b/HISTORY.rst
index 2428f033..e2936268 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -33,9 +33,6 @@ XXXX-XX-XX
a 64-bit process in 32-bit-WoW mode. Now it raises AccessDenied.
- 1427_: [OSX] Process cmdline() and environ() may erroneously raise OSError
on failed malloc().
-- 1431_: [Windows] GetNativeSystemInfo is not used instead of GetSystemInfo in
- order to support WoW64 processes. Affected APIs are psutil.cpu_count(),
- and Process memory_maps() and memory_info_exe() ("uss" field).
- 1432_: [Windows] Process.memory_info_ex()'s USS memory is miscalculated
because we're not using the actual system PAGESIZE.
- 1439_: [NetBSD] Process.connections() may return incomplete results if using
diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c
index baf197b9..5c05ac38 100644
--- a/psutil/_psutil_windows.c
+++ b/psutil/_psutil_windows.c
@@ -106,12 +106,12 @@ psutil_get_num_cpus(int fail_on_err) {
}
else {
psutil_debug("GetActiveProcessorCount() not available; "
- "using GetNativeSystemInfo()");
+ "using GetSystemInfo()");
ncpus = (unsigned int)PSUTIL_SYSTEM_INFO.dwNumberOfProcessors;
- if ((ncpus == 0) && (fail_on_err == 1)) {
+ if ((ncpus <= 0) && (fail_on_err == 1)) {
PyErr_SetString(
PyExc_RuntimeError,
- "GetNativeSystemInfo() failed to retrieve CPU count");
+ "GetSystemInfo() failed to retrieve CPU count");
}
}
return ncpus;
@@ -584,13 +584,13 @@ psutil_proc_cmdline(PyObject *self, PyObject *args, PyObject *kwdict) {
if ((pid == 0) || (pid == 4))
return Py_BuildValue("[]");
- use_peb = (py_usepeb == Py_True);
pid_return = psutil_pid_is_running(pid);
if (pid_return == 0)
return NoSuchProcess("");
if (pid_return == -1)
return NULL;
+ use_peb = (py_usepeb == Py_True) ? 1 : 0;
return psutil_get_cmdline(pid, use_peb);
}
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index 0ab8afe4..3fcee450 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -731,13 +731,18 @@ class Process(object):
@wrap_exceptions
def cmdline(self):
- try:
+ if cext.WINVER >= cext.WINDOWS_8_1:
+ # PEB method detects cmdline changes but requires more
+ # privileges: https://github.com/giampaolo/psutil/pull/1398
+ try:
+ ret = cext.proc_cmdline(self.pid, use_peb=True)
+ except OSError as err:
+ if err.errno in ACCESS_DENIED_ERRSET:
+ ret = cext.proc_cmdline(self.pid, use_peb=False)
+ else:
+ raise
+ else:
ret = cext.proc_cmdline(self.pid, use_peb=True)
- except OSError as err:
- if err.errno in ACCESS_DENIED_ERRSET:
- ret = cext.proc_cmdline(self.pid, use_peb=False)
- else:
- raise
if PY3:
return ret
else:
diff --git a/psutil/arch/windows/global.c b/psutil/arch/windows/global.c
index 6134687d..a622b635 100644
--- a/psutil/arch/windows/global.c
+++ b/psutil/arch/windows/global.c
@@ -180,7 +180,7 @@ psutil_set_winver() {
static int
psutil_load_sysinfo() {
- GetNativeSystemInfo(&PSUTIL_SYSTEM_INFO);
+ GetSystemInfo(&PSUTIL_SYSTEM_INFO);
return 0;
}
diff --git a/psutil/arch/windows/process_info.c b/psutil/arch/windows/process_info.c
index 22b4ee91..946a01cb 100644
--- a/psutil/arch/windows/process_info.c
+++ b/psutil/arch/windows/process_info.c
@@ -735,24 +735,24 @@ error:
/*
- * Get process cmdline() by using NtQueryInformationProcess. This is
- * useful on Windows 8.1+ in order to get less ERROR_ACCESS_DENIED
- * errors when querying privileged PIDs.
+ * Get process cmdline by using NtQueryInformationProcess. This is a
+ * method alternative to PEB which is less likely to result in
+ * AccessDenied. Requires Windows 8.1+.
*/
static int
-psutil_get_cmdline_data(long pid, WCHAR **pdata, SIZE_T *psize) {
+psutil_cmdline_query_proc(long pid, WCHAR **pdata, SIZE_T *psize) {
HANDLE hProcess;
- ULONG ret_length = 4096;
+ ULONG bufLen = 0;
NTSTATUS status;
- char * cmdline_buffer = NULL;
- WCHAR * cmdline_buffer_wchar = NULL;
+ char * buffer = NULL;
+ WCHAR * bufWchar = NULL;
PUNICODE_STRING tmp = NULL;
- size_t string_size;
+ size_t size;
int ProcessCommandLineInformation = 60;
- cmdline_buffer = calloc(ret_length, 1);
- if (cmdline_buffer == NULL) {
- PyErr_NoMemory();
+ if (PSUTIL_WINVER < PSUTIL_WINDOWS_8_1) {
+ PyErr_SetString(
+ PyExc_RuntimeError, "requires Windows 8.1+");
goto error;
}
@@ -766,7 +766,7 @@ psutil_get_cmdline_data(long pid, WCHAR **pdata, SIZE_T *psize) {
ProcessCommandLineInformation,
NULL,
0,
- &ret_length);
+ &bufLen);
if (status != STATUS_BUFFER_OVERFLOW && \
status != STATUS_BUFFER_TOO_SMALL && \
status != STATUS_INFO_LENGTH_MISMATCH) {
@@ -774,13 +774,20 @@ psutil_get_cmdline_data(long pid, WCHAR **pdata, SIZE_T *psize) {
goto error;
}
+ // allocate memory
+ buffer = calloc(bufLen, 1);
+ if (buffer == NULL) {
+ PyErr_NoMemory();
+ goto error;
+ }
+
// get the cmdline
status = psutil_NtQueryInformationProcess(
hProcess,
ProcessCommandLineInformation,
- cmdline_buffer,
- ret_length,
- &ret_length
+ buffer,
+ bufLen,
+ &bufLen
);
if (! NT_SUCCESS(status)) {
PyErr_SetFromOSErrnoWithSyscall("NtQueryInformationProcess(withlen)");
@@ -788,23 +795,23 @@ psutil_get_cmdline_data(long pid, WCHAR **pdata, SIZE_T *psize) {
}
// build the string
- tmp = (PUNICODE_STRING)cmdline_buffer;
- string_size = wcslen(tmp->Buffer) + 1;
- cmdline_buffer_wchar = (WCHAR *)calloc(string_size, sizeof(WCHAR));
- if (cmdline_buffer_wchar == NULL) {
+ tmp = (PUNICODE_STRING)buffer;
+ size = wcslen(tmp->Buffer) + 1;
+ bufWchar = (WCHAR *)calloc(size, sizeof(WCHAR));
+ if (bufWchar == NULL) {
PyErr_NoMemory();
goto error;
}
- wcscpy_s(cmdline_buffer_wchar, string_size, tmp->Buffer);
- *pdata = cmdline_buffer_wchar;
- *psize = string_size * sizeof(WCHAR);
- free(cmdline_buffer);
+ wcscpy_s(bufWchar, size, tmp->Buffer);
+ *pdata = bufWchar;
+ *psize = size * sizeof(WCHAR);
+ free(buffer);
CloseHandle(hProcess);
return 0;
error:
- if (cmdline_buffer != NULL)
- free(cmdline_buffer);
+ if (buffer != NULL)
+ free(buffer);
if (hProcess != NULL)
CloseHandle(hProcess);
return -1;
@@ -827,24 +834,18 @@ psutil_get_cmdline(long pid, int use_peb) {
int func_ret;
/*
- By defaut, still use PEB (if command line params have been patched in
- the PEB, we will get the actual ones). Reading the PEB to get the
- command line parameters still seem to be the best method if somebody
- has tampered with the parameters after creating the process.
+ Reading the PEB to get the cmdline seem to be the best method if
+ somebody has tampered with the parameters after creating the process.
For instance, create a process as suspended, patch the command line
- in its PEB and unfreeze it.
- The process will use the "new" parameters whereas the system
- (with NtQueryInformationProcess) will give you the "old" ones
- See:
+ in its PEB and unfreeze it. It requires more privileges than
+ NtQueryInformationProcess though (the fallback):
- https://github.com/giampaolo/psutil/pull/1398
- https://blog.xpnsec.com/how-to-argue-like-cobalt-strike/
*/
- if (use_peb == 1) {
+ if (use_peb == 1)
func_ret = psutil_get_process_data(pid, KIND_CMDLINE, &data, &size);
- }
- else {
- func_ret = psutil_get_cmdline_data(pid, &data, &size);
- }
+ else
+ func_ret = psutil_cmdline_query_proc(pid, &data, &size);
if (func_ret != 0)
goto out;
diff --git a/psutil/tests/test_windows.py b/psutil/tests/test_windows.py
index ff63cd79..c98d892c 100755
--- a/psutil/tests/test_windows.py
+++ b/psutil/tests/test_windows.py
@@ -82,7 +82,7 @@ class TestCpuAPIs(unittest.TestCase):
def test_cpu_count_vs_GetSystemInfo(self):
# Will likely fail on many-cores systems:
# https://stackoverflow.com/questions/31209256
- sys_value = win32api.GetNativeSystemInfo()[5]
+ sys_value = win32api.GetSystemInfo()[5]
psutil_value = psutil.cpu_count()
self.assertEqual(sys_value, psutil_value)
diff --git a/scripts/internal/winmake.py b/scripts/internal/winmake.py
index cd26c67e..c35853c5 100755
--- a/scripts/internal/winmake.py
+++ b/scripts/internal/winmake.py
@@ -29,7 +29,7 @@ if APPVEYOR:
PYTHON = sys.executable
else:
PYTHON = os.getenv('PYTHON', sys.executable)
-TSCRIPT = os.getenv('TSCRIPT', 'psutil\\tests\\__main__.py')
+TEST_SCRIPT = 'psutil\\tests\\__main__.py'
GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py"
PY3 = sys.version_info[0] == 3
HERE = os.path.abspath(os.path.dirname(__file__))
@@ -350,9 +350,16 @@ def flake8():
@cmd
def test():
"""Run tests"""
+ try:
+ arg = sys.argv[2]
+ except IndexError:
+ arg = TEST_SCRIPT
+
install()
test_setup()
- sh("%s %s" % (PYTHON, TSCRIPT))
+ cmdline = "%s %s" % (PYTHON, arg)
+ safe_print(cmdline)
+ sh(cmdline)
@cmd
@@ -361,7 +368,7 @@ def coverage():
# Note: coverage options are controlled by .coveragerc file
install()
test_setup()
- sh("%s -m coverage run %s" % (PYTHON, TSCRIPT))
+ sh("%s -m coverage run %s" % (PYTHON, TEST_SCRIPT))
sh("%s -m coverage report" % PYTHON)
sh("%s -m coverage html" % PYTHON)
sh("%s -m webbrowser -t htmlcov/index.html" % PYTHON)
@@ -426,11 +433,7 @@ def test_contracts():
@cmd
def test_by_name():
"""Run test by name"""
- try:
- safe_print(sys.argv)
- name = sys.argv[2]
- except IndexError:
- sys.exit('second arg missing')
+ name = sys.argv[2]
install()
test_setup()
sh("%s -m unittest -v %s" % (PYTHON, name))