Jinoh Kang : ntdll: Implement NtSetInformationVirtualMemory (intra-process case).

Alexandre Julliard julliard at winehq.org
Wed Jul 13 16:56:08 CDT 2022


Module: wine
Branch: master
Commit: 9d9075ce5d485a8e450c7781e221a03c7767d3d6
URL:    https://gitlab.winehq.org/wine/wine/-/commit/9d9075ce5d485a8e450c7781e221a03c7767d3d6

Author: Jinoh Kang <jinoh.kang.kr at gmail.com>
Date:   Fri Nov 26 13:11:50 2021 +0900

ntdll: Implement NtSetInformationVirtualMemory (intra-process case).

Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>

---

 dlls/ntdll/ntdll.spec     |  2 ++
 dlls/ntdll/unix/loader.c  |  1 +
 dlls/ntdll/unix/virtual.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++
 dlls/wow64/struct32.h     |  6 +++++
 dlls/wow64/syscall.h      |  1 +
 dlls/wow64/virtual.c      | 46 ++++++++++++++++++++++++++++++++++++
 6 files changed, 115 insertions(+)

diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 89b05728951..299d2195800 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -388,6 +388,7 @@
 @ stdcall -syscall NtSetInformationProcess(long long ptr long)
 @ stdcall -syscall NtSetInformationThread(long long ptr long)
 @ stdcall -syscall NtSetInformationToken(long long ptr long)
+@ stdcall -syscall NtSetInformationVirtualMemory(long long ptr ptr ptr long)
 @ stdcall -syscall NtSetIntervalProfile(long long)
 @ stdcall -syscall NtSetIoCompletion(ptr long long long long)
 @ stdcall -syscall NtSetLdtEntries(long int64 long int64)
@@ -1416,6 +1417,7 @@
 @ stdcall -private -syscall ZwSetInformationProcess(long long ptr long) NtSetInformationProcess
 @ stdcall -private -syscall ZwSetInformationThread(long long ptr long) NtSetInformationThread
 @ stdcall -private -syscall ZwSetInformationToken(long long ptr long) NtSetInformationToken
+@ stdcall -private -syscall ZwSetInformationVirtualMemory(long long ptr ptr ptr long) NtSetInformationVirtualMemory
 @ stdcall -private -syscall ZwSetIntervalProfile(long long) NtSetIntervalProfile
 @ stdcall -private -syscall ZwSetIoCompletion(ptr long long long long) NtSetIoCompletion
 @ stdcall -private -syscall ZwSetLdtEntries(long int64 long int64) NtSetLdtEntries
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index 2fd4acc06b9..f58a716d08c 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -310,6 +310,7 @@ static void * const syscalls[] =
     NtSetInformationProcess,
     NtSetInformationThread,
     NtSetInformationToken,
+    NtSetInformationVirtualMemory,
     NtSetIntervalProfile,
     NtSetIoCompletion,
     NtSetLdtEntries,
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index a93d5b4174a..96a5e095d16 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -4931,6 +4931,65 @@ NTSTATUS WINAPI NtAreMappedFilesTheSame(PVOID addr1, PVOID addr2)
 }
 
 
+static NTSTATUS prefetch_memory( HANDLE process, ULONG_PTR count,
+                                 PMEMORY_RANGE_ENTRY addresses, ULONG flags )
+{
+    ULONG_PTR i;
+    PVOID base;
+    SIZE_T size;
+    static unsigned int once;
+
+    if (!once++)
+    {
+        FIXME( "(process=%p,flags=%u) NtSetInformationVirtualMemory(VmPrefetchInformation) partial stub\n",
+                process, flags );
+    }
+
+    for (i = 0; i < count; i++)
+    {
+        if (!addresses[i].NumberOfBytes) return STATUS_INVALID_PARAMETER_4;
+    }
+
+    if (process != NtCurrentProcess()) return STATUS_SUCCESS;
+
+    for (i = 0; i < count; i++)
+    {
+        base = ROUND_ADDR( addresses[i].VirtualAddress, page_mask );
+        size = ROUND_SIZE( addresses[i].VirtualAddress, addresses[i].NumberOfBytes );
+        madvise( base, size, MADV_WILLNEED );
+    }
+
+    return STATUS_SUCCESS;
+}
+
+/***********************************************************************
+ *           NtSetInformationVirtualMemory   (NTDLL.@)
+ *           ZwSetInformationVirtualMemory   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtSetInformationVirtualMemory( HANDLE process,
+                                               VIRTUAL_MEMORY_INFORMATION_CLASS info_class,
+                                               ULONG_PTR count, PMEMORY_RANGE_ENTRY addresses,
+                                               PVOID ptr, ULONG size )
+{
+    TRACE("(%p, info_class=%d, %lu, %p, %p, %u)\n",
+          process, info_class, count, addresses, ptr, size);
+
+    switch (info_class)
+    {
+    case VmPrefetchInformation:
+        if (!ptr) return STATUS_INVALID_PARAMETER_5;
+        if (size != sizeof(ULONG)) return STATUS_INVALID_PARAMETER_6;
+        if (!count) return STATUS_INVALID_PARAMETER_3;
+        return prefetch_memory( process, count, addresses, *(ULONG *)ptr );
+
+    default:
+        FIXME("(%p,info_class=%d,%lu,%p,%p,%u) Unknown information class\n",
+              process, info_class, count, addresses, ptr, size);
+        return STATUS_INVALID_PARAMETER_2;
+    }
+}
+
+
 /**********************************************************************
  *           NtFlushInstructionCache  (NTDLL.@)
  */
diff --git a/dlls/wow64/struct32.h b/dlls/wow64/struct32.h
index b096c8d587b..91acc26436f 100644
--- a/dlls/wow64/struct32.h
+++ b/dlls/wow64/struct32.h
@@ -650,6 +650,12 @@ typedef struct
     ULONG                       Reserved4;
 } SYSTEM_EXTENDED_THREAD_INFORMATION32;
 
+typedef struct
+{
+    ULONG VirtualAddress;
+    ULONG NumberOfBytes;
+} MEMORY_RANGE_ENTRY32;
+
 struct __server_iovec32
 {
     ULONG        ptr;
diff --git a/dlls/wow64/syscall.h b/dlls/wow64/syscall.h
index bd107ce0ef5..65fbca89f4f 100644
--- a/dlls/wow64/syscall.h
+++ b/dlls/wow64/syscall.h
@@ -211,6 +211,7 @@
     SYSCALL_ENTRY( NtSetInformationProcess ) \
     SYSCALL_ENTRY( NtSetInformationThread ) \
     SYSCALL_ENTRY( NtSetInformationToken ) \
+    SYSCALL_ENTRY( NtSetInformationVirtualMemory ) \
     SYSCALL_ENTRY( NtSetIntervalProfile ) \
     SYSCALL_ENTRY( NtSetIoCompletion ) \
     SYSCALL_ENTRY( NtSetLdtEntries ) \
diff --git a/dlls/wow64/virtual.c b/dlls/wow64/virtual.c
index c21464857fa..8b69432829d 100644
--- a/dlls/wow64/virtual.c
+++ b/dlls/wow64/virtual.c
@@ -33,6 +33,21 @@
 WINE_DEFAULT_DEBUG_CHANNEL(wow);
 
 
+static MEMORY_RANGE_ENTRY *memory_range_entry_array_32to64( const MEMORY_RANGE_ENTRY32 *addresses32,
+                                                            ULONG count )
+{
+    MEMORY_RANGE_ENTRY *addresses = Wow64AllocateTemp( sizeof(MEMORY_RANGE_ENTRY) * count );
+    ULONG i;
+
+    for (i = 0; i < count; i++)
+    {
+        addresses[i].VirtualAddress = ULongToPtr( addresses32[i].VirtualAddress );
+        addresses[i].NumberOfBytes = addresses32[i].NumberOfBytes;
+    }
+
+    return addresses;
+}
+
 /**********************************************************************
  *           wow64_NtAllocateVirtualMemory
  */
@@ -470,6 +485,37 @@ NTSTATUS WINAPI wow64_NtResetWriteWatch( UINT *args )
 }
 
 
+/**********************************************************************
+ *           wow64_NtSetInformationVirtualMemory
+ */
+NTSTATUS WINAPI wow64_NtSetInformationVirtualMemory( UINT *args )
+{
+    HANDLE process = get_handle( &args );
+    VIRTUAL_MEMORY_INFORMATION_CLASS info_class = get_ulong( &args );
+    ULONG count = get_ulong( &args );
+    MEMORY_RANGE_ENTRY32 *addresses32 = get_ptr( &args );
+    PVOID ptr = get_ptr( &args );
+    ULONG len = get_ulong( &args );
+
+    MEMORY_RANGE_ENTRY *addresses;
+
+    if (!count) return STATUS_INVALID_PARAMETER_3;
+    addresses = memory_range_entry_array_32to64( addresses32, count );
+
+    switch (info_class)
+    {
+    case VmPrefetchInformation:
+        break;
+    default:
+        FIXME( "(%p,info_class=%u,%lu,%p,%p,%lu): not implemented\n",
+               process, info_class, count, addresses32, ptr, len );
+        return STATUS_INVALID_PARAMETER_2;
+    }
+
+    return NtSetInformationVirtualMemory( process, info_class, count, addresses, ptr, len );
+}
+
+
 /**********************************************************************
  *           wow64_NtSetLdtEntries
  */




More information about the wine-cvs mailing list