Signed-off-by: Nikolay Sivov <nsivov(a)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