[PATCH 1/2] ntdll: Add a partial implementation of NtMapViewOfSectionEx().

Nikolay Sivov nsivov at codeweavers.com
Wed May 4 06:55:35 CDT 2022


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/ntdll/ntdll.spec      |   2 +
 dlls/ntdll/tests/virtual.c | 149 +++++++++++++++++++++++++++++++++++++
 dlls/ntdll/unix/loader.c   |   1 +
 dlls/ntdll/unix/virtual.c  |  12 +++
 dlls/wow64/syscall.h       |   1 +
 dlls/wow64/virtual.c       |  34 +++++++++
 include/winternl.h         |   1 +
 7 files changed, 200 insertions(+)

diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index ba29b21d61d..a7a39a0bce2 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -253,6 +253,7 @@
 # @ stub NtMapUserPhysicalPages
 # @ stub NtMapUserPhysicalPagesScatter
 @ stdcall -syscall NtMapViewOfSection(long long ptr long long ptr ptr long long long)
+@ stdcall -syscall NtMapViewOfSectionEx(long long ptr ptr ptr long long ptr long)
 # @ stub NtModifyBootEntry
 @ stdcall -syscall NtNotifyChangeDirectoryFile(long long ptr ptr ptr ptr long long long)
 @ stdcall -syscall NtNotifyChangeKey(long long ptr ptr ptr long long ptr long long)
@@ -1279,6 +1280,7 @@
 # @ stub ZwMapUserPhysicalPages
 # @ stub ZwMapUserPhysicalPagesScatter
 @ stdcall -private -syscall ZwMapViewOfSection(long long ptr long long ptr ptr long long long) NtMapViewOfSection
+@ stdcall -private -syscall ZwMapViewOfSectionEx(long long ptr ptr ptr long long ptr long) NtMapViewOfSectionEx
 # @ stub ZwModifyBootEntry
 @ stdcall -private -syscall ZwNotifyChangeDirectoryFile(long long ptr ptr ptr ptr long long long) NtNotifyChangeDirectoryFile
 @ stdcall -private -syscall ZwNotifyChangeKey(long long ptr ptr ptr long long ptr long long) NtNotifyChangeKey
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c
index 30a97ba9d94..aeef2ed8fb9 100644
--- a/dlls/ntdll/tests/virtual.c
+++ b/dlls/ntdll/tests/virtual.c
@@ -39,6 +39,9 @@ static void * (WINAPI *pRtlFindExportedRoutineByName)(HMODULE,const char*);
 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
 static NTSTATUS (WINAPI *pNtAllocateVirtualMemoryEx)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG,
                                                      MEM_EXTENDED_PARAMETER *, ULONG);
+static NTSTATUS (WINAPI *pNtMapViewOfSectionEx)(HANDLE, HANDLE, PVOID *, const LARGE_INTEGER *, SIZE_T *,
+        ULONG, ULONG, MEM_EXTENDED_PARAMETER *, ULONG);
+
 static const BOOL is_win64 = sizeof(void*) != sizeof(int);
 static BOOL is_wow64;
 
@@ -908,6 +911,150 @@ static void test_NtMapViewOfSection(void)
     CloseHandle(process);
 }
 
+static void test_NtMapViewOfSectionEx(void)
+{
+    static const char testfile[] = "testfile.xxx";
+    static const char data[] = "test data for NtMapViewOfSectionEx";
+    char buffer[sizeof(data)];
+    HANDLE file, mapping, process;
+    DWORD status, written;
+    SIZE_T size, result;
+    LARGE_INTEGER offset;
+    void *ptr, *ptr2;
+    BOOL ret;
+
+    if (!pNtMapViewOfSectionEx)
+    {
+        win_skip("NtMapViewOfSectionEx() is not supported.\n");
+        return;
+    }
+
+    if (!pIsWow64Process || !pIsWow64Process(NtCurrentProcess(), &is_wow64)) is_wow64 = FALSE;
+
+    file = CreateFileA(testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+    ok(file != INVALID_HANDLE_VALUE, "Failed to create test file\n");
+    WriteFile(file, data, sizeof(data), &written, NULL);
+    SetFilePointer(file, 4096, NULL, FILE_BEGIN);
+    SetEndOfFile(file);
+
+    /* read/write mapping */
+
+    mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, 4096, NULL);
+    ok(mapping != 0, "CreateFileMapping failed\n");
+
+    process = create_target_process("sleep");
+    ok(process != NULL, "Can't start process\n");
+
+    ptr = NULL;
+    size = 0;
+    offset.QuadPart = 0;
+    status = pNtMapViewOfSectionEx(mapping, process, &ptr, &offset, &size, 0, PAGE_READWRITE, NULL, 0);
+    ok(status == STATUS_SUCCESS, "Unexpected status %08lx\n", status);
+    ok(!((ULONG_PTR)ptr & 0xffff), "returned memory %p is not aligned to 64k\n", ptr);
+
+    ret = ReadProcessMemory(process, ptr, buffer, sizeof(buffer), &result);
+    ok(ret, "ReadProcessMemory failed\n");
+    ok(result == sizeof(buffer), "ReadProcessMemory didn't read all data (%Ix)\n", result);
+    ok(!memcmp(buffer, data, sizeof(buffer)), "Wrong data read\n");
+
+    /* mapping at the same page conflicts */
+    ptr2 = ptr;
+    size = 0;
+    offset.QuadPart = 0;
+    status = pNtMapViewOfSectionEx(mapping, process, &ptr2, &offset, &size, 0, PAGE_READWRITE, NULL, 0);
+    ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx\n", status);
+
+    /* offset has to be aligned */
+    ptr2 = ptr;
+    size = 0;
+    offset.QuadPart = 1;
+    status = pNtMapViewOfSectionEx(mapping, process, &ptr2, &offset, &size, 0, PAGE_READWRITE, NULL, 0);
+    ok(status == STATUS_MAPPED_ALIGNMENT, "Unexpected status %08lx\n", status);
+
+    /* ptr has to be aligned */
+    ptr2 = (char *)ptr + 42;
+    size = 0;
+    offset.QuadPart = 0;
+    status = pNtMapViewOfSectionEx(mapping, process, &ptr2, &offset, &size, 0, PAGE_READWRITE, NULL, 0);
+    ok(status == STATUS_MAPPED_ALIGNMENT, "Unexpected status %08lx\n", status);
+
+    /* still not 64k aligned */
+    ptr2 = (char *)ptr + 0x1000;
+    size = 0;
+    offset.QuadPart = 0;
+    status = pNtMapViewOfSectionEx(mapping, process, &ptr2, &offset, &size, 0, PAGE_READWRITE, NULL, 0);
+    ok(status == STATUS_MAPPED_ALIGNMENT, "Unexpected status %08lx\n", status);
+
+    if (!is_win64 && !is_wow64)
+    {
+        /* new memory region conflicts with previous mapping */
+        ptr2 = ptr;
+        size = 0;
+        offset.QuadPart = 0;
+        status = pNtMapViewOfSectionEx(mapping, process, &ptr2, &offset, &size, AT_ROUND_TO_PAGE, PAGE_READWRITE, NULL, 0);
+        ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx\n", status);
+
+        ptr2 = (char *)ptr + 42;
+        size = 0;
+        offset.QuadPart = 0;
+        status = pNtMapViewOfSectionEx(mapping, process, &ptr2, &offset, &size, AT_ROUND_TO_PAGE, PAGE_READWRITE, NULL, 0);
+        ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx\n", status);
+
+        /* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
+        ptr2 = (char *)ptr + 0x1000;
+        size = 0;
+        offset.QuadPart = 0;
+        status = pNtMapViewOfSectionEx(mapping, process, &ptr2, &offset, &size, AT_ROUND_TO_PAGE, PAGE_READWRITE, NULL, 0);
+        ok(status == STATUS_SUCCESS, "Unexpected status %08lx\n", status);
+        ok((char *)ptr2 == (char *)ptr + 0x1000,
+           "expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2);
+        status = NtUnmapViewOfSection(process, ptr2);
+        ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08lx\n", status);
+
+        /* the address is rounded down if not on a page boundary */
+        ptr2 = (char *)ptr + 0x1001;
+        size = 0;
+        offset.QuadPart = 0;
+        status = pNtMapViewOfSectionEx(mapping, process, &ptr2, &offset, &size, AT_ROUND_TO_PAGE, PAGE_READWRITE, NULL, 0);
+        ok(status == STATUS_SUCCESS, "Unexpected status %08lx\n", status);
+        ok((char *)ptr2 == (char *)ptr + 0x1000,
+           "expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2);
+        status = NtUnmapViewOfSection(process, ptr2);
+        ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08lx\n", status);
+
+        ptr2 = (char *)ptr + 0x2000;
+        size = 0;
+        offset.QuadPart = 0;
+        status = pNtMapViewOfSectionEx(mapping, process, &ptr2, &offset, &size, AT_ROUND_TO_PAGE, PAGE_READWRITE, NULL, 0);
+        ok(status == STATUS_SUCCESS, "Unexpected status %08lx\n", status);
+        ok((char *)ptr2 == (char *)ptr + 0x2000,
+           "expected address %p, got %p\n", (char *)ptr + 0x2000, ptr2);
+        status = NtUnmapViewOfSection(process, ptr2);
+        ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08lx\n", status);
+    }
+    else
+    {
+        ptr2 = (char *)ptr + 0x1000;
+        size = 0;
+        offset.QuadPart = 0;
+        status = pNtMapViewOfSectionEx(mapping, process, &ptr2, &offset, &size, AT_ROUND_TO_PAGE, PAGE_READWRITE, NULL, 0);
+        todo_wine
+        ok(status == STATUS_INVALID_PARAMETER_9 || status == STATUS_INVALID_PARAMETER,
+           "NtMapViewOfSection returned %08lx\n", status);
+    }
+
+    status = NtUnmapViewOfSection(process, ptr);
+    ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08lx\n", status);
+
+    NtClose(mapping);
+
+    CloseHandle(file);
+    DeleteFileA(testfile);
+
+    TerminateProcess(process, 0);
+    CloseHandle(process);
+}
+
 #define SUPPORTED_XSTATE_FEATURES ((1 << XSTATE_LEGACY_FLOATING_POINT) | (1 << XSTATE_LEGACY_SSE) | (1 << XSTATE_AVX))
 
 static void test_user_shared_data(void)
@@ -1160,6 +1307,7 @@ START_TEST(virtual)
     pRtlFindExportedRoutineByName = (void *)GetProcAddress(mod, "RtlFindExportedRoutineByName");
     pRtlGetEnabledExtendedFeatures = (void *)GetProcAddress(mod, "RtlGetEnabledExtendedFeatures");
     pNtAllocateVirtualMemoryEx = (void *)GetProcAddress(mod, "NtAllocateVirtualMemoryEx");
+    pNtMapViewOfSectionEx = (void *)GetProcAddress(mod, "NtMapViewOfSectionEx");
 
     NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL);
     trace("system page size %#lx\n", sbi.PageSize);
@@ -1169,6 +1317,7 @@ START_TEST(virtual)
     test_NtAllocateVirtualMemory();
     test_RtlCreateUserStack();
     test_NtMapViewOfSection();
+    test_NtMapViewOfSectionEx();
     test_user_shared_data();
     test_syscalls();
 }
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index d1c42ddc0f3..cad760a1445 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -207,6 +207,7 @@ static void * const syscalls[] =
     NtLockVirtualMemory,
     NtMakeTemporaryObject,
     NtMapViewOfSection,
+    NtMapViewOfSectionEx,
     NtNotifyChangeDirectoryFile,
     NtNotifyChangeKey,
     NtNotifyChangeMultipleKeys,
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 94b300c5057..02478cceb06 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -4536,6 +4536,18 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
                                 offset_ptr, size_ptr, alloc_type, protect );
 }
 
+/***********************************************************************
+ *             NtMapViewOfSectionEx   (NTDLL.@)
+ *             ZwMapViewOfSectionEx   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr_ptr, const LARGE_INTEGER *offset_ptr,
+        SIZE_T *size_ptr, ULONG alloc_type, ULONG protect, MEM_EXTENDED_PARAMETER *params, ULONG params_count )
+{
+    if (params)
+        FIXME("Ignoring extended parameters.\n");
+
+    return NtMapViewOfSection( handle, process, addr_ptr, 0, 0, offset_ptr, size_ptr, ViewShare, alloc_type, protect );
+}
 
 /***********************************************************************
  *             NtUnmapViewOfSection   (NTDLL.@)
diff --git a/dlls/wow64/syscall.h b/dlls/wow64/syscall.h
index a3af9174c49..3b364d909d7 100644
--- a/dlls/wow64/syscall.h
+++ b/dlls/wow64/syscall.h
@@ -108,6 +108,7 @@
     SYSCALL_ENTRY( NtLockVirtualMemory ) \
     SYSCALL_ENTRY( NtMakeTemporaryObject ) \
     SYSCALL_ENTRY( NtMapViewOfSection ) \
+    SYSCALL_ENTRY( NtMapViewOfSectionEx ) \
     SYSCALL_ENTRY( NtNotifyChangeDirectoryFile ) \
     SYSCALL_ENTRY( NtNotifyChangeKey ) \
     SYSCALL_ENTRY( NtNotifyChangeMultipleKeys ) \
diff --git a/dlls/wow64/virtual.c b/dlls/wow64/virtual.c
index e89373f4239..61c84e5d7be 100644
--- a/dlls/wow64/virtual.c
+++ b/dlls/wow64/virtual.c
@@ -287,6 +287,40 @@ NTSTATUS WINAPI wow64_NtMapViewOfSection( UINT *args )
     return status;
 }
 
+/**********************************************************************
+ *           wow64_NtMapViewOfSectionEx
+ */
+NTSTATUS WINAPI wow64_NtMapViewOfSectionEx( UINT *args )
+{
+    HANDLE handle = get_handle( &args );
+    HANDLE process = get_handle( &args );
+    ULONG *addr32 = get_ptr( &args );
+    const LARGE_INTEGER *offset = get_ptr( &args );
+    ULONG *size32 = get_ptr( &args );
+    ULONG alloc = get_ulong( &args );
+    ULONG protect = get_ulong( &args );
+    MEM_EXTENDED_PARAMETER *params = get_ptr( &args );
+    ULONG params_count = get_ulong( &args );
+
+    void *addr;
+    SIZE_T size;
+    NTSTATUS status;
+
+    status = NtMapViewOfSectionEx( handle, process, addr_32to64( &addr, addr32 ), offset, size_32to64( &size, size32 ), alloc,
+            protect, params, params_count );
+    if (NT_SUCCESS(status))
+    {
+        SECTION_IMAGE_INFORMATION info;
+
+        if (!NtQuerySection( handle, SectionImageInformation, &info, sizeof(info), NULL ))
+        {
+            if (info.Machine == current_machine) init_image_mapping( addr );
+        }
+        put_addr( addr32, addr );
+        put_size( size32, size );
+    }
+    return status;
+}
 
 /**********************************************************************
  *           wow64_NtProtectVirtualMemory
diff --git a/include/winternl.h b/include/winternl.h
index b4942d86b4c..1d358fc0b2d 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -4007,6 +4007,7 @@ NTSYSAPI NTSTATUS  WINAPI NtLockFile(HANDLE,HANDLE,PIO_APC_ROUTINE,void*,PIO_STA
 NTSYSAPI NTSTATUS  WINAPI NtLockVirtualMemory(HANDLE,PVOID*,SIZE_T*,ULONG);
 NTSYSAPI NTSTATUS  WINAPI NtMakeTemporaryObject(HANDLE);
 NTSYSAPI NTSTATUS  WINAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG_PTR,SIZE_T,const LARGE_INTEGER*,SIZE_T*,SECTION_INHERIT,ULONG,ULONG);
+NTSYSAPI NTSTATUS  WINAPI NtMapViewOfSectionEx(HANDLE,HANDLE,PVOID*,const LARGE_INTEGER*,SIZE_T*,ULONG,ULONG,MEM_EXTENDED_PARAMETER*,ULONG);
 NTSYSAPI NTSTATUS  WINAPI NtNotifyChangeDirectoryFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,PVOID,ULONG,ULONG,BOOLEAN);
 NTSYSAPI NTSTATUS  WINAPI NtNotifyChangeKey(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,BOOLEAN,PVOID,ULONG,BOOLEAN);
 NTSYSAPI NTSTATUS  WINAPI NtNotifyChangeMultipleKeys(HANDLE,ULONG,OBJECT_ATTRIBUTES*,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,BOOLEAN,PVOID,ULONG,BOOLEAN);
-- 
2.35.1




More information about the wine-devel mailing list