| Index: third_party/psutil/psutil/arch/mswindows/process_handles.c
|
| diff --git a/third_party/psutil/psutil/arch/mswindows/process_handles.c b/third_party/psutil/psutil/arch/mswindows/process_handles.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fd272f2ac4089cf6a5c85c25467df97231e7c7d5
|
| --- /dev/null
|
| +++ b/third_party/psutil/psutil/arch/mswindows/process_handles.c
|
| @@ -0,0 +1,295 @@
|
| +#ifndef UNICODE
|
| +#define UNICODE
|
| +#endif
|
| +
|
| +#include <Python.h>
|
| +#include <windows.h>
|
| +#include <stdio.h>
|
| +#include "process_handles.h"
|
| +
|
| +#ifndef NT_SUCCESS
|
| + #define NT_SUCCESS(x) ((x) >= 0)
|
| +#endif
|
| +#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
|
| +
|
| +#define SystemHandleInformation 16
|
| +#define ObjectBasicInformation 0
|
| +#define ObjectNameInformation 1
|
| +#define ObjectTypeInformation 2
|
| +
|
| +
|
| +typedef LONG NTSTATUS;
|
| +
|
| +typedef struct _UNICODE_STRING {
|
| + USHORT Length;
|
| + USHORT MaximumLength;
|
| + PWSTR Buffer;
|
| +} UNICODE_STRING, *PUNICODE_STRING;
|
| +
|
| +typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
|
| + ULONG SystemInformationClass,
|
| + PVOID SystemInformation,
|
| + ULONG SystemInformationLength,
|
| + PULONG ReturnLength
|
| + );
|
| +
|
| +typedef NTSTATUS (NTAPI *_NtDuplicateObject)(
|
| + HANDLE SourceProcessHandle,
|
| + HANDLE SourceHandle,
|
| + HANDLE TargetProcessHandle,
|
| + PHANDLE TargetHandle,
|
| + ACCESS_MASK DesiredAccess,
|
| + ULONG Attributes,
|
| + ULONG Options
|
| + );
|
| +
|
| +typedef NTSTATUS (NTAPI *_NtQueryObject)(
|
| + HANDLE ObjectHandle,
|
| + ULONG ObjectInformationClass,
|
| + PVOID ObjectInformation,
|
| + ULONG ObjectInformationLength,
|
| + PULONG ReturnLength
|
| + );
|
| +
|
| +typedef struct _SYSTEM_HANDLE
|
| +{
|
| + ULONG ProcessId;
|
| + BYTE ObjectTypeNumber;
|
| + BYTE Flags;
|
| + USHORT Handle;
|
| + PVOID Object;
|
| + ACCESS_MASK GrantedAccess;
|
| +} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
|
| +
|
| +typedef struct _SYSTEM_HANDLE_INFORMATION
|
| +{
|
| + ULONG HandleCount;
|
| + SYSTEM_HANDLE Handles[1];
|
| +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
|
| +
|
| +typedef enum _POOL_TYPE
|
| +{
|
| + NonPagedPool,
|
| + PagedPool,
|
| + NonPagedPoolMustSucceed,
|
| + DontUseThisType,
|
| + NonPagedPoolCacheAligned,
|
| + PagedPoolCacheAligned,
|
| + NonPagedPoolCacheAlignedMustS
|
| +} POOL_TYPE, *PPOOL_TYPE;
|
| +
|
| +typedef struct _OBJECT_TYPE_INFORMATION
|
| +{
|
| + UNICODE_STRING Name;
|
| + ULONG TotalNumberOfObjects;
|
| + ULONG TotalNumberOfHandles;
|
| + ULONG TotalPagedPoolUsage;
|
| + ULONG TotalNonPagedPoolUsage;
|
| + ULONG TotalNamePoolUsage;
|
| + ULONG TotalHandleTableUsage;
|
| + ULONG HighWaterNumberOfObjects;
|
| + ULONG HighWaterNumberOfHandles;
|
| + ULONG HighWaterPagedPoolUsage;
|
| + ULONG HighWaterNonPagedPoolUsage;
|
| + ULONG HighWaterNamePoolUsage;
|
| + ULONG HighWaterHandleTableUsage;
|
| + ULONG InvalidAttributes;
|
| + GENERIC_MAPPING GenericMapping;
|
| + ULONG ValidAccess;
|
| + BOOLEAN SecurityRequired;
|
| + BOOLEAN MaintainHandleCount;
|
| + USHORT MaintainTypeList;
|
| + POOL_TYPE PoolType;
|
| + ULONG PagedPoolUsage;
|
| + ULONG NonPagedPoolUsage;
|
| +} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
|
| +
|
| +PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName)
|
| +{
|
| + return GetProcAddress(GetModuleHandleA(LibraryName), ProcName);
|
| +}
|
| +
|
| +
|
| +PyObject*
|
| +get_open_files(long pid, HANDLE processHandle)
|
| +{
|
| + _NtQuerySystemInformation NtQuerySystemInformation =
|
| + GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
|
| + _NtDuplicateObject NtDuplicateObject =
|
| + GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject");
|
| + _NtQueryObject NtQueryObject =
|
| + GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
|
| +
|
| + NTSTATUS status;
|
| + PSYSTEM_HANDLE_INFORMATION handleInfo;
|
| + ULONG handleInfoSize = 0x10000;
|
| +
|
| + ULONG i;
|
| + ULONG fileNameLength;
|
| + PyObject *filesList = Py_BuildValue("[]");
|
| + PyObject *arg = NULL;
|
| + PyObject *fileFromWchar = NULL;
|
| +
|
| +
|
| +
|
| + handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
|
| +
|
| + /* NtQuerySystemInformation won't give us the correct buffer size,
|
| + so we guess by doubling the buffer size. */
|
| + while ((status = NtQuerySystemInformation(
|
| + SystemHandleInformation,
|
| + handleInfo,
|
| + handleInfoSize,
|
| + NULL
|
| + )) == STATUS_INFO_LENGTH_MISMATCH)
|
| + handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2);
|
| +
|
| + /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */
|
| + if (!NT_SUCCESS(status)) {
|
| + //printf("NtQuerySystemInformation failed!\n");
|
| + return NULL;
|
| + }
|
| +
|
| + for (i = 0; i < handleInfo->HandleCount; i++)
|
| + {
|
| + SYSTEM_HANDLE handle = handleInfo->Handles[i];
|
| + HANDLE dupHandle = NULL;
|
| + POBJECT_TYPE_INFORMATION objectTypeInfo;
|
| + PVOID objectNameInfo;
|
| + UNICODE_STRING objectName;
|
| + ULONG returnLength;
|
| +
|
| + /* Check if this handle belongs to the PID the user specified. */
|
| + if (handle.ProcessId != pid)
|
| + continue;
|
| +
|
| + /* Skip handles with the following access codes as the next call
|
| + to NtDuplicateObject() or NtQueryObject() might hang forever. */
|
| + if((handle.GrantedAccess == 0x0012019f)
|
| + || (handle.GrantedAccess == 0x001a019f)
|
| + || (handle.GrantedAccess == 0x00120189)
|
| + || (handle.GrantedAccess == 0x00100000)) {
|
| + continue;
|
| + }
|
| +
|
| + /* Duplicate the handle so we can query it. */
|
| + if (!NT_SUCCESS(NtDuplicateObject(
|
| + processHandle,
|
| + handle.Handle,
|
| + GetCurrentProcess(),
|
| + &dupHandle,
|
| + 0,
|
| + 0,
|
| + 0
|
| + )))
|
| + {
|
| + //printf("[%#x] Error!\n", handle.Handle);
|
| + continue;
|
| + }
|
| +
|
| + /* Query the object type. */
|
| + objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
|
| + if (!NT_SUCCESS(NtQueryObject(
|
| + dupHandle,
|
| + ObjectTypeInformation,
|
| + objectTypeInfo,
|
| + 0x1000,
|
| + NULL
|
| + )))
|
| + {
|
| + //printf("[%#x] Error!\n", handle.Handle);
|
| + CloseHandle(dupHandle);
|
| + continue;
|
| + }
|
| +
|
| + objectNameInfo = malloc(0x1000);
|
| + if (!NT_SUCCESS(NtQueryObject(
|
| + dupHandle,
|
| + ObjectNameInformation,
|
| + objectNameInfo,
|
| + 0x1000,
|
| + &returnLength
|
| + )))
|
| + {
|
| + /* Reallocate the buffer and try again. */
|
| + objectNameInfo = realloc(objectNameInfo, returnLength);
|
| + if (!NT_SUCCESS(NtQueryObject(
|
| + dupHandle,
|
| + ObjectNameInformation,
|
| + objectNameInfo,
|
| + returnLength,
|
| + NULL
|
| + )))
|
| + {
|
| + /* We have the type name, so just display that.*/
|
| + /*
|
| + printf(
|
| + "[%#x] %.*S: (could not get name)\n",
|
| + handle.Handle,
|
| + objectTypeInfo->Name.Length / 2,
|
| + objectTypeInfo->Name.Buffer
|
| + );
|
| + */
|
| + free(objectTypeInfo);
|
| + free(objectNameInfo);
|
| + CloseHandle(dupHandle);
|
| + continue;
|
| +
|
| + }
|
| + }
|
| +
|
| + /* Cast our buffer into an UNICODE_STRING. */
|
| + objectName = *(PUNICODE_STRING)objectNameInfo;
|
| +
|
| + /* Print the information! */
|
| + if (objectName.Length)
|
| + {
|
| + /* The object has a name. Make sure it is a file otherwise
|
| + ignore it */
|
| + fileNameLength = objectName.Length / 2;
|
| + if (wcscmp(objectTypeInfo->Name.Buffer, L"File") == 0) {
|
| + //printf("%.*S\n", objectName.Length / 2, objectName.Buffer);
|
| + fileFromWchar = PyUnicode_FromWideChar(objectName.Buffer,
|
| + fileNameLength);
|
| + #if PY_MAJOR_VERSION >= 3
|
| + arg = Py_BuildValue("N", PyUnicode_AsUTF8String(fileFromWchar));
|
| + #else
|
| + arg = Py_BuildValue("N", PyUnicode_FromObject(fileFromWchar));
|
| + #endif
|
| + Py_XDECREF(fileFromWchar);
|
| + PyList_Append(filesList, arg);
|
| + Py_XDECREF(arg);
|
| + }
|
| + /*
|
| + printf(
|
| + "[%#x] %.*S: %.*S\n",
|
| + handle.Handle,
|
| + objectTypeInfo->Name.Length / 2,
|
| + objectTypeInfo->Name.Buffer,
|
| + objectName.Length / 2,
|
| + objectName.Buffer
|
| + );
|
| + */
|
| + }
|
| + else
|
| + {
|
| + /* Print something else. */
|
| + /*
|
| + printf(
|
| + "[%#x] %.*S: (unnamed)\n",
|
| + handle.Handle,
|
| + objectTypeInfo->Name.Length / 2,
|
| + objectTypeInfo->Name.Buffer
|
| + );
|
| + */
|
| + ;;
|
| + }
|
| + free(objectTypeInfo);
|
| + free(objectNameInfo);
|
| + CloseHandle(dupHandle);
|
| + }
|
| + free(handleInfo);
|
| + CloseHandle(processHandle);
|
| + return filesList;
|
| +}
|
| +
|
|
|