kernel32: Add a test to show that NtMapViewOfSection should not perform an image relocation.
This commit is contained in:
parent
90dd4ea9a6
commit
20093556f9
|
@ -21,12 +21,18 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "ntstatus.h"
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
#include "winternl.h"
|
||||||
#include "wine/test.h"
|
#include "wine/test.h"
|
||||||
|
|
||||||
#define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1)))
|
#define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1)))
|
||||||
|
|
||||||
|
static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG);
|
||||||
|
static NTSTATUS (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID);
|
||||||
|
|
||||||
static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
|
static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
|
||||||
{
|
{
|
||||||
if (rva == 0)
|
if (rva == 0)
|
||||||
|
@ -553,6 +559,105 @@ static void test_ImportDescriptors(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_image_mapping(const char *dll_name, DWORD scn_page_access)
|
||||||
|
{
|
||||||
|
HANDLE hfile, hmap;
|
||||||
|
NTSTATUS status;
|
||||||
|
LARGE_INTEGER offset;
|
||||||
|
SIZE_T size;
|
||||||
|
void *addr1, *addr2;
|
||||||
|
MEMORY_BASIC_INFORMATION info;
|
||||||
|
SYSTEM_INFO si;
|
||||||
|
|
||||||
|
if (!pNtMapViewOfSection) return;
|
||||||
|
|
||||||
|
GetSystemInfo(&si);
|
||||||
|
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
hfile = CreateFile(dll_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
|
||||||
|
ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
|
||||||
|
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
hmap = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, 0);
|
||||||
|
ok(hmap != 0, "CreateFileMapping error %d\n", GetLastError());
|
||||||
|
|
||||||
|
offset.u.LowPart = 0;
|
||||||
|
offset.u.HighPart = 0;
|
||||||
|
|
||||||
|
addr1 = NULL;
|
||||||
|
size = 0;
|
||||||
|
status = pNtMapViewOfSection(hmap, GetCurrentProcess(), &addr1, 0, 0, &offset,
|
||||||
|
&size, 1 /* ViewShare */, 0, PAGE_READONLY);
|
||||||
|
ok(status == STATUS_SUCCESS, "NtMapViewOfSection error %x\n", status);
|
||||||
|
ok(addr1 != 0, "mapped address should be valid\n");
|
||||||
|
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
size = VirtualQuery((char *)addr1 + section.VirtualAddress, &info, sizeof(info));
|
||||||
|
ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError());
|
||||||
|
ok(info.BaseAddress == (char *)addr1 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr1 + section.VirtualAddress);
|
||||||
|
ok(info.RegionSize == si.dwPageSize, "got %#lx != expected %#x\n", info.RegionSize, si.dwPageSize);
|
||||||
|
ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access);
|
||||||
|
ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
|
||||||
|
ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect);
|
||||||
|
ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
|
||||||
|
ok(info.Type == SEC_IMAGE, "%#x != SEC_IMAGE\n", info.Type);
|
||||||
|
|
||||||
|
addr2 = NULL;
|
||||||
|
size = 0;
|
||||||
|
status = pNtMapViewOfSection(hmap, GetCurrentProcess(), &addr2, 0, 0, &offset,
|
||||||
|
&size, 1 /* ViewShare */, 0, PAGE_READONLY);
|
||||||
|
/* FIXME: remove once Wine is fixed */
|
||||||
|
if (status != STATUS_IMAGE_NOT_AT_BASE)
|
||||||
|
{
|
||||||
|
todo_wine {
|
||||||
|
ok(status == STATUS_IMAGE_NOT_AT_BASE, "expected STATUS_IMAGE_NOT_AT_BASE, got %x\n", status);
|
||||||
|
ok(addr2 != 0, "mapped address should be valid\n");
|
||||||
|
}
|
||||||
|
goto wine_is_broken;
|
||||||
|
}
|
||||||
|
ok(status == STATUS_IMAGE_NOT_AT_BASE, "expected STATUS_IMAGE_NOT_AT_BASE, got %x\n", status);
|
||||||
|
ok(addr2 != 0, "mapped address should be valid\n");
|
||||||
|
|
||||||
|
ok(addr2 != addr1, "mapped addresses should be different\n");
|
||||||
|
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
size = VirtualQuery((char *)addr2 + section.VirtualAddress, &info, sizeof(info));
|
||||||
|
ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError());
|
||||||
|
ok(info.BaseAddress == (char *)addr2 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr2 + section.VirtualAddress);
|
||||||
|
ok(info.RegionSize == si.dwPageSize, "got %#lx != expected %#x\n", info.RegionSize, si.dwPageSize);
|
||||||
|
ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access);
|
||||||
|
ok(info.AllocationBase == addr2, "%p != %p\n", info.AllocationBase, addr2);
|
||||||
|
ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect);
|
||||||
|
ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
|
||||||
|
ok(info.Type == SEC_IMAGE, "%#x != SEC_IMAGE\n", info.Type);
|
||||||
|
|
||||||
|
status = pNtUnmapViewOfSection(GetCurrentProcess(), addr2);
|
||||||
|
ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection error %x\n", status);
|
||||||
|
|
||||||
|
addr2 = MapViewOfFile(hmap, 0, 0, 0, 0);
|
||||||
|
ok(addr2 != addr1, "mapped addresses should be different\n");
|
||||||
|
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
size = VirtualQuery((char *)addr2 + section.VirtualAddress, &info, sizeof(info));
|
||||||
|
ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError());
|
||||||
|
ok(info.BaseAddress == (char *)addr2 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr2 + section.VirtualAddress);
|
||||||
|
ok(info.RegionSize == si.dwPageSize, "got %#lx != expected %#x\n", info.RegionSize, si.dwPageSize);
|
||||||
|
ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access);
|
||||||
|
ok(info.AllocationBase == addr2, "%p != %p\n", info.AllocationBase, addr2);
|
||||||
|
ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect);
|
||||||
|
ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
|
||||||
|
ok(info.Type == SEC_IMAGE, "%#x != SEC_IMAGE\n", info.Type);
|
||||||
|
|
||||||
|
UnmapViewOfFile(addr2);
|
||||||
|
|
||||||
|
wine_is_broken:
|
||||||
|
status = pNtUnmapViewOfSection(GetCurrentProcess(), addr1);
|
||||||
|
ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection error %x\n", status);
|
||||||
|
|
||||||
|
CloseHandle(hmap);
|
||||||
|
CloseHandle(hfile);
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL is_mem_writable(DWORD prot)
|
static BOOL is_mem_writable(DWORD prot)
|
||||||
{
|
{
|
||||||
switch (prot & 0xff)
|
switch (prot & 0xff)
|
||||||
|
@ -776,9 +881,7 @@ static void test_section_access(void)
|
||||||
|
|
||||||
nt_header.FileHeader.NumberOfSections = 1;
|
nt_header.FileHeader.NumberOfSections = 1;
|
||||||
nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
|
nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
|
||||||
|
nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_RELOCS_STRIPPED;
|
||||||
/* don't set IMAGE_FILE_DLL to show that it doesn't change anything for a DLL or a process image */
|
|
||||||
nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
|
|
||||||
|
|
||||||
nt_header.OptionalHeader.SectionAlignment = si.dwPageSize;
|
nt_header.OptionalHeader.SectionAlignment = si.dwPageSize;
|
||||||
nt_header.OptionalHeader.FileAlignment = 0x200;
|
nt_header.OptionalHeader.FileAlignment = 0x200;
|
||||||
|
@ -852,6 +955,19 @@ static void test_section_access(void)
|
||||||
ret = FreeLibrary(hlib);
|
ret = FreeLibrary(hlib);
|
||||||
ok(ret, "FreeLibrary error %d\n", GetLastError());
|
ok(ret, "FreeLibrary error %d\n", GetLastError());
|
||||||
|
|
||||||
|
test_image_mapping(dll_name, td[i].scn_page_access);
|
||||||
|
|
||||||
|
/* reset IMAGE_FILE_DLL otherwise CreateProcess fails */
|
||||||
|
nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_RELOCS_STRIPPED;
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
hfile = CreateFile(dll_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
|
||||||
|
ok (hfile != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
|
||||||
|
SetFilePointer(hfile, sizeof(dos_header), NULL, FILE_BEGIN);
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
|
||||||
|
ok(ret, "WriteFile error %d\n", GetLastError());
|
||||||
|
CloseHandle(hfile);
|
||||||
|
|
||||||
memset(&sti, 0, sizeof(sti));
|
memset(&sti, 0, sizeof(sti));
|
||||||
sti.cb = sizeof(sti);
|
sti.cb = sizeof(sti);
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
|
@ -886,6 +1002,8 @@ static void test_section_access(void)
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
|
|
||||||
|
test_image_mapping(dll_name, td[i].scn_page_access);
|
||||||
|
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = DeleteFile(dll_name);
|
ret = DeleteFile(dll_name);
|
||||||
ok(ret, "DeleteFile error %d\n", GetLastError());
|
ok(ret, "DeleteFile error %d\n", GetLastError());
|
||||||
|
@ -894,6 +1012,9 @@ static void test_section_access(void)
|
||||||
|
|
||||||
START_TEST(loader)
|
START_TEST(loader)
|
||||||
{
|
{
|
||||||
|
pNtMapViewOfSection = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtMapViewOfSection");
|
||||||
|
pNtUnmapViewOfSection = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtUnmapViewOfSection");
|
||||||
|
|
||||||
test_Loader();
|
test_Loader();
|
||||||
test_ImportDescriptors();
|
test_ImportDescriptors();
|
||||||
test_section_access();
|
test_section_access();
|
||||||
|
|
Loading…
Reference in New Issue