kernel32: Add the tests for various combinations of CreateFileMapping/MapViewOfFile protections.

This commit is contained in:
Dmitry Timoshkov 2011-12-15 16:06:37 +08:00 committed by Alexandre Julliard
parent 59b2639e39
commit 5379a75baf
1 changed files with 291 additions and 1 deletions

View File

@ -1699,6 +1699,7 @@ static void test_CreateFileMapping_protection(void)
{
if (!hmap)
{
trace("%d: CreateFileMapping(%04x) failed: %d\n", i, td[i].prot, GetLastError());
/* NT4 and win2k don't support EXEC on file mappings */
if (td[i].prot == PAGE_EXECUTE_READ || td[i].prot == PAGE_EXECUTE_READWRITE)
{
@ -1714,7 +1715,7 @@ static void test_CreateFileMapping_protection(void)
continue;
}
}
ok(hmap != 0, "%d: CreateFileMapping error %d\n", i, GetLastError());
ok(hmap != 0, "%d: CreateFileMapping(%04x) error %d\n", i, td[i].prot, GetLastError());
base = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0);
ok(base != NULL, "%d: MapViewOfFile failed %d\n", i, GetLastError());
@ -1871,6 +1872,294 @@ static void test_CreateFileMapping_protection(void)
DeleteFile(file_name);
}
#define ACCESS_READ 0x01
#define ACCESS_WRITE 0x02
#define ACCESS_EXECUTE 0x04
#define ACCESS_WRITECOPY 0x08
static DWORD page_prot_to_access(DWORD prot)
{
switch (prot)
{
case PAGE_READWRITE:
return ACCESS_READ | ACCESS_WRITE;
case PAGE_EXECUTE:
case PAGE_EXECUTE_READ:
return ACCESS_READ | ACCESS_EXECUTE;
case PAGE_EXECUTE_READWRITE:
return ACCESS_READ | ACCESS_WRITE | ACCESS_WRITECOPY | ACCESS_EXECUTE;
case PAGE_EXECUTE_WRITECOPY:
return ACCESS_READ | ACCESS_WRITECOPY | ACCESS_EXECUTE;
case PAGE_READONLY:
return ACCESS_READ;
case PAGE_WRITECOPY:
return ACCESS_READ;
default:
return 0;
}
}
static BOOL is_compatible_protection(DWORD map_prot, DWORD view_prot, DWORD prot)
{
DWORD map_access, view_access, prot_access;
map_access = page_prot_to_access(map_prot);
view_access = page_prot_to_access(view_prot);
prot_access = page_prot_to_access(prot);
if (view_access == prot_access) return TRUE;
if (!view_access) return FALSE;
if ((view_access & prot_access) != prot_access) return FALSE;
if ((map_access & prot_access) == prot_access) return TRUE;
return FALSE;
}
static DWORD map_prot_to_access(DWORD prot)
{
switch (prot)
{
case PAGE_READWRITE:
case PAGE_EXECUTE_READWRITE:
return SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT | SECTION_QUERY;
case PAGE_READONLY:
case PAGE_WRITECOPY:
case PAGE_EXECUTE:
case PAGE_EXECUTE_READ:
case PAGE_EXECUTE_WRITECOPY:
return SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT | SECTION_QUERY;
default:
return 0;
}
}
static BOOL is_compatible_access(DWORD map_prot, DWORD view_prot)
{
DWORD access = map_prot_to_access(map_prot);
return (view_prot & access) == view_prot;
}
static void test_mapping(void)
{
static const DWORD page_prot[] =
{
PAGE_NOACCESS, PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY,
PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY
};
static const struct
{
DWORD access, prot;
} view[] =
{
{ 0, PAGE_NOACCESS }, /* 0x00 */
{ FILE_MAP_COPY, PAGE_WRITECOPY }, /* 0x01 */
{ FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x02 */
{ FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x03 */
{ FILE_MAP_READ, PAGE_READONLY }, /* 0x04 */
{ FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x05 */
{ FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x06 */
{ FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x07 */
{ SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x08 */
{ SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x09 */
{ SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0a */
{ SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0b */
{ SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_READONLY }, /* 0x0c */
{ SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x0d */
{ SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0e */
{ SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0f */
{ FILE_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x20 */
{ FILE_MAP_EXECUTE | FILE_MAP_COPY, PAGE_EXECUTE_WRITECOPY }, /* 0x21 */
{ FILE_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x22 */
{ FILE_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x23 */
{ FILE_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x24 */
{ FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x25 */
{ FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x26 */
{ FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x27 */
{ FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x28 */
{ FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x29 */
{ FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2a */
{ FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x2b */
{ FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x2c */
{ FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x2d */
{ FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2e */
{ FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE } /* 0x2f */
};
void *base;
DWORD i, j, k, ret, old_prot, prev_prot;
SYSTEM_INFO si;
char temp_path[MAX_PATH];
char file_name[MAX_PATH];
HANDLE hfile, hmap;
MEMORY_BASIC_INFORMATION info;
GetSystemInfo(&si);
trace("system page size %#x\n", si.dwPageSize);
GetTempPath(MAX_PATH, temp_path);
GetTempFileName(temp_path, "map", 0, file_name);
SetLastError(0xdeadbeef);
hfile = CreateFile(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
SetFilePointer(hfile, si.dwPageSize, NULL, FILE_BEGIN);
SetEndOfFile(hfile);
for (i = 0; i < sizeof(page_prot)/sizeof(page_prot[0]); i++)
{
SetLastError(0xdeadbeef);
hmap = CreateFileMapping(hfile, NULL, page_prot[i] | SEC_COMMIT, 0, si.dwPageSize, NULL);
if (!hmap)
{
trace("%d: CreateFileMapping(%04x) failed: %d\n", i, page_prot[i], GetLastError());
if (page_prot[i] == PAGE_NOACCESS)
{
ok(!hmap, "%d: CreateFileMapping(%04x) should fail\n", i, page_prot[i]);
ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
continue;
}
/* NT4 and win2k don't support EXEC on file mappings */
if (page_prot[i] == PAGE_EXECUTE_READ || page_prot[i] == PAGE_EXECUTE_READWRITE)
{
ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i);
continue;
}
/* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
if (page_prot[i] == PAGE_EXECUTE_WRITECOPY)
{
ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
continue;
}
}
ok(hmap != 0, "%d: CreateFileMapping(%04x) error %d\n", i, page_prot[i], GetLastError());
for (j = 0; j < sizeof(view)/sizeof(view[0]); j++)
{
SetLastError(0xdeadbeef);
base = MapViewOfFile(hmap, view[j].access, 0, 0, 0);
if (!is_compatible_access(page_prot[i], view[j].access))
{
ok(!base, "%d: MapViewOfFile(%04x/%04x) should fail\n", j, page_prot[i], view[j].access);
ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
continue;
}
/* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */
if (!base && (view[j].access & FILE_MAP_EXECUTE))
{
ok(broken(!base), "%d: MapViewOfFile(%04x/%04x) failed %d\n", j, page_prot[i], view[j].access, GetLastError());
continue;
}
ok(base != NULL, "%d: MapViewOfFile(%04x/%04x) failed %d\n", j, page_prot[i], view[j].access, GetLastError());
SetLastError(0xdeadbeef);
ret = VirtualQuery(base, &info, sizeof(info));
ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
ok(info.BaseAddress == base, "%d: (%04x) got %p, expected %p\n", j, view[j].access, info.BaseAddress, base);
ok(info.RegionSize == si.dwPageSize, "%d: (%04x) got %#lx != expected %#x\n", j, view[j].access, info.RegionSize, si.dwPageSize);
/* FIXME: completely remove the condition below once Wine is fixed */
if (info.Protect != view[j].prot)
todo_wine
ok(info.Protect == view[j].prot ||
broken(view[j].prot == PAGE_EXECUTE_READ && info.Protect == PAGE_READONLY) || /* win2k */
broken(view[j].prot == PAGE_EXECUTE_READWRITE && info.Protect == PAGE_READWRITE) || /* win2k */
broken(view[j].prot == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
"%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.Protect, view[j].prot);
else
ok(info.Protect == view[j].prot ||
broken(view[j].prot == PAGE_EXECUTE_READ && info.Protect == PAGE_READONLY) || /* win2k */
broken(view[j].prot == PAGE_EXECUTE_READWRITE && info.Protect == PAGE_READWRITE) || /* win2k */
broken(view[j].prot == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
"%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.Protect, view[j].prot);
ok(info.AllocationBase == base, "%d: (%04x) got %p, expected %p\n", j, view[j].access, info.AllocationBase, base);
ok(info.AllocationProtect == info.Protect, "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.AllocationProtect, info.Protect);
ok(info.State == MEM_COMMIT, "%d: (%04x) got %#x, expected MEM_COMMIT\n", j, view[j].access, info.State);
ok(info.Type == MEM_MAPPED, "%d: (%04x) got %#x, expected MEM_MAPPED\n", j, view[j].access, info.Type);
prev_prot = info.Protect;
for (k = 0; k < sizeof(page_prot)/sizeof(page_prot[0]); k++)
{
/*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
SetLastError(0xdeadbeef);
old_prot = 0xdeadbeef;
ret = VirtualProtect(base, si.dwPageSize, page_prot[k], &old_prot);
if (is_compatible_protection(page_prot[i], view[j].prot, page_prot[k]))
{
/* win2k and XP don't support EXEC on file mappings */
if (!ret && page_prot[k] == PAGE_EXECUTE)
{
ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n");
continue;
}
/* NT4 and win2k don't support EXEC on file mappings */
if (!ret && (page_prot[k] == PAGE_EXECUTE_READ || page_prot[k] == PAGE_EXECUTE_READWRITE))
{
ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n");
continue;
}
/* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
if (!ret && page_prot[k] == PAGE_EXECUTE_WRITECOPY)
{
todo_wine
ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n");
continue;
}
/* win2k and XP don't support PAGE_EXECUTE_WRITECOPY views properly */
if (!ret && view[j].prot == PAGE_EXECUTE_WRITECOPY)
{
ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY view properly\n");
continue;
}
/* FIXME: completely remove the condition below once Wine is fixed */
if (!ret && page_prot[k] == PAGE_WRITECOPY)
{
todo_wine
ok(ret, "VirtualProtect error %d\n", GetLastError());
continue;
}
ok(ret, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot[i], view[j].prot, page_prot[k]);
ok(old_prot == prev_prot, "got %#x, expected %#x\n", old_prot, prev_prot);
prev_prot = page_prot[k];
}
else
{
/* NT4 doesn't fail on incompatible map and view */
if (ret)
{
todo_wine
ok(broken(ret), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
skip("Incompatible map and view are not properly handled on this platform\n");
break; /* NT4 won't pass remaining tests */
}
ok(!ret, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
}
UnmapViewOfFile(base);
}
CloseHandle(hmap);
}
CloseHandle(hfile);
DeleteFile(file_name);
}
START_TEST(virtual)
{
int argc;
@ -1906,6 +2195,7 @@ START_TEST(virtual)
pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch");
pNtAreMappedFilesTheSame = (void *)GetProcAddress( GetModuleHandle("ntdll.dll"),
"NtAreMappedFilesTheSame" );
test_mapping();
test_CreateFileMapping_protection();
test_VirtualAlloc_protection();
test_VirtualProtect();