kernel32: Add a test to show that Windows changes the WRITECOPY to WRITE protection on an image section write.
This commit is contained in:
parent
30882eb08e
commit
bed1e5c8f5
|
@ -553,39 +553,54 @@ static void test_ImportDescriptors(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_section_access(void)
|
static void test_section_access(void)
|
||||||
{
|
{
|
||||||
static const struct test_data
|
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[] =
|
} td[] =
|
||||||
{
|
{
|
||||||
{ 0, PAGE_NOACCESS },
|
{ 0, PAGE_NOACCESS, 0 },
|
||||||
{ IMAGE_SCN_MEM_READ, PAGE_READONLY },
|
{ IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 },
|
||||||
{ IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
|
{ IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE },
|
||||||
{ IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE },
|
{ IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 },
|
||||||
{ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
|
{ 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_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_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 },
|
{ 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 },
|
{ IMAGE_SCN_CNT_INITIALIZED_DATA, PAGE_NOACCESS, 0 },
|
||||||
{ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY },
|
{ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 },
|
||||||
{ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
|
{ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE },
|
||||||
{ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE },
|
{ 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 },
|
{ 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 },
|
{ 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 },
|
{ 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 },
|
{ 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 },
|
{ IMAGE_SCN_CNT_UNINITIALIZED_DATA, PAGE_NOACCESS, 0 },
|
||||||
{ IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY },
|
{ IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 },
|
||||||
{ IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
|
{ IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE },
|
||||||
{ IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE },
|
{ 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 },
|
{ 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 },
|
{ 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 },
|
{ 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 }
|
{ 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 filler[0x1000];
|
||||||
static const char section_data[0x10] = "section data";
|
static const char section_data[0x10] = "section data";
|
||||||
|
@ -664,6 +679,7 @@ static void test_section_access(void)
|
||||||
hlib = LoadLibrary(dll_name);
|
hlib = LoadLibrary(dll_name);
|
||||||
ok(hlib != 0, "LoadLibrary error %d\n", GetLastError());
|
ok(hlib != 0, "LoadLibrary error %d\n", GetLastError());
|
||||||
|
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info));
|
size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info));
|
||||||
ok(size == sizeof(info),
|
ok(size == sizeof(info),
|
||||||
"%d: VirtualQuery error %d\n", i, GetLastError());
|
"%d: VirtualQuery error %d\n", i, GetLastError());
|
||||||
|
@ -682,6 +698,21 @@ static void test_section_access(void)
|
||||||
if (info.Protect != PAGE_NOACCESS)
|
if (info.Protect != PAGE_NOACCESS)
|
||||||
ok(!memcmp((const char *)info.BaseAddress, section_data, section.SizeOfRawData), "wrong section data\n");
|
ok(!memcmp((const char *)info.BaseAddress, section_data, section.SizeOfRawData), "wrong section data\n");
|
||||||
|
|
||||||
|
/* 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);
|
SetLastError(0xdeadbeef);
|
||||||
ret = FreeLibrary(hlib);
|
ret = FreeLibrary(hlib);
|
||||||
ok(ret, "FreeLibrary error %d\n", GetLastError());
|
ok(ret, "FreeLibrary error %d\n", GetLastError());
|
||||||
|
|
Loading…
Reference in New Issue