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