ntdll: Add a partial implementation of NtMapViewOfSectionEx().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2022-05-04 14:55:35 +03:00 committed by Alexandre Julliard
parent bc69f50575
commit dc5d76b3af
7 changed files with 200 additions and 0 deletions

View File

@ -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

View File

@ -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();
}

View File

@ -207,6 +207,7 @@ static void * const syscalls[] =
NtLockVirtualMemory,
NtMakeTemporaryObject,
NtMapViewOfSection,
NtMapViewOfSectionEx,
NtNotifyChangeDirectoryFile,
NtNotifyChangeKey,
NtNotifyChangeMultipleKeys,

View File

@ -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.@)

View File

@ -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 ) \

View File

@ -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

View File

@ -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);