summaryrefslogtreecommitdiff
path: root/psutil/arch/windows/process_info.c
diff options
context:
space:
mode:
Diffstat (limited to 'psutil/arch/windows/process_info.c')
-rw-r--r--psutil/arch/windows/process_info.c140
1 files changed, 135 insertions, 5 deletions
diff --git a/psutil/arch/windows/process_info.c b/psutil/arch/windows/process_info.c
index df7ae9fb..ab1f844c 100644
--- a/psutil/arch/windows/process_info.c
+++ b/psutil/arch/windows/process_info.c
@@ -273,6 +273,18 @@ typedef NTSTATUS (NTAPI *_NtWow64ReadVirtualMemory64)(
IN ULONG64 Size,
OUT PULONG64 NumberOfBytesRead);
+typedef enum {
+ MemoryInformationBasic
+} MEMORY_INFORMATION_CLASS;
+
+typedef NTSTATUS (NTAPI *_NtWow64QueryVirtualMemory64)(
+ IN HANDLE ProcessHandle,
+ IN PVOID64 BaseAddress,
+ IN MEMORY_INFORMATION_CLASS MemoryInformationClass,
+ OUT PMEMORY_BASIC_INFORMATION64 MemoryInformation,
+ IN ULONG64 Size,
+ OUT PULONG64 ReturnLength OPTIONAL);
+
typedef struct {
PVOID Reserved1[2];
PVOID64 PebBaseAddress;
@@ -308,9 +320,66 @@ typedef struct {
} PEB64;
#endif
+/* Given a pointer into a process's memory, figure out how much data can be
+ * read from it. */
+static int psutil_get_process_region_size(HANDLE hProcess,
+ LPCVOID src,
+ SIZE_T *psize) {
+ MEMORY_BASIC_INFORMATION info;
+
+ if (!VirtualQueryEx(hProcess, src, &info, sizeof(info))) {
+ PyErr_SetFromWindowsErr(0);
+ return -1;
+ }
+
+ *psize = info.RegionSize - ((char*)src - (char*)info.BaseAddress);
+ return 0;
+}
+
+
+#ifndef _WIN64
+/* Given a pointer into a process's memory, figure out how much data can be
+ * read from it. */
+static int psutil_get_process_region_size64(HANDLE hProcess,
+ const PVOID64 src64,
+ PULONG64 psize) {
+ static _NtWow64QueryVirtualMemory64 NtWow64QueryVirtualMemory64 = NULL;
+ MEMORY_BASIC_INFORMATION64 info64;
+
+ if (NtWow64QueryVirtualMemory64 == NULL) {
+ NtWow64QueryVirtualMemory64 =
+ (_NtWow64QueryVirtualMemory64)GetProcAddress(
+ GetModuleHandleA("ntdll.dll"),
+ "NtWow64QueryVirtualMemory64");
+
+ if (NtWow64QueryVirtualMemory64 == NULL) {
+ PyErr_SetString(PyExc_NotImplementedError,
+ "NtWow64QueryVirtualMemory64 missing");
+ return -1;
+ }
+ }
+
+ if (!NT_SUCCESS(NtWow64QueryVirtualMemory64(
+ hProcess,
+ src64,
+ 0,
+ &info64,
+ sizeof(info64),
+ NULL))) {
+ PyErr_SetFromWindowsErr(0);
+ return -1;
+ }
+
+ *psize = info64.RegionSize - ((char*)src64 - (char*)info64.BaseAddress);
+ return 0;
+}
+#endif
+
+
enum psutil_process_data_kind {
KIND_CMDLINE,
KIND_CWD,
+ KIND_ENVIRON,
};
/* Get data from the process with the given pid. The data is returned in the
@@ -321,7 +390,8 @@ enum psutil_process_data_kind {
is returned, and an appropriate Python exception is set. */
static int psutil_get_process_data(long pid,
enum psutil_process_data_kind kind,
- WCHAR **pdata) {
+ WCHAR **pdata,
+ SIZE_T *psize) {
/* This function is quite complex because there are several cases to be
considered:
@@ -414,6 +484,9 @@ static int psutil_get_process_data(long pid,
src = UlongToPtr(procParameters32.CurrentDirectoryPath.Buffer);
size = procParameters32.CurrentDirectoryPath.Length;
break;
+ case KIND_ENVIRON:
+ src = UlongToPtr(procParameters32.env);
+ break;
}
} else
#else
@@ -433,8 +506,14 @@ static int psutil_get_process_data(long pid,
if (NtWow64QueryInformationProcess64 == NULL) {
NtWow64QueryInformationProcess64 =
(_NtQueryInformationProcess)GetProcAddress(
- GetModuleHandleA("ntdll.dll"),
- "NtWow64QueryInformationProcess64");
+ GetModuleHandleA("ntdll.dll"),
+ "NtWow64QueryInformationProcess64");
+
+ if (NtWow64QueryInformationProcess64 == NULL) {
+ PyErr_SetString(PyExc_NotImplementedError,
+ "NtWow64QueryInformationProcess64 missing");
+ goto error;
+ }
}
if (!NT_SUCCESS(NtWow64QueryInformationProcess64(
@@ -453,6 +532,12 @@ static int psutil_get_process_data(long pid,
(_NtWow64ReadVirtualMemory64)GetProcAddress(
GetModuleHandleA("ntdll.dll"),
"NtWow64ReadVirtualMemory64");
+
+ if (NtWow64ReadVirtualMemory64 == NULL) {
+ PyErr_SetString(PyExc_NotImplementedError,
+ "NtWow64ReadVirtualMemory64 missing");
+ goto error;
+ }
}
if (!NT_SUCCESS(NtWow64ReadVirtualMemory64(hProcess,
@@ -483,6 +568,9 @@ static int psutil_get_process_data(long pid,
src64 = procParameters64.CurrentDirectoryPath.Buffer,
size = procParameters64.CurrentDirectoryPath.Length;
break;
+ case KIND_ENVIRON:
+ src64 = procParameters64.env;
+ break;
}
} else
#endif
@@ -531,7 +619,26 @@ static int psutil_get_process_data(long pid,
src = procParameters.CurrentDirectoryPath.Buffer;
size = procParameters.CurrentDirectoryPath.Length;
break;
+ case KIND_ENVIRON:
+ src = procParameters.env;
+ break;
+ }
+ }
+
+ if (kind == KIND_ENVIRON) {
+#ifndef _WIN64
+ if (weAreWow64 && !theyAreWow64) {
+ ULONG64 size64;
+
+ if (psutil_get_process_region_size64(hProcess, src64, &size64) != 0)
+ goto error;
+
+ size = (SIZE_T)size64;
}
+ else
+#endif
+ if (psutil_get_process_region_size(hProcess, src, &size) != 0)
+ goto error;
}
buffer = calloc(size + 2, 1);
@@ -559,6 +666,7 @@ static int psutil_get_process_data(long pid,
}
*pdata = buffer;
+ *psize = size;
return 0;
@@ -578,12 +686,13 @@ PyObject *
psutil_get_cmdline(long pid) {
PyObject *ret = NULL;
WCHAR *data = NULL;
+ SIZE_T size;
PyObject *py_retlist = NULL;
PyObject *py_unicode = NULL;
LPWSTR *szArglist = NULL;
int nArgs, i;
- if (psutil_get_process_data(pid, KIND_CMDLINE, &data) != 0)
+ if (psutil_get_process_data(pid, KIND_CMDLINE, &data, &size) != 0)
goto out;
// attempt to parse the command line using Win32 API
@@ -622,8 +731,9 @@ out:
PyObject *psutil_get_cwd(long pid) {
PyObject *ret = NULL;
WCHAR *data = NULL;
+ SIZE_T size;
- if (psutil_get_process_data(pid, KIND_CWD, &data) != 0)
+ if (psutil_get_process_data(pid, KIND_CWD, &data, &size) != 0)
goto out;
// convert wchar array to a Python unicode string
@@ -635,6 +745,26 @@ out:
return ret;
}
+/*
+ * returns a Python string containing the environment variable data for the
+ * process with given pid or NULL on error.
+ */
+PyObject *psutil_get_environ(long pid) {
+ PyObject *ret = NULL;
+ WCHAR *data = NULL;
+ SIZE_T size;
+
+ if (psutil_get_process_data(pid, KIND_ENVIRON, &data, &size) != 0)
+ goto out;
+
+ // convert wchar array to a Python unicode string
+ ret = PyUnicode_FromWideChar(data, size / 2);
+
+out:
+ free(data);
+
+ return ret;
+}
#define PH_FIRST_PROCESS(Processes) ((PSYSTEM_PROCESS_INFORMATION)(Processes))
#define PH_NEXT_PROCESS(Process) ( \