[PATCH v2 2/4] ntdll: Add NtQueryVirtualMemory(MemoryWorkingSetExInformation).

Andrew Wesie awesie at gmail.com
Fri Jan 24 14:19:38 CST 2020


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45667
Signed-off-by: Andrew Wesie <awesie at gmail.com>
---
 dlls/ntdll/virtual.c | 62 ++++++++++++++++++++++++++++++++++++++++++++
 include/winternl.h   | 21 ++++++++++++++-
 2 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index ad91cffd8f..477dd805b2 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -3134,6 +3134,65 @@ static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS get_working_set_ex( HANDLE process, LPCVOID addr,
+                                    MEMORY_WORKING_SET_EX_INFORMATION *info,
+                                    SIZE_T len, SIZE_T *res_len )
+{
+    char pagemap_path[32];
+    FILE *f;
+    MEMORY_WORKING_SET_EX_INFORMATION *p;
+    sigset_t sigset;
+
+    if (process != NtCurrentProcess())
+    {
+        FIXME( "(process=%p,addr=%p) Unimplemented information class: MemoryWorkingSetExInformation\n", process, addr );
+        return STATUS_INVALID_INFO_CLASS;
+    }
+
+    snprintf( pagemap_path, sizeof(pagemap_path), "/proc/%u/pagemap", getpid() );
+    f = fopen( pagemap_path, "rb" );
+    if (!f)
+    {
+        static int once;
+        if (!once++) WARN( "unable to open %s for MemoryWorkingSetExInformation\n", pagemap_path );
+    }
+
+    server_enter_uninterrupted_section( &csVirtual, &sigset );
+    for (p = info; (UINT_PTR)(p + 1) <= (UINT_PTR)info + len; p++)
+    {
+        BYTE vprot;
+        UINT64 pagemap;
+        struct file_view *view;
+
+        memset( &p->VirtualAttributes, 0, sizeof(p->VirtualAttributes) );
+
+        /* If we don't have pagemap information, default to invalid. */
+        if (!f || fseek( f, ((UINT_PTR)p->VirtualAddress >> 12) * sizeof(pagemap), SEEK_SET ) == -1 ||
+                fread( &pagemap, sizeof(pagemap), 1, f ) != 1)
+        {
+            pagemap = 0;
+        }
+
+        if ((view = VIRTUAL_FindView( p->VirtualAddress, 0 )) &&
+                get_committed_size( view, p->VirtualAddress, &vprot ) &&
+                (vprot & VPROT_COMMITTED))
+        {
+            p->VirtualAttributes.Valid = !(vprot & VPROT_GUARD) && (vprot & 0x0f) && (pagemap >> 63);
+            p->VirtualAttributes.Shared = !is_view_valloc( view ) && ((pagemap >> 61) & 1);
+            if (p->VirtualAttributes.Shared && p->VirtualAttributes.Valid)
+                p->VirtualAttributes.ShareCount = 1; /* FIXME */
+            if (p->VirtualAttributes.Valid)
+                p->VirtualAttributes.Win32Protection = VIRTUAL_GetWin32Prot( vprot, view->protect );
+        }
+    }
+    server_leave_uninterrupted_section( &csVirtual, &sigset );
+
+    if (f)
+        fclose( f );
+    if (res_len)
+        *res_len = (UINT_PTR)p - (UINT_PTR)info;
+    return STATUS_SUCCESS;
+}
 
 #define UNIMPLEMENTED_INFO_CLASS(c) \
     case c: \
@@ -3156,6 +3215,9 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
         case MemoryBasicInformation:
             return get_basic_memory_info( process, addr, buffer, len, res_len );
 
+        case MemoryWorkingSetExInformation:
+            return get_working_set_ex( process, addr, buffer, len, res_len );
+
         UNIMPLEMENTED_INFO_CLASS(MemoryWorkingSetList);
         UNIMPLEMENTED_INFO_CLASS(MemorySectionName);
         UNIMPLEMENTED_INFO_CLASS(MemoryBasicVlmInformation);
diff --git a/include/winternl.h b/include/winternl.h
index e5aed5acb1..ea6707714d 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -1051,7 +1051,8 @@ typedef enum _MEMORY_INFORMATION_CLASS {
     MemoryBasicInformation,
     MemoryWorkingSetList,
     MemorySectionName,
-    MemoryBasicVlmInformation
+    MemoryBasicVlmInformation,
+    MemoryWorkingSetExInformation
 } MEMORY_INFORMATION_CLASS;
 
 typedef struct _MEMORY_SECTION_NAME
@@ -1059,6 +1060,24 @@ typedef struct _MEMORY_SECTION_NAME
     UNICODE_STRING SectionFileName;
 } MEMORY_SECTION_NAME, *PMEMORY_SECTION_NAME;
 
+typedef union _MEMORY_WORKING_SET_EX_BLOCK {
+    ULONG_PTR Flags;
+    struct {
+        ULONG_PTR Valid : 1;
+        ULONG_PTR ShareCount : 3;
+        ULONG_PTR Win32Protection : 11;
+        ULONG_PTR Shared : 1;
+        ULONG_PTR Node : 6;
+        ULONG_PTR Locked : 1;
+        ULONG_PTR LargePage : 1;
+    } DUMMYSTRUCTNAME;
+} MEMORY_WORKING_SET_EX_BLOCK, *PMEMORY_WORKING_SET_EX_BLOCK;
+
+typedef struct _MEMORY_WORKING_SET_EX_INFORMATION {
+    PVOID                       VirtualAddress;
+    MEMORY_WORKING_SET_EX_BLOCK VirtualAttributes;
+} MEMORY_WORKING_SET_EX_INFORMATION, *PMEMORY_WORKING_SET_EX_INFORMATION;
+
 typedef enum _MUTANT_INFORMATION_CLASS
 {
     MutantBasicInformation
-- 
2.17.1




More information about the wine-devel mailing list