Dmitry Timoshkov : kernel32: Add a test to show that NtMapViewOfSection should not perform an image relocation .
Alexandre Julliard
julliard at winehq.org
Mon Feb 20 11:17:32 CST 2012
Module: wine
Branch: master
Commit: 20093556f92fbced66761526b8801bcd94ec484d
URL: http://source.winehq.org/git/wine.git/?a=commit;h=20093556f92fbced66761526b8801bcd94ec484d
Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date: Mon Feb 20 16:01:25 2012 +0800
kernel32: Add a test to show that NtMapViewOfSection should not perform an image relocation.
---
dlls/kernel32/tests/loader.c | 127 +++++++++++++++++++++++++++++++++++++++++-
1 files changed, 124 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index 0b67bb6..9c969c2 100644
--- a/dlls/kernel32/tests/loader.c
+++ b/dlls/kernel32/tests/loader.c
@@ -21,12 +21,18 @@
#include <stdarg.h>
#include <assert.h>
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "winternl.h"
#include "wine/test.h"
#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)
{
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)
{
switch (prot & 0xff)
@@ -776,9 +881,7 @@ static void test_section_access(void)
nt_header.FileHeader.NumberOfSections = 1;
nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
-
- /* 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.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_RELOCS_STRIPPED;
nt_header.OptionalHeader.SectionAlignment = si.dwPageSize;
nt_header.OptionalHeader.FileAlignment = 0x200;
@@ -852,6 +955,19 @@ static void test_section_access(void)
ret = FreeLibrary(hlib);
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));
sti.cb = sizeof(sti);
SetLastError(0xdeadbeef);
@@ -886,6 +1002,8 @@ static void test_section_access(void)
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
+ test_image_mapping(dll_name, td[i].scn_page_access);
+
SetLastError(0xdeadbeef);
ret = DeleteFile(dll_name);
ok(ret, "DeleteFile error %d\n", GetLastError());
@@ -894,6 +1012,9 @@ static void test_section_access(void)
START_TEST(loader)
{
+ pNtMapViewOfSection = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtMapViewOfSection");
+ pNtUnmapViewOfSection = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtUnmapViewOfSection");
+
test_Loader();
test_ImportDescriptors();
test_section_access();
More information about the wine-cvs
mailing list