Author: akhaldi
Date: Mon Jun 4 10:45:54 2012
New Revision: 56691
URL:
http://svn.reactos.org/svn/reactos?rev=56691&view=rev
Log:
[KERNEL32_WINETEST]
* Sync loader tests to Wine 1.5.4. Thanks to Arty for fixing the related issues.
See issue #7071 for more details.
Modified:
trunk/rostests/winetests/kernel32/loader.c
Modified: trunk/rostests/winetests/kernel32/loader.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/kernel32/loader…
==============================================================================
--- trunk/rostests/winetests/kernel32/loader.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/kernel32/loader.c [iso-8859-1] Mon Jun 4 10:45:54 2012
@@ -21,11 +21,17 @@
#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)
{
@@ -57,7 +63,7 @@
#elif defined __sparc__
IMAGE_FILE_MACHINE_SPARC, /* Machine */
#elif defined __arm__
- IMAGE_FILE_MACHINE_ARM, /* Machine */
+ IMAGE_FILE_MACHINE_ARMV7, /* Machine */
#else
# error You must specify the machine type
#endif
@@ -553,42 +559,307 @@
}
}
+static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL is_dll)
+{
+ 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 != 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);
+
+ UnmapViewOfFile(addr2);
+
+ SetLastError(0xdeadbeef);
+ addr2 = LoadLibrary(dll_name);
+ if (is_dll)
+ {
+ ok(!addr2, "LoadLibrary should fail, is_dll %d\n", is_dll);
+ ok(GetLastError() == ERROR_INVALID_ADDRESS, "expected ERROR_INVALID_ADDRESS,
got %d\n", GetLastError());
+ }
+ else
+ {
+ BOOL ret;
+ ok(addr2 != 0, "LoadLibrary error %d, is_dll %d\n", GetLastError(),
is_dll);
+ ok(addr2 != addr1, "mapped addresses should be different\n");
+
+ SetLastError(0xdeadbeef);
+ ret = FreeLibrary(addr2);
+ ok(ret, "FreeLibrary error %d\n", GetLastError());
+ }
+
+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)
+ {
+ case PAGE_READWRITE:
+ case PAGE_WRITECOPY:
+ case PAGE_EXECUTE_READWRITE:
+ case PAGE_EXECUTE_WRITECOPY:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+static void test_VirtualProtect(void *base, void *section)
+{
+ static const struct test_data
+ {
+ DWORD prot_set, prot_get;
+ } td[] =
+ {
+ { 0, 0 }, /* 0x00 */
+ { PAGE_NOACCESS, PAGE_NOACCESS }, /* 0x01 */
+ { PAGE_READONLY, PAGE_READONLY }, /* 0x02 */
+ { PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x03 */
+ { PAGE_READWRITE, PAGE_WRITECOPY }, /* 0x04 */
+ { PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x05 */
+ { PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x06 */
+ { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x07 */
+ { PAGE_WRITECOPY, PAGE_WRITECOPY }, /* 0x08 */
+ { PAGE_WRITECOPY | PAGE_NOACCESS, 0 }, /* 0x09 */
+ { PAGE_WRITECOPY | PAGE_READONLY, 0 }, /* 0x0a */
+ { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, 0 }, /* 0x0b */
+ { PAGE_WRITECOPY | PAGE_READWRITE, 0 }, /* 0x0c */
+ { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x0d */
+ { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x0e */
+ { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x0f
*/
+
+ { PAGE_EXECUTE, PAGE_EXECUTE }, /* 0x10 */
+ { PAGE_EXECUTE_READ, PAGE_EXECUTE_READ }, /* 0x20 */
+ { PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x30 */
+ { PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY }, /* 0x40 */
+ { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0x50 */
+ { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0x60 */
+ { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x70 */
+ { PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_WRITECOPY }, /* 0x80 */
+ { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, 0 }, /* 0x90 */
+ { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, 0 }, /* 0xa0 */
+ { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0xb0 */
+ { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, 0 }, /* 0xc0 */
+ { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0xd0
*/
+ { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /*
0xe0 */
+ { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ |
PAGE_EXECUTE, 0 } /* 0xf0 */
+ };
+ DWORD ret, orig_prot, old_prot, rw_prot, exec_prot, i, j;
+ MEMORY_BASIC_INFORMATION info;
+ SYSTEM_INFO si;
+
+ GetSystemInfo(&si);
+ trace("system page size %#x\n", si.dwPageSize);
+
+ SetLastError(0xdeadbeef);
+ ret = VirtualProtect(section, si.dwPageSize, PAGE_NOACCESS, &old_prot);
+ ok(ret, "VirtualProtect error %d\n", GetLastError());
+
+ orig_prot = old_prot;
+
+ for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ {
+ SetLastError(0xdeadbeef);
+ ret = VirtualQuery(section, &info, sizeof(info));
+ ok(ret, "VirtualQuery failed %d\n", GetLastError());
+ ok(info.BaseAddress == section, "%d: got %p != expected %p\n", i,
info.BaseAddress, section);
+ ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n",
i, info.RegionSize, si.dwPageSize);
+ ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected
PAGE_NOACCESS\n", i, info.Protect);
+ ok(info.AllocationBase == base, "%d: %p != %p\n", i,
info.AllocationBase, base);
+ ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x !=
PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
+ ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i,
info.State);
+ ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i, info.Type);
+
+ old_prot = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = VirtualProtect(section, si.dwPageSize, td[i].prot_set, &old_prot);
+ if (td[i].prot_get)
+ {
+ ok(ret, "%d: VirtualProtect error %d, requested prot %#x\n", i,
GetLastError(), td[i].prot_set);
+ ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected
PAGE_NOACCESS\n", i, old_prot);
+
+ SetLastError(0xdeadbeef);
+ ret = VirtualQuery(section, &info, sizeof(info));
+ ok(ret, "VirtualQuery failed %d\n", GetLastError());
+ ok(info.BaseAddress == section, "%d: got %p != expected %p\n", i,
info.BaseAddress, section);
+ ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected
%#x\n", i, info.RegionSize, si.dwPageSize);
+ ok(info.Protect == td[i].prot_get, "%d: got %#x != expected %#x\n",
i, info.Protect, td[i].prot_get);
+ ok(info.AllocationBase == base, "%d: %p != %p\n", i,
info.AllocationBase, base);
+ ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x !=
PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
+ ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i,
info.State);
+ ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i,
info.Type);
+ }
+ else
+ {
+ ok(!ret, "%d: VirtualProtect should fail\n", i);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected
ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
+ }
+
+ old_prot = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = VirtualProtect(section, si.dwPageSize, PAGE_NOACCESS, &old_prot);
+ ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
+ if (td[i].prot_get)
+ ok(old_prot == td[i].prot_get, "%d: got %#x != expected %#x\n", i,
old_prot, td[i].prot_get);
+ else
+ ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected
PAGE_NOACCESS\n", i, old_prot);
+ }
+
+ exec_prot = 0;
+
+ for (i = 0; i <= 4; i++)
+ {
+ rw_prot = 0;
+
+ for (j = 0; j <= 4; j++)
+ {
+ DWORD prot = exec_prot | rw_prot;
+
+ SetLastError(0xdeadbeef);
+ ret = VirtualProtect(section, si.dwPageSize, prot, &old_prot);
+ if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
+ {
+ ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected
ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ }
+ else
+ ok(ret, "VirtualProtect(%02x) error %d\n", prot,
GetLastError());
+
+ rw_prot = 1 << j;
+ }
+
+ exec_prot = 1 << (i + 4);
+ }
+
+ SetLastError(0xdeadbeef);
+ ret = VirtualProtect(section, si.dwPageSize, orig_prot, &old_prot);
+ ok(ret, "VirtualProtect error %d\n", GetLastError());
+}
+
static void test_section_access(void)
{
static const struct test_data
{
- DWORD scn_file_access, scn_page_access;
+ DWORD scn_file_access, scn_page_access, scn_page_access_after_write;
} td[] =
{
- { 0, PAGE_NOACCESS },
- { IMAGE_SCN_MEM_READ, PAGE_READONLY },
- { IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
- { IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE },
- { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
+ { 0, PAGE_NOACCESS, 0 },
+ { IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 },
+ { IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE },
+ { IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 },
+ { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE },
{ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ },
- { IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY },
- { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE,
PAGE_EXECUTE_WRITECOPY },
-
- { IMAGE_SCN_CNT_INITIALIZED_DATA, PAGE_NOACCESS },
- { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY },
- { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
- { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE },
- { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE,
PAGE_WRITECOPY },
- { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE,
PAGE_EXECUTE_READ },
- { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE,
PAGE_EXECUTE_WRITECOPY },
- { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE |
IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY },
-
- { IMAGE_SCN_CNT_UNINITIALIZED_DATA, PAGE_NOACCESS },
- { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY },
- { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
- { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE },
- { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE,
PAGE_WRITECOPY },
- { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE,
PAGE_EXECUTE_READ },
- { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE,
PAGE_EXECUTE_WRITECOPY },
- { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE |
IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY }
+ { IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY,
PAGE_EXECUTE_READWRITE },
+ { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE,
PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE },
+
+ { IMAGE_SCN_CNT_INITIALIZED_DATA, PAGE_NOACCESS, 0 },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY,
PAGE_READWRITE },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE,
PAGE_WRITECOPY, PAGE_READWRITE },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE,
PAGE_EXECUTE_READ, 0 },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE,
PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE |
IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE },
+
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA, PAGE_NOACCESS, 0 },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY,
PAGE_READWRITE },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE,
PAGE_WRITECOPY, PAGE_READWRITE },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE,
PAGE_EXECUTE_READ, 0 },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE,
PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE |
IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }
};
static const char filler[0x1000];
static const char section_data[0x10] = "section data";
+ char buf[256];
int i;
DWORD dummy, file_align;
HANDLE hfile;
@@ -598,7 +869,9 @@
char dll_name[MAX_PATH];
SIZE_T size;
MEMORY_BASIC_INFORMATION info;
- BOOL ret;
+ STARTUPINFO sti;
+ PROCESS_INFORMATION pi;
+ DWORD ret;
GetSystemInfo(&si);
trace("system page size %#x\n", si.dwPageSize);
@@ -626,6 +899,7 @@
nt_header.FileHeader.NumberOfSections = 1;
nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
+ 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;
@@ -662,18 +936,14 @@
SetLastError(0xdeadbeef);
hlib = LoadLibrary(dll_name);
- ok(ret, "LoadLibrary error %d\n", GetLastError());
-
+ ok(hlib != 0, "LoadLibrary error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
size = VirtualQuery((char *)hlib + section.VirtualAddress, &info,
sizeof(info));
ok(size == sizeof(info),
"%d: VirtualQuery error %d\n", i, GetLastError());
ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p !=
expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress);
ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n",
i, info.RegionSize, si.dwPageSize);
- /* FIXME: remove the condition below once Wine is fixed */
- if ((td[i].scn_file_access & IMAGE_SCN_MEM_WRITE) &&
- (td[i].scn_file_access & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
- todo_wine ok(info.Protect == td[i].scn_page_access, "%d: got %#x != expected
%#x\n", i, info.Protect, td[i].scn_page_access);
- else
ok(info.Protect == td[i].scn_page_access, "%d: got %#x != expected
%#x\n", i, info.Protect, td[i].scn_page_access);
ok(info.AllocationBase == hlib, "%d: %p != %p\n", i,
info.AllocationBase, hlib);
ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x !=
PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
@@ -682,18 +952,96 @@
if (info.Protect != PAGE_NOACCESS)
ok(!memcmp((const char *)info.BaseAddress, section_data,
section.SizeOfRawData), "wrong section data\n");
+ test_VirtualProtect(hlib, (char *)hlib + section.VirtualAddress);
+
+ /* Windows changes the WRITECOPY to WRITE protection on an image section write
(for a changed page only) */
+ if (is_mem_writable(info.Protect))
+ {
+ char *p = info.BaseAddress;
+ *p = 0xfe;
+ SetLastError(0xdeadbeef);
+ size = VirtualQuery((char *)hlib + section.VirtualAddress, &info,
sizeof(info));
+ ok(size == sizeof(info), "%d: VirtualQuery error %d\n", i,
GetLastError());
+ /* FIXME: remove the condition below once Wine is fixed */
+ if (info.Protect == PAGE_WRITECOPY || info.Protect ==
PAGE_EXECUTE_WRITECOPY)
+ todo_wine ok(info.Protect == td[i].scn_page_access_after_write, "%d:
got %#x != expected %#x\n", i, info.Protect, td[i].scn_page_access_after_write);
+ else
+ ok(info.Protect == td[i].scn_page_access_after_write, "%d: got %#x
!= expected %#x\n", i, info.Protect, td[i].scn_page_access_after_write);
+ }
+
SetLastError(0xdeadbeef);
ret = FreeLibrary(hlib);
ok(ret, "FreeLibrary error %d\n", GetLastError());
+ test_image_mapping(dll_name, td[i].scn_page_access, TRUE);
+
+ /* 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);
+ /* LoadLibrary called on an already memory-mapped file in
+ * test_image_mapping() above leads to a file handle leak
+ * under nt4, and inability to overwrite and delete the file
+ * due to sharing violation error. Ignore it and skip the test,
+ * but leave a not deletable temporary file.
+ */
+ ok(hfile != INVALID_HANDLE_VALUE || broken(hfile == INVALID_HANDLE_VALUE) /* nt4
*/,
+ "CreateFile error %d\n", GetLastError());
+ if (hfile == INVALID_HANDLE_VALUE) goto nt4_is_broken;
+ 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);
+ ret = CreateProcess(dll_name, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL,
NULL, &sti, &pi);
+ ok(ret, "CreateProcess() error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ size = VirtualQueryEx(pi.hProcess, (char *)hlib + section.VirtualAddress,
&info, sizeof(info));
+ ok(size == sizeof(info),
+ "%d: VirtualQuery error %d\n", i, GetLastError());
+ ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p !=
expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress);
+ ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n",
i, info.RegionSize, si.dwPageSize);
+ ok(info.Protect == td[i].scn_page_access, "%d: got %#x != expected
%#x\n", i, info.Protect, td[i].scn_page_access);
+ ok(info.AllocationBase == hlib, "%d: %p != %p\n", i,
info.AllocationBase, hlib);
+ ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x !=
PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
+ ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i,
info.State);
+ ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i, info.Type);
+ if (info.Protect != PAGE_NOACCESS)
+ {
+ SetLastError(0xdeadbeef);
+ ret = ReadProcessMemory(pi.hProcess, info.BaseAddress, buf,
section.SizeOfRawData, NULL);
+ ok(ret, "ReadProcessMemory() error %d\n", GetLastError());
+ ok(!memcmp(buf, section_data, section.SizeOfRawData), "wrong section
data\n");
+ }
+
+ SetLastError(0xdeadbeef);
+ ret = TerminateProcess(pi.hProcess, 0);
+ ok(ret, "TerminateProcess() error %d\n", GetLastError());
+ ret = WaitForSingleObject(pi.hProcess, 3000);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %x\n", ret);
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ test_image_mapping(dll_name, td[i].scn_page_access, FALSE);
+
+nt4_is_broken:
SetLastError(0xdeadbeef);
ret = DeleteFile(dll_name);
- ok(ret, "DeleteFile error %d\n", GetLastError());
+ ok(ret || broken(!ret) /* nt4 */, "DeleteFile error %d\n",
GetLastError());
}
}
START_TEST(loader)
{
+ pNtMapViewOfSection = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtMapViewOfSection");
+ pNtUnmapViewOfSection = (void
*)GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtUnmapViewOfSection");
+
test_Loader();
test_ImportDescriptors();
test_section_access();