Reactos
at master 4579 lines 225 kB view raw
1/* 2 * Unit test suite for Virtual* family of APIs. 3 * 4 * Copyright 2004 Dmitry Timoshkov 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21#include <stdarg.h> 22#include <stdio.h> 23 24#include "ntstatus.h" 25#define WIN32_NO_STATUS 26#include "windef.h" 27#include "winbase.h" 28#include "winnt.h" 29#include "winternl.h" 30#include "winerror.h" 31#include "winuser.h" 32#include "excpt.h" 33#include "wine/test.h" 34 35#define NUM_THREADS 4 36#define MAPPING_SIZE 0x100000 37 38static HINSTANCE hkernel32, hkernelbase, hntdll; 39static SYSTEM_INFO si; 40static BOOL is_wow64; 41static UINT (WINAPI *pGetWriteWatch)(DWORD,LPVOID,SIZE_T,LPVOID*,ULONG_PTR*,ULONG*); 42static UINT (WINAPI *pResetWriteWatch)(LPVOID,SIZE_T); 43static NTSTATUS (WINAPI *pNtAreMappedFilesTheSame)(PVOID,PVOID); 44static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, 45 const LARGE_INTEGER *, ULONG, ULONG, HANDLE ); 46static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG_PTR, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG); 47static DWORD (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID); 48static NTSTATUS (WINAPI *pNtQuerySection)(HANDLE, SECTION_INFORMATION_CLASS, void *, SIZE_T, SIZE_T *); 49static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG, PVECTORED_EXCEPTION_HANDLER); 50static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID); 51static BOOL (WINAPI *pGetProcessDEPPolicy)(HANDLE, LPDWORD, PBOOL); 52static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); 53static NTSTATUS (WINAPI *pNtProtectVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG *); 54static NTSTATUS (WINAPI *pNtReadVirtualMemory)(HANDLE,const void *,void *,SIZE_T, SIZE_T *); 55static NTSTATUS (WINAPI *pNtWriteVirtualMemory)(HANDLE, void *, const void *, SIZE_T, SIZE_T *); 56#ifndef __REACTOS__ // TODO: Enable when kernelbase is fixed. ROSTESTS-414 57static BOOL (WINAPI *pPrefetchVirtualMemory)(HANDLE, ULONG_PTR, PWIN32_MEMORY_RANGE_ENTRY, ULONG); 58#endif 59 60/* ############################### */ 61 62static HANDLE create_target_process(const char *arg) 63{ 64 char **argv; 65 char cmdline[MAX_PATH]; 66 PROCESS_INFORMATION pi; 67 BOOL ret; 68 STARTUPINFOA si = { 0 }; 69 si.cb = sizeof(si); 70 71 winetest_get_mainargs( &argv ); 72 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg); 73 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 74 ok(ret, "error: %lu\n", GetLastError()); 75 ret = CloseHandle(pi.hThread); 76 ok(ret, "error %lu\n", GetLastError()); 77 return pi.hProcess; 78} 79 80static void test_VirtualAllocEx(void) 81{ 82 const unsigned int alloc_size = 1<<15; 83 char *src, *dst; 84 SIZE_T bytes_written = 0, bytes_read = 0, i; 85 void *addr1, *addr2; 86 BOOL b, ret; 87 DWORD old_prot; 88 MEMORY_BASIC_INFORMATION info; 89 HANDLE hProcess; 90 NTSTATUS status; 91 92 /* Same process */ 93 addr1 = VirtualAllocEx(GetCurrentProcess(), NULL, alloc_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 94 ok(!!addr1, "Failed to allocated, error %lu.\n", GetLastError()); 95 ret = VirtualFreeEx(NULL, addr1, 0, MEM_RELEASE); 96 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Unexpected value %d, error %lu.\n", ret, GetLastError()); 97 addr2 = VirtualAllocEx(NULL, NULL, alloc_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 98 ok(!addr2 && GetLastError() == ERROR_INVALID_HANDLE, "Unexpected value %p, error %lu.\n", addr2, GetLastError()); 99 ret = VirtualFreeEx(GetCurrentProcess(), addr1, 0, MEM_RELEASE); 100 ok(ret, "Unexpected value %d, error %lu.\n", ret, GetLastError()); 101 102 hProcess = create_target_process("sleep"); 103 ok(hProcess != NULL, "Can't start process\n"); 104 105 SetLastError(0xdeadbeef); 106 addr1 = VirtualAllocEx(hProcess, NULL, alloc_size, MEM_COMMIT, 107 PAGE_EXECUTE_READWRITE); 108 ok(addr1 != NULL, "VirtualAllocEx error %lu\n", GetLastError()); 109 110 src = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE ); 111 dst = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE ); 112 for (i = 0; i < alloc_size; i++) 113 src[i] = i & 0xff; 114 115 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written); 116 ok(b && (bytes_written == alloc_size), "%Iu bytes written\n", 117 bytes_written); 118 b = ReadProcessMemory(hProcess, addr1, dst, alloc_size, &bytes_read); 119 ok(b && (bytes_read == alloc_size), "%Iu bytes read\n", bytes_read); 120 ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n"); 121 bytes_written = 0xdeadbeef; 122 status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written ); 123 ok( status == STATUS_SUCCESS, "wrong status %lx\n", status ); 124 ok( bytes_written == alloc_size, "%Iu bytes written\n", bytes_written ); 125 bytes_read = 0xdeadbeef; 126 memset( dst, 0, alloc_size ); 127 status = pNtReadVirtualMemory( hProcess, addr1, dst, alloc_size, &bytes_read ); 128 ok( status == STATUS_SUCCESS, "wrong status %lx\n", status ); 129 ok( bytes_read == alloc_size, "%Iu bytes read\n", bytes_read ); 130 ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n"); 131 132 /* test 0 length */ 133 bytes_written = 0xdeadbeef; 134 b = WriteProcessMemory(hProcess, addr1, src, 0, &bytes_written); 135 ok((b && !bytes_written) || broken(!b && GetLastError() == ERROR_INVALID_PARAMETER), "write failed: %lu\n", GetLastError()); 136 bytes_read = 0xdeadbeef; 137 b = ReadProcessMemory(hProcess, addr1, src, 0, &bytes_read); 138 ok(b && !bytes_read, "read failed: %lu\n", GetLastError()); 139 bytes_written = 0xdeadbeef; 140 status = pNtWriteVirtualMemory( hProcess, addr1, src, 0, &bytes_written ); 141 ok( status == STATUS_SUCCESS, "wrong status %lx\n", status ); 142 ok( bytes_written == 0, "%Iu bytes written\n", bytes_written ); 143 bytes_read = 0xdeadbeef; 144 status = pNtReadVirtualMemory( hProcess, addr1, src, 0, &bytes_read ); 145 ok( status == STATUS_SUCCESS, "wrong status %lx\n", status ); 146 ok( !bytes_read, "%Iu bytes read\n", bytes_read ); 147 148 /* test invalid source buffers */ 149 150 b = VirtualProtect( src + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot ); 151 ok( b, "VirtualProtect failed error %lu\n", GetLastError() ); 152 bytes_written = 0xdeadbeef; 153 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written); 154 ok( !b, "WriteProcessMemory succeeded\n" ); 155 ok( GetLastError() == ERROR_NOACCESS || 156 GetLastError() == ERROR_PARTIAL_COPY, /* vista */ 157 "wrong error %lu\n", GetLastError() ); 158 ok( bytes_written == 0, "%Iu bytes written\n", bytes_written ); 159 bytes_read = 0xdeadbeef; 160 b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read); 161 ok( !b, "ReadProcessMemory succeeded\n" ); 162 ok( GetLastError() == ERROR_NOACCESS || 163 GetLastError() == ERROR_PARTIAL_COPY, /* win10 v1607+ */ 164 "wrong error %lu\n", GetLastError() ); 165 if (GetLastError() == ERROR_NOACCESS) 166 ok( bytes_read == 0, "%Iu bytes read\n", bytes_read ); 167 else 168 ok( bytes_read == 0x2000, "%Iu bytes read\n", bytes_read ); 169 bytes_written = 0xdeadbeef; 170 status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written ); 171 ok( status == STATUS_PARTIAL_COPY, "wrong status %lx\n", status ); 172 ok( bytes_written == 0, "%Iu bytes written\n", bytes_written ); 173 bytes_read = 0xdeadbeef; 174 status = pNtReadVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_read ); 175 ok( status == STATUS_PARTIAL_COPY || status == STATUS_ACCESS_VIOLATION, "wrong status %lx\n", status ); 176 ok( bytes_read == (status == STATUS_PARTIAL_COPY ? 0x2000 : 0), "%Iu bytes read\n", bytes_read ); 177 178 b = VirtualProtect( src, 0x2000, PAGE_NOACCESS, &old_prot ); 179 ok( b, "VirtualProtect failed error %lu\n", GetLastError() ); 180 bytes_written = 0xdeadbeef; 181 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written); 182 ok( !b, "WriteProcessMemory succeeded\n" ); 183 ok( GetLastError() == ERROR_NOACCESS || 184 GetLastError() == ERROR_PARTIAL_COPY, /* vista */ 185 "wrong error %lu\n", GetLastError() ); 186 ok( bytes_written == 0, "%Iu bytes written\n", bytes_written ); 187 bytes_read = 0xdeadbeef; 188 b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read); 189 ok( !b, "ReadProcessMemory succeeded\n" ); 190 ok( GetLastError() == ERROR_NOACCESS || 191 GetLastError() == ERROR_PARTIAL_COPY, /* win10 v1607+ */ 192 "wrong error %lu\n", GetLastError() ); 193 ok( bytes_read == 0, "%Iu bytes read\n", bytes_read ); 194 bytes_written = 0xdeadbeef; 195 status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written ); 196 ok( status == STATUS_PARTIAL_COPY, "wrong status %lx\n", status ); 197 ok( bytes_written == 0, "%Iu bytes written\n", bytes_written ); 198 bytes_read = 0xdeadbeef; 199 status = pNtReadVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_read ); 200 ok( status == STATUS_PARTIAL_COPY || status == STATUS_ACCESS_VIOLATION, "wrong status %lx\n", status ); 201 ok( bytes_read == 0, "%Iu bytes read\n", bytes_read ); 202 b = VirtualProtect( src, alloc_size, PAGE_READWRITE, &old_prot ); 203 ok( b, "VirtualProtect failed error %lu\n", GetLastError() ); 204 205 /* test readonly buffers */ 206 207 b = VirtualProtectEx( hProcess, addr1, alloc_size, PAGE_READONLY, &old_prot ); 208 ok( b, "VirtualProtectEx, error %lu\n", GetLastError() ); 209 bytes_written = 0xdeadbeef; 210 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written); 211 ok( !b, "WriteProcessMemory succeeded\n" ); 212 if (!b) ok( GetLastError() == ERROR_NOACCESS, "wrong error %lu\n", GetLastError() ); 213 ok( bytes_written == 0xdeadbeef, "%Iu bytes written\n", bytes_written ); 214 status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written ); 215 todo_wine 216 ok( status == STATUS_PARTIAL_COPY || broken(status == STATUS_ACCESS_VIOLATION), 217 "wrong status %lx\n", status ); 218 todo_wine 219 ok( bytes_written == 0, "%Iu bytes written\n", bytes_written ); 220 221 b = VirtualProtectEx( hProcess, addr1, alloc_size, PAGE_EXECUTE_READ, &old_prot ); 222 ok( b, "VirtualProtectEx, error %lu\n", GetLastError() ); 223 bytes_written = 0xdeadbeef; 224 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written); 225 ok( b, "WriteProcessMemory failed\n" ); 226 ok( bytes_written == alloc_size, "%Iu bytes written\n", bytes_written ); 227 bytes_written = 0xdeadbeef; 228 status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written ); 229 todo_wine 230 ok( status == STATUS_PARTIAL_COPY || broken(status == STATUS_ACCESS_VIOLATION), 231 "wrong status %lx\n", status ); 232 todo_wine 233 ok( bytes_written == 0, "%Iu bytes written\n", bytes_written ); 234 235 b = VirtualProtectEx( hProcess, addr1, 0x2000, PAGE_EXECUTE_READWRITE, &old_prot ); 236 ok( b, "VirtualProtectEx, error %lu\n", GetLastError() ); 237 bytes_written = 0xdeadbeef; 238 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written); 239 todo_wine 240 ok( !b || broken(b), /* <= win10 1507 */ "WriteProcessMemory succeeded\n" ); 241 bytes_written = 0xdeadbeef; 242 status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written ); 243 todo_wine 244 ok( status == STATUS_PARTIAL_COPY || broken(status == STATUS_SUCCESS), /* <= win10 1507 */ 245 "wrong status %lx\n", status ); 246 ok( bytes_written == (status ? 0x2000 : alloc_size), "%Iu bytes written\n", bytes_written ); 247 248 b = VirtualProtectEx( hProcess, (char *)addr1 + 0x2000, alloc_size - 0x2000, PAGE_READONLY, &old_prot ); 249 ok( b, "VirtualProtectEx, error %lu\n", GetLastError() ); 250 bytes_written = 0xdeadbeef; 251 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written); 252 todo_wine 253 ok( !b || broken(b), /* <= win10 1507 */ "WriteProcessMemory succeeded\n" ); 254 status = pNtWriteVirtualMemory( hProcess, addr1, src, alloc_size, &bytes_written ); 255 todo_wine 256 ok( status == STATUS_PARTIAL_COPY || broken(status == STATUS_SUCCESS), /* <= win10 1507 */ 257 "wrong status %lx\n", status ); 258 ok( bytes_written == (status ? 0x2000 : alloc_size), "%Iu bytes written\n", bytes_written ); 259 260 VirtualFree( src, 0, MEM_RELEASE ); 261 VirtualFree( dst, 0, MEM_RELEASE ); 262 263 /* 264 * The following tests parallel those in test_VirtualAlloc() 265 */ 266 267 SetLastError(0xdeadbeef); 268 addr1 = VirtualAllocEx(hProcess, 0, 0, MEM_RESERVE, PAGE_NOACCESS); 269 ok(addr1 == NULL, "VirtualAllocEx should fail on zero-sized allocation\n"); 270 ok(GetLastError() == ERROR_INVALID_PARAMETER, 271 "got %lu, expected ERROR_INVALID_PARAMETER\n", GetLastError()); 272 273 addr1 = VirtualAllocEx(hProcess, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS); 274 ok(addr1 != NULL, "VirtualAllocEx failed\n"); 275 276 /* test a not committed memory */ 277 memset(&info, 'q', sizeof(info)); 278 ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info), "VirtualQueryEx failed\n"); 279 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1); 280 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1); 281 ok(info.AllocationProtect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.AllocationProtect); 282 ok(info.RegionSize == 0x10000, "%Ix != 0x10000\n", info.RegionSize); 283 ok(info.State == MEM_RESERVE, "%lx != MEM_RESERVE\n", info.State); 284 ok(info.Protect == 0, "%lx != PAGE_NOACCESS\n", info.Protect); 285 ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type); 286 287 SetLastError(0xdeadbeef); 288 ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot), 289 "VirtualProtectEx should fail on a not committed memory\n"); 290 ok(GetLastError() == ERROR_INVALID_ADDRESS, 291 "got %lu, expected ERROR_INVALID_ADDRESS\n", GetLastError()); 292 293 addr2 = VirtualAllocEx(hProcess, addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS); 294 ok(addr1 == addr2, "VirtualAllocEx failed\n"); 295 296 /* test a committed memory */ 297 ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info), 298 "VirtualQueryEx failed\n"); 299 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1); 300 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1); 301 ok(info.AllocationProtect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.AllocationProtect); 302 ok(info.RegionSize == 0x1000, "%Ix != 0x1000\n", info.RegionSize); 303 ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State); 304 /* this time NT reports PAGE_NOACCESS as well */ 305 ok(info.Protect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.Protect); 306 ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type); 307 308 /* this should fail, since not the whole range is committed yet */ 309 SetLastError(0xdeadbeef); 310 ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot), 311 "VirtualProtectEx should fail on a not committed memory\n"); 312 ok(GetLastError() == ERROR_INVALID_ADDRESS, 313 "got %lu, expected ERROR_INVALID_ADDRESS\n", GetLastError()); 314 315 old_prot = 0; 316 ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtectEx failed\n"); 317 ok(old_prot == PAGE_NOACCESS, "wrong old protection: got %04lx instead of PAGE_NOACCESS\n", old_prot); 318 319 old_prot = 0; 320 ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtectEx failed\n"); 321 ok(old_prot == PAGE_READONLY, "wrong old protection: got %04lx instead of PAGE_READONLY\n", old_prot); 322 323 ok(!VirtualFreeEx(hProcess, addr1, 0x10000, 0), 324 "VirtualFreeEx should fail with type 0\n"); 325 ok(GetLastError() == ERROR_INVALID_PARAMETER, 326 "got %lu, expected ERROR_INVALID_PARAMETER\n", GetLastError()); 327 328 ok(VirtualFreeEx(hProcess, addr1, 0x10000, MEM_DECOMMIT), "VirtualFreeEx failed\n"); 329 330 /* if the type is MEM_RELEASE, size must be 0 */ 331 ok(!VirtualFreeEx(hProcess, addr1, 1, MEM_RELEASE), 332 "VirtualFreeEx should fail\n"); 333 ok(GetLastError() == ERROR_INVALID_PARAMETER, 334 "got %lu, expected ERROR_INVALID_PARAMETER\n", GetLastError()); 335 336 ok(VirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE), "VirtualFreeEx failed\n"); 337 338 TerminateProcess(hProcess, 0); 339 CloseHandle(hProcess); 340} 341 342static void test_VirtualAlloc(void) 343{ 344 void *addr1, *addr2; 345 DWORD old_prot; 346 MEMORY_BASIC_INFORMATION info; 347 348 SetLastError(0xdeadbeef); 349 addr1 = VirtualAlloc(0, 0, MEM_RESERVE, PAGE_NOACCESS); 350 ok(addr1 == NULL, "VirtualAlloc should fail on zero-sized allocation\n"); 351 ok(GetLastError() == ERROR_INVALID_PARAMETER, 352 "got %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError()); 353 354 addr1 = VirtualAlloc(0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS); 355 ok(addr1 != NULL, "VirtualAlloc failed\n"); 356 357 /* test a not committed memory */ 358 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), 359 "VirtualQuery failed\n"); 360 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1); 361 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1); 362 ok(info.AllocationProtect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.AllocationProtect); 363 ok(info.RegionSize == 0x10000, "%Ix != 0x10000\n", info.RegionSize); 364 ok(info.State == MEM_RESERVE, "%lx != MEM_RESERVE\n", info.State); 365 ok(info.Protect == 0, "%lx != PAGE_NOACCESS\n", info.Protect); 366 ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type); 367 368 SetLastError(0xdeadbeef); 369 ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot), 370 "VirtualProtect should fail on a not committed memory\n"); 371 ok( GetLastError() == ERROR_INVALID_ADDRESS, 372 "got %ld, expected ERROR_INVALID_ADDRESS\n", GetLastError()); 373 374 addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS); 375 ok(addr1 == addr2, "VirtualAlloc failed\n"); 376 377 /* test a committed memory */ 378 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), 379 "VirtualQuery failed\n"); 380 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1); 381 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1); 382 ok(info.AllocationProtect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.AllocationProtect); 383 ok(info.RegionSize == 0x1000, "%Ix != 0x1000\n", info.RegionSize); 384 ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State); 385 /* this time NT reports PAGE_NOACCESS as well */ 386 ok(info.Protect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.Protect); 387 ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type); 388 389 /* this should fail, since not the whole range is committed yet */ 390 SetLastError(0xdeadbeef); 391 ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot), 392 "VirtualProtect should fail on a not committed memory\n"); 393 ok( GetLastError() == ERROR_INVALID_ADDRESS, 394 "got %ld, expected ERROR_INVALID_ADDRESS\n", GetLastError()); 395 396 ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtect failed\n"); 397 ok(old_prot == PAGE_NOACCESS, 398 "wrong old protection: got %04lx instead of PAGE_NOACCESS\n", old_prot); 399 400 ok(VirtualProtect(addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtect failed\n"); 401 ok(old_prot == PAGE_READONLY, 402 "wrong old protection: got %04lx instead of PAGE_READONLY\n", old_prot); 403 404 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), 405 "VirtualQuery failed\n"); 406 ok(info.RegionSize == 0x1000, "%Ix != 0x1000\n", info.RegionSize); 407 ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State); 408 ok(info.Protect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.Protect); 409 memset( addr1, 0x55, 20 ); 410 ok( *(DWORD *)addr1 == 0x55555555, "wrong data %lx\n", *(DWORD *)addr1 ); 411 412 addr2 = VirtualAlloc( addr1, 0x1000, MEM_RESET, PAGE_NOACCESS ); 413 ok( addr2 == addr1, "VirtualAlloc failed err %lu\n", GetLastError() ); 414 ok( *(DWORD *)addr1 == 0x55555555 || *(DWORD *)addr1 == 0, "wrong data %lx\n", *(DWORD *)addr1 ); 415 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), 416 "VirtualQuery failed\n"); 417 ok(info.RegionSize == 0x1000, "%Ix != 0x1000\n", info.RegionSize); 418 ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State); 419 ok(info.Protect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.Protect); 420 421 addr2 = VirtualAlloc( (char *)addr1 + 0x1000, 0x1000, MEM_RESET, PAGE_NOACCESS ); 422 ok( (char *)addr2 == (char *)addr1 + 0x1000, "VirtualAlloc failed\n" ); 423 424 ok(VirtualQuery(addr2, &info, sizeof(info)) == sizeof(info), 425 "VirtualQuery failed\n"); 426 ok(info.RegionSize == 0xf000, "%Ix != 0xf000\n", info.RegionSize); 427 ok(info.State == MEM_RESERVE, "%lx != MEM_RESERVE\n", info.State); 428 ok(info.Protect == 0, "%lx != 0\n", info.Protect); 429 430 addr2 = VirtualAlloc( (char *)addr1 + 0xf000, 0x2000, MEM_RESET, PAGE_NOACCESS ); 431 ok( !addr2, "VirtualAlloc failed\n" ); 432 ok( GetLastError() == ERROR_INVALID_ADDRESS, "wrong error %lu\n", GetLastError() ); 433 434 /* invalid protection values */ 435 SetLastError(0xdeadbeef); 436 addr2 = VirtualAlloc(NULL, 0x1000, MEM_RESERVE, 0); 437 ok(!addr2, "VirtualAlloc succeeded\n"); 438 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError()); 439 440 SetLastError(0xdeadbeef); 441 addr2 = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, 0); 442 ok(!addr2, "VirtualAlloc succeeded\n"); 443 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError()); 444 445 SetLastError(0xdeadbeef); 446 addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_READONLY | PAGE_EXECUTE); 447 ok(!addr2, "VirtualAlloc succeeded\n"); 448 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError()); 449 450 SetLastError(0xdeadbeef); 451 ok(!VirtualProtect(addr1, 0x1000, PAGE_READWRITE | PAGE_EXECUTE_WRITECOPY, &old_prot), 452 "VirtualProtect succeeded\n"); 453 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError()); 454 455 SetLastError(0xdeadbeef); 456 ok(!VirtualProtect(addr1, 0x1000, 0, &old_prot), "VirtualProtect succeeded\n"); 457 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError()); 458 459 SetLastError(0xdeadbeef); 460 ok(!VirtualFree(addr1, 0x10000, 0), "VirtualFree should fail with type 0\n"); 461 ok(GetLastError() == ERROR_INVALID_PARAMETER, 462 "got %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError()); 463 464 SetLastError(0xdeadbeef); 465 ok(!VirtualFree(addr1, 0, MEM_FREE), "VirtualFree should fail with type MEM_FREE\n"); 466 ok(GetLastError() == ERROR_INVALID_PARAMETER, 467 "got %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError()); 468 469 ok(VirtualFree(addr1, 0x10000, MEM_DECOMMIT), "VirtualFree failed\n"); 470 471 /* if the type is MEM_RELEASE, size must be 0 */ 472 ok(!VirtualFree(addr1, 1, MEM_RELEASE), "VirtualFree should fail\n"); 473 ok(GetLastError() == ERROR_INVALID_PARAMETER, 474 "got %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError()); 475 476 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n"); 477 478 /* PAGE_NOCACHE cannot be set per page in recent Windows */ 479 addr1 = VirtualAlloc( NULL, 0x2000, MEM_COMMIT, PAGE_READWRITE | PAGE_NOCACHE ); 480 ok( addr1 != NULL, "VirtualAlloc failed\n"); 481 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n"); 482 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1); 483 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1); 484 ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE), 485 "wrong protect %lx\n", info.AllocationProtect); 486 ok(info.RegionSize == 0x2000, "wrong size %Ix\n", info.RegionSize); 487 ok(info.State == MEM_COMMIT, "wrong state %lx\n", info.State); 488 ok(info.Protect == (PAGE_READWRITE | PAGE_NOCACHE), "wrong protect %lx\n", info.Protect); 489 ok(info.Type == MEM_PRIVATE, "wrong type %lx\n", info.Type); 490 491 ok(VirtualProtect(addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtect failed\n"); 492 ok( old_prot == (PAGE_READWRITE | PAGE_NOCACHE), "wrong protect %lx\n", old_prot ); 493 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n"); 494 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1); 495 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1); 496 ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE), 497 "wrong protect %lx\n", info.AllocationProtect); 498 ok(info.RegionSize == 0x2000 || broken(info.RegionSize == 0x1000), 499 "wrong size %Ix\n", info.RegionSize); 500 ok(info.State == MEM_COMMIT, "wrong state %lx\n", info.State); 501 ok(info.Protect == (PAGE_READWRITE | PAGE_NOCACHE) || broken(info.Protect == PAGE_READWRITE), 502 "wrong protect %lx\n", info.Protect); 503 ok(info.Type == MEM_PRIVATE, "wrong type %lx\n", info.Type); 504 505 ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtect failed\n"); 506 ok( old_prot == (PAGE_READWRITE | PAGE_NOCACHE) || broken(old_prot == PAGE_READWRITE), 507 "wrong protect %lx\n", old_prot ); 508 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n"); 509 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1); 510 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1); 511 ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE), 512 "wrong protect %lx\n", info.AllocationProtect); 513 ok(info.RegionSize == 0x1000, "wrong size %Ix\n", info.RegionSize); 514 ok(info.State == MEM_COMMIT, "wrong state %lx\n", info.State); 515 ok(info.Protect == (PAGE_READONLY | PAGE_NOCACHE) || broken(info.Protect == PAGE_READONLY), 516 "wrong protect %lx\n", info.Protect); 517 ok(info.Type == MEM_PRIVATE, "wrong type %lx\n", info.Type); 518 519 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n"); 520 521 addr1 = VirtualAlloc( NULL, 0x2000, MEM_COMMIT, PAGE_READWRITE ); 522 ok( addr1 != NULL, "VirtualAlloc failed\n"); 523 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n"); 524 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1); 525 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1); 526 ok(info.AllocationProtect == PAGE_READWRITE, 527 "wrong protect %lx\n", info.AllocationProtect); 528 ok(info.RegionSize == 0x2000, "wrong size %Ix\n", info.RegionSize); 529 ok(info.State == MEM_COMMIT, "wrong state %lx\n", info.State); 530 ok(info.Protect == PAGE_READWRITE, "wrong protect %lx\n", info.Protect); 531 ok(info.Type == MEM_PRIVATE, "wrong type %lx\n", info.Type); 532 533 ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY | PAGE_NOCACHE, &old_prot), "VirtualProtect failed\n"); 534 ok( old_prot == PAGE_READWRITE, "wrong protect %lx\n", old_prot ); 535 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n"); 536 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1); 537 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1); 538 ok(info.AllocationProtect == PAGE_READWRITE, "wrong protect %lx\n", info.AllocationProtect); 539 ok(info.RegionSize == 0x1000, "wrong size %Ix\n", info.RegionSize); 540 ok(info.State == MEM_COMMIT, "wrong state %lx\n", info.State); 541 ok(info.Protect == PAGE_READONLY || broken(info.Protect == (PAGE_READONLY | PAGE_NOCACHE)), 542 "wrong protect %lx\n", info.Protect); 543 ok(info.Type == MEM_PRIVATE, "wrong type %lx\n", info.Type); 544 545 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n"); 546 547 /* memory returned by VirtualAlloc should be aligned to 64k */ 548 addr1 = VirtualAlloc(0, 0x2000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 549 ok(addr1 != NULL, "VirtualAlloc failed\n"); 550 ok(!((ULONG_PTR)addr1 & 0xffff), "returned memory %p is not aligned to 64k\n", addr1); 551 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n"); 552 addr2 = VirtualAlloc(addr1, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 553 ok(addr2 == addr1, "VirtualAlloc returned %p, expected %p\n", addr2, addr1); 554 555 /* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */ 556 SetLastError(0xdeadbeef); 557 addr2 = VirtualAlloc(addr1, 0x1000, MEM_RESERVE | MEM_COMMIT | AT_ROUND_TO_PAGE, PAGE_EXECUTE_READWRITE); 558 ok(!addr2, "VirtualAlloc unexpectedly succeeded\n"); 559 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError()); 560 561 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n"); 562} 563 564static void test_MapViewOfFile(void) 565{ 566 static const char testfile[] = "testfile.xxx"; 567 const char *name; 568 HANDLE file, mapping, map2; 569 void *ptr, *ptr2, *addr; 570 SECTION_BASIC_INFORMATION section_info; 571 SECTION_IMAGE_INFORMATION image_info; 572 MEMORY_BASIC_INFORMATION info; 573 BOOL ret; 574 SIZE_T size; 575 NTSTATUS status; 576 SIZE_T info_size; 577 LARGE_INTEGER map_size; 578 579 SetLastError(0xdeadbeef); 580 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); 581 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError() ); 582 SetFilePointer( file, 12288, NULL, FILE_BEGIN ); 583 SetEndOfFile( file ); 584 585 /* read/write mapping */ 586 587 SetLastError(0xdeadbeef); 588 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL ); 589 ok( mapping != 0, "CreateFileMapping error %lu\n", GetLastError() ); 590 591 SetLastError(0xdeadbeef); 592 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 ); 593 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); 594 UnmapViewOfFile( ptr ); 595 596 SetLastError(0xdeadbeef); 597 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 ); 598 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %lu\n", GetLastError() ); 599 UnmapViewOfFile( ptr ); 600 601 SetLastError(0xdeadbeef); 602 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 ); 603 ok( ptr != NULL, "MapViewOfFile 0 error %lu\n", GetLastError() ); 604 UnmapViewOfFile( ptr ); 605 606 SetLastError(0xdeadbeef); 607 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 ); 608 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %lu\n", GetLastError() ); 609 UnmapViewOfFile( ptr ); 610 611 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2, 612 FILE_MAP_READ|FILE_MAP_WRITE, FALSE, 0 ); 613 ok( ret, "DuplicateHandle failed error %lu\n", GetLastError()); 614 ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 ); 615 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %lu\n", GetLastError() ); 616 UnmapViewOfFile( ptr ); 617 CloseHandle( map2 ); 618 619 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2, 620 FILE_MAP_READ, FALSE, 0 ); 621 ok( ret, "DuplicateHandle failed error %lu\n", GetLastError()); 622 SetLastError(0xdeadbeef); 623 ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 ); 624 ok( !ptr, "MapViewOfFile succeeded\n" ); 625 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %ld\n", GetLastError() ); 626 CloseHandle( map2 ); 627 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2, 0, FALSE, 0 ); 628 ok( ret, "DuplicateHandle failed error %lu\n", GetLastError()); 629 SetLastError(0xdeadbeef); 630 ptr = MapViewOfFile( map2, 0, 0, 0, 4096 ); 631 ok( !ptr, "MapViewOfFile succeeded\n" ); 632 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %ld\n", GetLastError() ); 633 CloseHandle( map2 ); 634 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2, 635 FILE_MAP_READ, FALSE, 0 ); 636 ok( ret, "DuplicateHandle failed error %lu\n", GetLastError()); 637 ptr = MapViewOfFile( map2, 0, 0, 0, 4096 ); 638 ok( ptr != NULL, "MapViewOfFile NO_ACCESS error %lu\n", GetLastError() ); 639 640 UnmapViewOfFile( ptr ); 641 CloseHandle( map2 ); 642 CloseHandle( mapping ); 643 644 /* read-only mapping */ 645 646 SetLastError(0xdeadbeef); 647 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL ); 648 ok( mapping != 0, "CreateFileMapping error %lu\n", GetLastError() ); 649 650 SetLastError(0xdeadbeef); 651 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 ); 652 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); 653 UnmapViewOfFile( ptr ); 654 655 SetLastError(0xdeadbeef); 656 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 ); 657 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %lu\n", GetLastError() ); 658 UnmapViewOfFile( ptr ); 659 660 SetLastError(0xdeadbeef); 661 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 ); 662 ok( ptr != NULL, "MapViewOfFile 0 error %lu\n", GetLastError() ); 663 UnmapViewOfFile( ptr ); 664 665 SetLastError(0xdeadbeef); 666 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 ); 667 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" ); 668 ok( GetLastError() == ERROR_INVALID_PARAMETER || 669 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %ld\n", GetLastError() ); 670 CloseHandle( mapping ); 671 672 /* copy-on-write mapping */ 673 674 SetLastError(0xdeadbeef); 675 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL ); 676 ok( mapping != 0, "CreateFileMapping error %lu\n", GetLastError() ); 677 678 SetLastError(0xdeadbeef); 679 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 ); 680 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); 681 UnmapViewOfFile( ptr ); 682 683 SetLastError(0xdeadbeef); 684 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 ); 685 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %lu\n", GetLastError() ); 686 UnmapViewOfFile( ptr ); 687 688 SetLastError(0xdeadbeef); 689 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 ); 690 ok( ptr != NULL, "MapViewOfFile 0 error %lu\n", GetLastError() ); 691 UnmapViewOfFile( ptr ); 692 693 SetLastError(0xdeadbeef); 694 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 ); 695 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" ); 696 ok( GetLastError() == ERROR_INVALID_PARAMETER || 697 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %ld\n", GetLastError() ); 698 CloseHandle( mapping ); 699 700 /* no access mapping */ 701 702 SetLastError(0xdeadbeef); 703 mapping = CreateFileMappingA( file, NULL, PAGE_NOACCESS, 0, 4096, NULL ); 704 ok( !mapping, "CreateFileMappingA succeeded\n" ); 705 ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %ld\n", GetLastError() ); 706 CloseHandle( file ); 707 708 /* now try read-only file */ 709 710 SetLastError(0xdeadbeef); 711 file = CreateFileA( testfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 ); 712 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError() ); 713 714 SetLastError(0xdeadbeef); 715 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL ); 716 ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" ); 717 ok( GetLastError() == ERROR_INVALID_PARAMETER || 718 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %ld\n", GetLastError() ); 719 720 SetLastError(0xdeadbeef); 721 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL ); 722 ok( mapping != 0, "CreateFileMapping PAGE_WRITECOPY error %lu\n", GetLastError() ); 723 CloseHandle( mapping ); 724 725 SetLastError(0xdeadbeef); 726 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL ); 727 ok( mapping != 0, "CreateFileMapping PAGE_READONLY error %lu\n", GetLastError() ); 728 CloseHandle( mapping ); 729 CloseHandle( file ); 730 731 /* now try no access file */ 732 733 SetLastError(0xdeadbeef); 734 file = CreateFileA( testfile, 0, 0, NULL, OPEN_EXISTING, 0, 0 ); 735 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError() ); 736 737 SetLastError(0xdeadbeef); 738 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL ); 739 ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" ); 740 ok( GetLastError() == ERROR_INVALID_PARAMETER || 741 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %ld\n", GetLastError() ); 742 743 SetLastError(0xdeadbeef); 744 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL ); 745 ok( !mapping, "CreateFileMapping PAGE_WRITECOPY succeeded\n" ); 746 ok( GetLastError() == ERROR_INVALID_PARAMETER || 747 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %ld\n", GetLastError() ); 748 749 SetLastError(0xdeadbeef); 750 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL ); 751 ok( !mapping, "CreateFileMapping PAGE_READONLY succeeded\n" ); 752 ok( GetLastError() == ERROR_INVALID_PARAMETER || 753 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %ld\n", GetLastError() ); 754 755 CloseHandle( file ); 756 DeleteFileA( testfile ); 757 758 SetLastError(0xdeadbeef); 759 name = "Local\\Foo"; 760 file = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4090, name ); 761 /* nt4 doesn't have Local\\ */ 762 if (!file && GetLastError() == ERROR_PATH_NOT_FOUND) 763 { 764 name = "Foo"; 765 file = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4090, name ); 766 } 767 ok( file != 0, "CreateFileMapping PAGE_READWRITE error %lu\n", GetLastError() ); 768 769 SetLastError(0xdeadbeef); 770 mapping = OpenFileMappingA( FILE_MAP_READ, FALSE, name ); 771 ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %lu\n", GetLastError() ); 772 SetLastError(0xdeadbeef); 773 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 ); 774 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" ); 775 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %ld\n", GetLastError() ); 776 SetLastError(0xdeadbeef); 777 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); 778 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); 779 SetLastError(0xdeadbeef); 780 size = VirtualQuery( ptr, &info, sizeof(info) ); 781 ok( size == sizeof(info), 782 "VirtualQuery error %lu\n", GetLastError() ); 783 ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr ); 784 ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr ); 785 ok( info.AllocationProtect == PAGE_READONLY, "%lx != PAGE_READONLY\n", info.AllocationProtect ); 786 ok( info.RegionSize == 4096, "%Ix != 4096\n", info.RegionSize ); 787 ok( info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State ); 788 ok( info.Protect == PAGE_READONLY, "%lx != PAGE_READONLY\n", info.Protect ); 789 UnmapViewOfFile( ptr ); 790 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, 791 sizeof(section_info), &info_size ); 792 ok( status == STATUS_ACCESS_DENIED, "NtQuerySection failed err %lx\n", status ); 793 CloseHandle( mapping ); 794 mapping = OpenFileMappingA( FILE_MAP_READ | SECTION_QUERY, FALSE, name ); 795 ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %lu\n", GetLastError() ); 796 info_size = (SIZE_T)0xdeadbeef << 16; 797 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, 798 sizeof(section_info), &info_size ); 799 ok( !status, "NtQuerySection failed err %lx\n", status ); 800 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %Iu\n", info_size ); 801 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08lx\n", 802 section_info.Attributes ); 803 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); 804 ok( section_info.Size.QuadPart == info.RegionSize, "NtQuerySection wrong size %lx%08lx / %08Ix\n", 805 section_info.Size.u.HighPart, section_info.Size.u.LowPart, info.RegionSize ); 806 CloseHandle( mapping ); 807 808 SetLastError(0xdeadbeef); 809 mapping = OpenFileMappingA( FILE_MAP_WRITE, FALSE, name ); 810 ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %lu\n", GetLastError() ); 811 SetLastError(0xdeadbeef); 812 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); 813 ok( !ptr, "MapViewOfFile succeeded\n" ); 814 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %ld\n", GetLastError() ); 815 SetLastError(0xdeadbeef); 816 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 ); 817 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %lu\n", GetLastError() ); 818 SetLastError(0xdeadbeef); 819 size = VirtualQuery( ptr, &info, sizeof(info) ); 820 ok( size == sizeof(info), 821 "VirtualQuery error %lu\n", GetLastError() ); 822 ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr ); 823 ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr ); 824 ok( info.AllocationProtect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.AllocationProtect ); 825 ok( info.RegionSize == 4096, "%Ix != 4096\n", info.RegionSize ); 826 ok( info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State ); 827 ok( info.Protect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.Protect ); 828 UnmapViewOfFile( ptr ); 829 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, 830 sizeof(section_info), &info_size ); 831 ok( status == STATUS_ACCESS_DENIED, "NtQuerySection failed err %lx\n", status ); 832 CloseHandle( mapping ); 833 834 mapping = OpenFileMappingA( FILE_MAP_WRITE | SECTION_QUERY, FALSE, name ); 835 ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %lu\n", GetLastError() ); 836 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, 837 sizeof(section_info), &info_size ); 838 ok( !status, "NtQuerySection failed err %lx\n", status ); 839 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %Iu\n", info_size ); 840 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08lx\n", 841 section_info.Attributes ); 842 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); 843 ok( section_info.Size.QuadPart == info.RegionSize, "NtQuerySection wrong size %lx%08lx / %08Ix\n", 844 section_info.Size.u.HighPart, section_info.Size.u.LowPart, info.RegionSize ); 845 CloseHandle( mapping ); 846 847 CloseHandle( file ); 848 849 /* read/write mapping with SEC_RESERVE */ 850 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_RESERVE, 0, MAPPING_SIZE, NULL); 851 ok(mapping != 0, "CreateFileMappingA failed with error %ld\n", GetLastError()); 852 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, 853 sizeof(section_info), NULL ); 854 ok( !status, "NtQuerySection failed err %lx\n", status ); 855 ok( section_info.Attributes == SEC_RESERVE, "NtQuerySection wrong attr %08lx\n", 856 section_info.Attributes ); 857 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); 858 ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %lx%08lx / %08x\n", 859 section_info.Size.u.HighPart, section_info.Size.u.LowPart, MAPPING_SIZE ); 860 861 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0); 862 ok(ptr != NULL, "MapViewOfFile failed with error %ld\n", GetLastError()); 863 864 ptr2 = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0); 865 ok( ptr2 != NULL, "MapViewOfFile failed with error %ld\n", GetLastError()); 866 ok( ptr != ptr2, "MapViewOfFile returned same pointer\n" ); 867 868 ret = VirtualQuery(ptr, &info, sizeof(info)); 869 ok(ret, "VirtualQuery failed with error %ld\n", GetLastError()); 870 ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress); 871 ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase); 872 ok(info.RegionSize == MAPPING_SIZE, "RegionSize should have been 0x%x but was 0x%Ix\n", MAPPING_SIZE, info.RegionSize); 873 ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%lx\n", info.State); 874 ok(info.AllocationProtect == PAGE_READWRITE, 875 "AllocationProtect should have been PAGE_READWRITE but was 0x%lx\n", info.AllocationProtect); 876 ok(info.Protect == 0, "Protect should have been 0 instead of 0x%lx\n", info.Protect); 877 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%lx\n", info.Type); 878 879 ret = VirtualQuery(ptr2, &info, sizeof(info)); 880 ok(ret, "VirtualQuery failed with error %ld\n", GetLastError()); 881 ok(info.BaseAddress == ptr2, 882 "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress); 883 ok(info.AllocationBase == ptr2, 884 "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase); 885 ok(info.AllocationProtect == PAGE_READWRITE, 886 "AllocationProtect should have been PAGE_READWRITE but was 0x%lx\n", info.AllocationProtect); 887 ok(info.RegionSize == MAPPING_SIZE, 888 "RegionSize should have been 0x%x but was 0x%Ix\n", MAPPING_SIZE, info.RegionSize); 889 ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%lx\n", info.State); 890 ok(info.Protect == 0, "Protect should have been 0 instead of 0x%lx\n", info.Protect); 891 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%lx\n", info.Type); 892 893 ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY); 894 ok(ptr != NULL, "VirtualAlloc failed with error %ld\n", GetLastError()); 895 896 ret = VirtualQuery(ptr, &info, sizeof(info)); 897 ok(ret, "VirtualQuery failed with error %ld\n", GetLastError()); 898 ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress); 899 ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase); 900 ok(info.RegionSize == 0x10000, "RegionSize should have been 0x10000 but was 0x%Ix\n", info.RegionSize); 901 ok(info.State == MEM_COMMIT, "State should have been MEM_COMMIT instead of 0x%lx\n", info.State); 902 ok(info.Protect == PAGE_READONLY, "Protect should have been PAGE_READONLY instead of 0x%lx\n", info.Protect); 903 ok(info.AllocationProtect == PAGE_READWRITE, 904 "AllocationProtect should have been PAGE_READWRITE but was 0x%lx\n", info.AllocationProtect); 905 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%lx\n", info.Type); 906 907 /* shows that the VirtualAlloc above affects the mapping, not just the 908 * virtual memory in this process - it also affects all other processes 909 * with a view of the mapping, but that isn't tested here */ 910 ret = VirtualQuery(ptr2, &info, sizeof(info)); 911 ok(ret, "VirtualQuery failed with error %ld\n", GetLastError()); 912 ok(info.BaseAddress == ptr2, 913 "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress); 914 ok(info.AllocationBase == ptr2, 915 "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase); 916 ok(info.AllocationProtect == PAGE_READWRITE, 917 "AllocationProtect should have been PAGE_READWRITE but was 0x%lx\n", info.AllocationProtect); 918 ok(info.RegionSize == 0x10000, 919 "RegionSize should have been 0x10000 but was 0x%Ix\n", info.RegionSize); 920 ok(info.State == MEM_COMMIT, 921 "State should have been MEM_COMMIT instead of 0x%lx\n", info.State); 922 ok(info.Protect == PAGE_READWRITE, 923 "Protect should have been PAGE_READWRITE instead of 0x%lx\n", info.Protect); 924 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%lx\n", info.Type); 925 926 addr = VirtualAlloc( ptr, MAPPING_SIZE, MEM_RESET, PAGE_READONLY ); 927 ok( addr == ptr, "VirtualAlloc failed with error %lu\n", GetLastError() ); 928 929 ret = VirtualFree( ptr, 0x10000, MEM_DECOMMIT ); 930 ok( !ret, "VirtualFree succeeded\n" ); 931 ok( GetLastError() == ERROR_INVALID_PARAMETER, "VirtualFree failed with %lu\n", GetLastError() ); 932 933 ret = UnmapViewOfFile(ptr2); 934 ok(ret, "UnmapViewOfFile failed with error %ld\n", GetLastError()); 935 ret = UnmapViewOfFile(ptr); 936 ok(ret, "UnmapViewOfFile failed with error %ld\n", GetLastError()); 937 CloseHandle(mapping); 938 939 /* same thing with SEC_COMMIT */ 940 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, MAPPING_SIZE, NULL); 941 ok(mapping != 0, "CreateFileMappingA failed with error %ld\n", GetLastError()); 942 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, 943 sizeof(section_info), NULL ); 944 ok( !status, "NtQuerySection failed err %lx\n", status ); 945 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08lx\n", 946 section_info.Attributes ); 947 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); 948 ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %lx%08lx / %08x\n", 949 section_info.Size.u.HighPart, section_info.Size.u.LowPart, MAPPING_SIZE ); 950 951 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0); 952 ok(ptr != NULL, "MapViewOfFile failed with error %ld\n", GetLastError()); 953 954 ret = VirtualQuery(ptr, &info, sizeof(info)); 955 ok(ret, "VirtualQuery failed with error %ld\n", GetLastError()); 956 ok(info.BaseAddress == ptr, "wrong BaseAddress %p/%p\n", ptr, info.BaseAddress); 957 ok(info.AllocationBase == ptr, "wrong AllocationBase %p/%p\n", ptr, info.AllocationBase); 958 ok(info.RegionSize == MAPPING_SIZE, "wrong RegionSize 0x%Ix\n", info.RegionSize); 959 ok(info.State == MEM_COMMIT, "wrong State 0x%lx\n", info.State); 960 ok(info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect 0x%lx\n", info.AllocationProtect); 961 ok(info.Protect == PAGE_READWRITE, "wrong Protect 0x%lx\n", info.Protect); 962 ok(info.Type == MEM_MAPPED, "wrong Type 0x%lx\n", info.Type); 963 964 ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY); 965 ok(ptr != NULL, "VirtualAlloc failed with error %ld\n", GetLastError()); 966 967 ret = VirtualQuery(ptr, &info, sizeof(info)); 968 ok(ret, "VirtualQuery failed with error %ld\n", GetLastError()); 969 ok(info.BaseAddress == ptr, "wrong BaseAddress %p/%p\n", ptr, info.BaseAddress); 970 ok(info.AllocationBase == ptr, "wrong AllocationBase %p/%p\n", ptr, info.AllocationBase); 971 ok(info.RegionSize == 0x10000, "wrong RegionSize 0x%Ix\n", info.RegionSize); 972 ok(info.State == MEM_COMMIT, "wrong State 0x%lx\n", info.State); 973 ok(info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect 0x%lx\n", info.AllocationProtect); 974 ok(info.Protect == PAGE_READONLY, "wrong Protect 0x%lx\n", info.Protect); 975 ok(info.Type == MEM_MAPPED, "wrong Type 0x%lx\n", info.Type); 976 977 addr = VirtualAlloc( ptr, MAPPING_SIZE, MEM_RESET, PAGE_READONLY ); 978 ok( addr == ptr, "VirtualAlloc failed with error %lu\n", GetLastError() ); 979 980 ret = VirtualFree( ptr, 0x10000, MEM_DECOMMIT ); 981 ok( !ret, "VirtualFree succeeded\n" ); 982 ok( GetLastError() == ERROR_INVALID_PARAMETER, "VirtualFree failed with %lu\n", GetLastError() ); 983 984 ret = UnmapViewOfFile(ptr); 985 ok(ret, "UnmapViewOfFile failed with error %ld\n", GetLastError()); 986 CloseHandle(mapping); 987 988 /* same thing with SEC_NOCACHE (only supported on recent Windows versions) */ 989 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT | SEC_NOCACHE, 990 0, MAPPING_SIZE, NULL); 991 ok(mapping != 0, "CreateFileMappingA failed with error %ld\n", GetLastError()); 992 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, 993 sizeof(section_info), NULL ); 994 ok( !status, "NtQuerySection failed err %lx\n", status ); 995 ok( section_info.Attributes == (SEC_COMMIT | SEC_NOCACHE) || 996 broken(section_info.Attributes == SEC_COMMIT), 997 "NtQuerySection wrong attr %08lx\n", section_info.Attributes ); 998 if (section_info.Attributes & SEC_NOCACHE) 999 { 1000 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0); 1001 ok(ptr != NULL, "MapViewOfFile failed with error %ld\n", GetLastError()); 1002 1003 ret = VirtualQuery(ptr, &info, sizeof(info)); 1004 ok(ret, "VirtualQuery failed with error %ld\n", GetLastError()); 1005 ok(info.BaseAddress == ptr, "wrong BaseAddress %p/%p\n", ptr, info.BaseAddress); 1006 ok(info.AllocationBase == ptr, "wrong AllocationBase %p/%p\n", ptr, info.AllocationBase); 1007 ok(info.RegionSize == MAPPING_SIZE, "wrong RegionSize 0x%Ix\n", info.RegionSize); 1008 ok(info.State == MEM_COMMIT, "wrong State 0x%lx\n", info.State); 1009 ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE), 1010 "wrong AllocationProtect 0x%lx\n", info.AllocationProtect); 1011 ok(info.Protect == (PAGE_READWRITE | PAGE_NOCACHE), "wrong Protect 0x%lx\n", info.Protect); 1012 ok(info.Type == MEM_MAPPED, "wrong Type 0x%lx\n", info.Type); 1013 1014 ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY); 1015 ok(ptr != NULL, "VirtualAlloc failed with error %ld\n", GetLastError()); 1016 1017 ret = VirtualQuery(ptr, &info, sizeof(info)); 1018 ok(ret, "VirtualQuery failed with error %ld\n", GetLastError()); 1019 ok(info.BaseAddress == ptr, "wrong BaseAddress %p/%p\n", ptr, info.BaseAddress); 1020 ok(info.AllocationBase == ptr, "wrong AllocationBase %p/%p\n", ptr, info.AllocationBase); 1021 ok(info.RegionSize == 0x10000, "wrong RegionSize 0x%Ix\n", info.RegionSize); 1022 ok(info.State == MEM_COMMIT, "wrong State 0x%lx\n", info.State); 1023 ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE), 1024 "wrong AllocationProtect 0x%lx\n", info.AllocationProtect); 1025 ok(info.Protect == (PAGE_READONLY | PAGE_NOCACHE), "wrong Protect 0x%lx\n", info.Protect); 1026 ok(info.Type == MEM_MAPPED, "wrong Type 0x%lx\n", info.Type); 1027 1028 ret = UnmapViewOfFile(ptr); 1029 ok(ret, "UnmapViewOfFile failed with error %ld\n", GetLastError()); 1030 } 1031 CloseHandle(mapping); 1032 1033 addr = VirtualAlloc(NULL, 0x10000, MEM_COMMIT, PAGE_READONLY ); 1034 ok( addr != NULL, "VirtualAlloc failed with error %lu\n", GetLastError() ); 1035 1036 SetLastError(0xdeadbeef); 1037 ok( !UnmapViewOfFile(addr), "UnmapViewOfFile should fail on VirtualAlloc mem\n" ); 1038 ok( GetLastError() == ERROR_INVALID_ADDRESS, 1039 "got %lu, expected ERROR_INVALID_ADDRESS\n", GetLastError()); 1040 SetLastError(0xdeadbeef); 1041 ok( !UnmapViewOfFile((char *)addr + 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" ); 1042 ok( GetLastError() == ERROR_INVALID_ADDRESS, 1043 "got %lu, expected ERROR_INVALID_ADDRESS\n", GetLastError()); 1044 SetLastError(0xdeadbeef); 1045 ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" ); 1046 ok( GetLastError() == ERROR_INVALID_ADDRESS, 1047 "got %lu, expected ERROR_INVALID_ADDRESS\n", GetLastError()); 1048 1049 ok( VirtualFree(addr, 0, MEM_RELEASE), "VirtualFree failed\n" ); 1050 1051 /* close named mapping handle without unmapping */ 1052 name = "Foo"; 1053 SetLastError(0xdeadbeef); 1054 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name); 1055 ok( mapping != 0, "CreateFileMappingA failed with error %ld\n", GetLastError() ); 1056 SetLastError(0xdeadbeef); 1057 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0); 1058 ok( ptr != NULL, "MapViewOfFile failed with error %ld\n", GetLastError() ); 1059 SetLastError(0xdeadbeef); 1060 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name); 1061 ok( map2 != 0, "OpenFileMappingA failed with error %ld\n", GetLastError() ); 1062 SetLastError(0xdeadbeef); 1063 ret = CloseHandle(map2); 1064 ok(ret, "CloseHandle error %ld\n", GetLastError()); 1065 SetLastError(0xdeadbeef); 1066 ret = CloseHandle(mapping); 1067 ok(ret, "CloseHandle error %ld\n", GetLastError()); 1068 1069 ret = IsBadReadPtr(ptr, MAPPING_SIZE); 1070 ok( !ret, "memory is not accessible\n" ); 1071 1072 ret = VirtualQuery(ptr, &info, sizeof(info)); 1073 ok(ret, "VirtualQuery error %ld\n", GetLastError()); 1074 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr); 1075 ok(info.RegionSize == MAPPING_SIZE, "got %#Ix != expected %#x\n", info.RegionSize, MAPPING_SIZE); 1076 ok(info.Protect == PAGE_READWRITE, "got %#lx != expected PAGE_READWRITE\n", info.Protect); 1077 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr); 1078 ok(info.AllocationProtect == PAGE_READWRITE, "%#lx != PAGE_READWRITE\n", info.AllocationProtect); 1079 ok(info.State == MEM_COMMIT, "%#lx != MEM_COMMIT\n", info.State); 1080 ok(info.Type == MEM_MAPPED, "%#lx != MEM_MAPPED\n", info.Type); 1081 1082 SetLastError(0xdeadbeef); 1083 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name); 1084 ok( map2 == 0, "OpenFileMappingA succeeded\n" ); 1085 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %ld\n", GetLastError() ); 1086 if (map2) CloseHandle(map2); /* FIXME: remove once Wine is fixed */ 1087 SetLastError(0xdeadbeef); 1088 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name); 1089 ok( mapping != 0, "CreateFileMappingA failed\n" ); 1090 ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %ld\n", GetLastError() ); 1091 SetLastError(0xdeadbeef); 1092 ret = CloseHandle(mapping); 1093 ok(ret, "CloseHandle error %ld\n", GetLastError()); 1094 1095 ret = IsBadReadPtr(ptr, MAPPING_SIZE); 1096 ok( !ret, "memory is not accessible\n" ); 1097 1098 ret = VirtualQuery(ptr, &info, sizeof(info)); 1099 ok(ret, "VirtualQuery error %ld\n", GetLastError()); 1100 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr); 1101 ok(info.RegionSize == MAPPING_SIZE, "got %#Ix != expected %#x\n", info.RegionSize, MAPPING_SIZE); 1102 ok(info.Protect == PAGE_READWRITE, "got %#lx != expected PAGE_READWRITE\n", info.Protect); 1103 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr); 1104 ok(info.AllocationProtect == PAGE_READWRITE, "%#lx != PAGE_READWRITE\n", info.AllocationProtect); 1105 ok(info.State == MEM_COMMIT, "%#lx != MEM_COMMIT\n", info.State); 1106 ok(info.Type == MEM_MAPPED, "%#lx != MEM_MAPPED\n", info.Type); 1107 1108 SetLastError(0xdeadbeef); 1109 ret = UnmapViewOfFile(ptr); 1110 ok( ret, "UnmapViewOfFile failed with error %ld\n", GetLastError() ); 1111 1112 ret = IsBadReadPtr(ptr, MAPPING_SIZE); 1113 ok( ret, "memory is accessible\n" ); 1114 1115 ret = VirtualQuery(ptr, &info, sizeof(info)); 1116 ok(ret, "VirtualQuery error %ld\n", GetLastError()); 1117 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr); 1118 ok(info.Protect == PAGE_NOACCESS, "got %#lx != expected PAGE_NOACCESS\n", info.Protect); 1119 ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase); 1120 ok(info.AllocationProtect == 0, "%#lx != 0\n", info.AllocationProtect); 1121 ok(info.State == MEM_FREE, "%#lx != MEM_FREE\n", info.State); 1122 ok(info.Type == 0, "%#lx != 0\n", info.Type); 1123 1124 SetLastError(0xdeadbeef); 1125 file = CreateFileA(testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); 1126 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError() ); 1127 SetFilePointer(file, 4096, NULL, FILE_BEGIN); 1128 SetEndOfFile(file); 1129 1130 SetLastError(0xdeadbeef); 1131 mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name); 1132 ok( mapping != 0, "CreateFileMappingA failed with error %ld\n", GetLastError() ); 1133 SetLastError(0xdeadbeef); 1134 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0); 1135 ok( ptr != NULL, "MapViewOfFile failed with error %ld\n", GetLastError() ); 1136 SetLastError(0xdeadbeef); 1137 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name); 1138 ok( map2 != 0, "OpenFileMappingA failed with error %ld\n", GetLastError() ); 1139 SetLastError(0xdeadbeef); 1140 ret = CloseHandle(map2); 1141 ok(ret, "CloseHandle error %ld\n", GetLastError()); 1142 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, 1143 sizeof(section_info), &info_size ); 1144 ok( !status, "NtQuerySection failed err %lx\n", status ); 1145 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %Iu\n", info_size ); 1146 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08lx\n", 1147 section_info.Attributes ); 1148 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); 1149 ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %lx%08lx\n", 1150 section_info.Size.u.HighPart, section_info.Size.u.LowPart ); 1151 SetLastError(0xdeadbeef); 1152 ret = CloseHandle(mapping); 1153 ok(ret, "CloseHandle error %ld\n", GetLastError()); 1154 1155 ret = IsBadReadPtr(ptr, MAPPING_SIZE); 1156 ok( !ret, "memory is not accessible\n" ); 1157 1158 ret = VirtualQuery(ptr, &info, sizeof(info)); 1159 ok(ret, "VirtualQuery error %ld\n", GetLastError()); 1160 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr); 1161 ok(info.RegionSize == MAPPING_SIZE, "got %#Ix != expected %#x\n", info.RegionSize, MAPPING_SIZE); 1162 ok(info.Protect == PAGE_READWRITE, "got %#lx != expected PAGE_READWRITE\n", info.Protect); 1163 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr); 1164 ok(info.AllocationProtect == PAGE_READWRITE, "%#lx != PAGE_READWRITE\n", info.AllocationProtect); 1165 ok(info.State == MEM_COMMIT, "%#lx != MEM_COMMIT\n", info.State); 1166 ok(info.Type == MEM_MAPPED, "%#lx != MEM_MAPPED\n", info.Type); 1167 1168 SetLastError(0xdeadbeef); 1169 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name); 1170 ok( map2 == 0, "OpenFileMappingA succeeded\n" ); 1171 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %ld\n", GetLastError() ); 1172 CloseHandle(map2); 1173 SetLastError(0xdeadbeef); 1174 mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name); 1175 ok( mapping != 0, "CreateFileMappingA failed\n" ); 1176 ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %ld\n", GetLastError() ); 1177 SetLastError(0xdeadbeef); 1178 ret = CloseHandle(mapping); 1179 ok(ret, "CloseHandle error %ld\n", GetLastError()); 1180 1181 ret = IsBadReadPtr(ptr, MAPPING_SIZE); 1182 ok( !ret, "memory is not accessible\n" ); 1183 1184 ret = VirtualQuery(ptr, &info, sizeof(info)); 1185 ok(ret, "VirtualQuery error %ld\n", GetLastError()); 1186 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr); 1187 ok(info.RegionSize == MAPPING_SIZE, "got %#Ix != expected %#x\n", info.RegionSize, MAPPING_SIZE); 1188 ok(info.Protect == PAGE_READWRITE, "got %#lx != expected PAGE_READWRITE\n", info.Protect); 1189 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr); 1190 ok(info.AllocationProtect == PAGE_READWRITE, "%#lx != PAGE_READWRITE\n", info.AllocationProtect); 1191 ok(info.State == MEM_COMMIT, "%#lx != MEM_COMMIT\n", info.State); 1192 ok(info.Type == MEM_MAPPED, "%#lx != MEM_MAPPED\n", info.Type); 1193 1194 SetLastError(0xdeadbeef); 1195 ret = UnmapViewOfFile(ptr); 1196 ok( ret, "UnmapViewOfFile failed with error %ld\n", GetLastError() ); 1197 1198 ret = IsBadReadPtr(ptr, MAPPING_SIZE); 1199 ok( ret, "memory is accessible\n" ); 1200 1201 ret = VirtualQuery(ptr, &info, sizeof(info)); 1202 ok(ret, "VirtualQuery error %ld\n", GetLastError()); 1203 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr); 1204 ok(info.Protect == PAGE_NOACCESS, "got %#lx != expected PAGE_NOACCESS\n", info.Protect); 1205 ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase); 1206 ok(info.AllocationProtect == 0, "%#lx != 0\n", info.AllocationProtect); 1207 ok(info.State == MEM_FREE, "%#lx != MEM_FREE\n", info.State); 1208 ok(info.Type == 0, "%#lx != 0\n", info.Type); 1209 1210 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 12288, NULL ); 1211 ok( mapping != NULL, "CreateFileMappingA failed with error %lu\n", GetLastError() ); 1212 1213 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 ); 1214 ok( ptr != NULL, "MapViewOfFile failed with error %lu\n", GetLastError() ); 1215 1216 ret = UnmapViewOfFile( (char *)ptr + 100 ); 1217 ok( ret, "UnmapViewOfFile failed with error %lu\n", GetLastError() ); 1218 1219 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 ); 1220 ok( ptr != NULL, "MapViewOfFile failed with error %lu\n", GetLastError() ); 1221 1222 ret = UnmapViewOfFile( (char *)ptr + 4096 ); 1223 ok( ret, "UnmapViewOfFile failed with error %lu\n", GetLastError() ); 1224 1225 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 ); 1226 ok( ptr != NULL, "MapViewOfFile failed with error %lu\n", GetLastError() ); 1227 1228 ret = UnmapViewOfFile( (char *)ptr + 4096 + 100 ); 1229 ok( ret, "UnmapViewOfFile failed with error %lu\n", GetLastError() ); 1230 1231 CloseHandle(mapping); 1232 1233 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 36, NULL ); 1234 ok( mapping != NULL, "CreateFileMappingA failed with error %lu\n", GetLastError() ); 1235 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, 1236 sizeof(section_info), &info_size ); 1237 ok( !status, "NtQuerySection failed err %lx\n", status ); 1238 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %Iu\n", info_size ); 1239 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08lx\n", 1240 section_info.Attributes ); 1241 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); 1242 ok( section_info.Size.QuadPart == 36, "NtQuerySection wrong size %lx%08lx\n", 1243 section_info.Size.u.HighPart, section_info.Size.u.LowPart ); 1244 CloseHandle(mapping); 1245 1246 SetFilePointer(file, 0x3456, NULL, FILE_BEGIN); 1247 SetEndOfFile(file); 1248 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 0, NULL ); 1249 ok( mapping != NULL, "CreateFileMappingA failed with error %lu\n", GetLastError() ); 1250 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, 1251 sizeof(section_info), &info_size ); 1252 ok( !status, "NtQuerySection failed err %lx\n", status ); 1253 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %Iu\n", info_size ); 1254 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08lx\n", 1255 section_info.Attributes ); 1256 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); 1257 ok( section_info.Size.QuadPart == 0x3456, "NtQuerySection wrong size %lx%08lx\n", 1258 section_info.Size.u.HighPart, section_info.Size.u.LowPart ); 1259 CloseHandle(mapping); 1260 1261 map_size.QuadPart = 0x3457; 1262 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL, 1263 &map_size, PAGE_READONLY, SEC_COMMIT, file ); 1264 ok( status == STATUS_SECTION_TOO_BIG, "NtCreateSection failed %lx\n", status ); 1265 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL, 1266 &map_size, PAGE_READONLY, SEC_IMAGE, file ); 1267 ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection failed %lx\n", status ); 1268 if (!status) CloseHandle( mapping ); 1269 map_size.QuadPart = 0x3452; 1270 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL, 1271 &map_size, PAGE_READONLY, SEC_COMMIT, file ); 1272 ok( !status, "NtCreateSection failed %lx\n", status ); 1273 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info), NULL ); 1274 ok( !status, "NtQuerySection failed err %lx\n", status ); 1275 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08lx\n", 1276 section_info.Attributes ); 1277 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); 1278 ok( section_info.Size.QuadPart == 0x3452, "NtQuerySection wrong size %lx%08lx\n", 1279 section_info.Size.u.HighPart, section_info.Size.u.LowPart ); 1280 size = map_size.QuadPart; 1281 status = pNtMapViewOfSection( mapping, GetCurrentProcess(), &ptr, 0, 0, NULL, 1282 &size, ViewShare, 0, PAGE_READONLY ); 1283 ok( !status, "NtMapViewOfSection failed err %lx\n", status ); 1284 pNtUnmapViewOfSection( GetCurrentProcess(), ptr ); 1285 size = map_size.QuadPart + 1; 1286 status = pNtMapViewOfSection( mapping, GetCurrentProcess(), &ptr, 0, 0, NULL, 1287 &size, ViewShare, 0, PAGE_READONLY ); 1288 ok( status == STATUS_INVALID_VIEW_SIZE, "NtMapViewOfSection failed err %lx\n", status ); 1289 CloseHandle(mapping); 1290 1291 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL, 1292 &map_size, PAGE_READONLY, SEC_COMMIT, 0 ); 1293 ok( !status, "NtCreateSection failed %lx\n", status ); 1294 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info), NULL ); 1295 ok( !status, "NtQuerySection failed err %lx\n", status ); 1296 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08lx\n", 1297 section_info.Attributes ); 1298 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); 1299 ok( section_info.Size.QuadPart == 0x4000, "NtQuerySection wrong size %lx%08lx\n", 1300 section_info.Size.u.HighPart, section_info.Size.u.LowPart ); 1301 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info)-1, NULL ); 1302 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQuerySection failed err %lx\n", status ); 1303 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info)+1, NULL ); 1304 ok( !status, "NtQuerySection failed err %lx\n", status ); 1305 status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info)-1, NULL ); 1306 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQuerySection failed err %lx\n", status ); 1307 status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info), NULL ); 1308 ok( status == STATUS_SECTION_NOT_IMAGE, "NtQuerySection failed err %lx\n", status ); 1309 status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info)+1, NULL ); 1310 ok( status == STATUS_SECTION_NOT_IMAGE, "NtQuerySection failed err %lx\n", status ); 1311 if (sizeof(SIZE_T) > sizeof(int)) 1312 { 1313 status = pNtQuerySection( mapping, SectionImageInformation, &image_info, 1314 sizeof(image_info) + ((SIZE_T)0x10000000 << 8), NULL ); 1315 todo_wine 1316 ok( status == STATUS_ACCESS_VIOLATION, "NtQuerySection wrong err %lx\n", status ); 1317 } 1318 CloseHandle(mapping); 1319 1320 SetFilePointer(file, 0, NULL, FILE_BEGIN); 1321 SetEndOfFile(file); 1322 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL, 1323 NULL, PAGE_READONLY, SEC_COMMIT, file ); 1324 ok( status == STATUS_MAPPED_FILE_SIZE_ZERO, "NtCreateSection failed %lx\n", status ); 1325 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL, 1326 NULL, PAGE_READONLY, SEC_IMAGE, file ); 1327 ok( status == STATUS_INVALID_FILE_FOR_SECTION, "NtCreateSection failed %lx\n", status ); 1328 1329 CloseHandle(file); 1330 DeleteFileA(testfile); 1331} 1332 1333 1334static void test_NtAreMappedFilesTheSame(void) 1335{ 1336 static const char testfile[] = "testfile.xxx"; 1337 HANDLE file, file2, mapping, map2; 1338 void *ptr, *ptr2; 1339 NTSTATUS status; 1340 char path[MAX_PATH]; 1341 1342 if (!pNtAreMappedFilesTheSame) 1343 { 1344 win_skip( "NtAreMappedFilesTheSame not available\n" ); 1345 return; 1346 } 1347 1348 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 1349 NULL, CREATE_ALWAYS, 0, 0 ); 1350 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError() ); 1351 SetFilePointer( file, 4096, NULL, FILE_BEGIN ); 1352 SetEndOfFile( file ); 1353 1354 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL ); 1355 ok( mapping != 0, "CreateFileMapping error %lu\n", GetLastError() ); 1356 1357 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 ); 1358 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); 1359 1360 file2 = CreateFileA( testfile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 1361 NULL, OPEN_EXISTING, 0, 0 ); 1362 ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError() ); 1363 1364 map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY, 0, 4096, NULL ); 1365 ok( map2 != 0, "CreateFileMapping error %lu\n", GetLastError() ); 1366 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 ); 1367 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); 1368 status = pNtAreMappedFilesTheSame( ptr, ptr2 ); 1369 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %lx\n", status ); 1370 UnmapViewOfFile( ptr2 ); 1371 1372 ptr2 = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 ); 1373 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); 1374 status = pNtAreMappedFilesTheSame( ptr, ptr2 ); 1375 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %lx\n", status ); 1376 UnmapViewOfFile( ptr2 ); 1377 CloseHandle( map2 ); 1378 1379 map2 = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL ); 1380 ok( map2 != 0, "CreateFileMapping error %lu\n", GetLastError() ); 1381 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 ); 1382 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); 1383 status = pNtAreMappedFilesTheSame( ptr, ptr2 ); 1384 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %lx\n", status ); 1385 UnmapViewOfFile( ptr2 ); 1386 CloseHandle( map2 ); 1387 CloseHandle( file2 ); 1388 1389 status = pNtAreMappedFilesTheSame( ptr, ptr ); 1390 ok( status == STATUS_SUCCESS || broken(status == STATUS_NOT_SAME_DEVICE), 1391 "NtAreMappedFilesTheSame returned %lx\n", status ); 1392 1393 status = pNtAreMappedFilesTheSame( ptr, (char *)ptr + 30 ); 1394 ok( status == STATUS_SUCCESS || broken(status == STATUS_NOT_SAME_DEVICE), 1395 "NtAreMappedFilesTheSame returned %lx\n", status ); 1396 1397 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") ); 1398 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %lx\n", status ); 1399 1400 status = pNtAreMappedFilesTheSame( ptr, (void *)0xdeadbeef ); 1401 ok( status == STATUS_CONFLICTING_ADDRESSES || status == STATUS_INVALID_ADDRESS, 1402 "NtAreMappedFilesTheSame returned %lx\n", status ); 1403 1404 status = pNtAreMappedFilesTheSame( ptr, NULL ); 1405 ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %lx\n", status ); 1406 1407 status = pNtAreMappedFilesTheSame( ptr, (void *)GetProcessHeap() ); 1408 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %lx\n", status ); 1409 1410 status = pNtAreMappedFilesTheSame( NULL, NULL ); 1411 ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %lx\n", status ); 1412 1413 ptr2 = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE ); 1414 ok( ptr2 != NULL, "VirtualAlloc error %lu\n", GetLastError() ); 1415 status = pNtAreMappedFilesTheSame( ptr, ptr2 ); 1416 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %lx\n", status ); 1417 VirtualFree( ptr2, 0, MEM_RELEASE ); 1418 1419 UnmapViewOfFile( ptr ); 1420 CloseHandle( mapping ); 1421 CloseHandle( file ); 1422 1423 status = pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"), 1424 GetModuleHandleA("kernel32.dll") ); 1425 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %lx\n", status ); 1426 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"), 1427 GetModuleHandleA("kernel32.dll") ); 1428 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %lx\n", status ); 1429 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"), 1430 (char *)GetModuleHandleA("kernel32.dll") + 4096 ); 1431 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %lx\n", status ); 1432 1433 GetSystemDirectoryA( path, MAX_PATH ); 1434 strcat( path, "\\kernel32.dll" ); 1435 file = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 ); 1436 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError() ); 1437 1438 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL ); 1439 ok( mapping != 0, "CreateFileMapping error %lu\n", GetLastError() ); 1440 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 ); 1441 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); 1442 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") ); 1443 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %lx\n", status ); 1444 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"), ptr ); 1445 todo_wine 1446 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %lx\n", status ); 1447 UnmapViewOfFile( ptr ); 1448 CloseHandle( mapping ); 1449 1450 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL ); 1451 ok( mapping != 0, "CreateFileMapping error %lu\n", GetLastError() ); 1452 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); 1453 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); 1454 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") ); 1455 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %lx\n", status ); 1456 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"), ptr ); 1457 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %lx\n", status ); 1458 1459 file2 = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 ); 1460 ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError() ); 1461 map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL ); 1462 ok( map2 != 0, "CreateFileMapping error %lu\n", GetLastError() ); 1463 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 0 ); 1464 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); 1465 status = pNtAreMappedFilesTheSame( ptr, ptr2 ); 1466 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %lx\n", status ); 1467 status = pNtAreMappedFilesTheSame( ptr2, ptr ); 1468 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %lx\n", status ); 1469 UnmapViewOfFile( ptr2 ); 1470 CloseHandle( map2 ); 1471 CloseHandle( file2 ); 1472 1473 UnmapViewOfFile( ptr ); 1474 CloseHandle( mapping ); 1475 1476 CloseHandle( file ); 1477 DeleteFileA( testfile ); 1478} 1479 1480static void test_CreateFileMapping(void) 1481{ 1482 HANDLE handle, handle2, file[3]; 1483 char path[MAX_PATH], filename[MAX_PATH]; 1484 unsigned int i; 1485 NTSTATUS status; 1486 1487 static const struct { DWORD file, flags, error, attrs; } sec_flag_tests[] = 1488 { 1489 /* anonymous mapping */ 1490 { 0, SEC_RESERVE, 0 }, /* 0 */ 1491 { 0, SEC_RESERVE | SEC_NOCACHE, 0 }, 1492 { 0, SEC_RESERVE | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER }, 1493 { 0, SEC_RESERVE | SEC_WRITECOMBINE, 0 }, 1494 { 0, SEC_COMMIT, 0 }, 1495 { 0, SEC_COMMIT | SEC_NOCACHE, 0 }, /* 5 */ 1496 { 0, SEC_COMMIT | SEC_WRITECOMBINE, 0 }, 1497 { 0, SEC_RESERVE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, 1498 { 0, SEC_IMAGE, ERROR_BAD_EXE_FORMAT }, 1499 { 0, SEC_IMAGE | SEC_RESERVE, ERROR_INVALID_PARAMETER }, 1500 { 0, SEC_IMAGE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, /* 10 */ 1501 { 0, SEC_NOCACHE, ERROR_INVALID_PARAMETER }, 1502 { 0, SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER }, 1503 { 0, SEC_WRITECOMBINE, ERROR_INVALID_PARAMETER }, 1504 { 0, SEC_FILE, ERROR_INVALID_PARAMETER }, 1505 { 0, SEC_FILE | SEC_RESERVE, ERROR_INVALID_PARAMETER }, /* 15 */ 1506 { 0, SEC_FILE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, 1507 { 0, 0, 0, SEC_COMMIT }, 1508 /* normal file */ 1509 { 1, SEC_RESERVE, 0, SEC_FILE }, 1510 { 1, SEC_RESERVE | SEC_NOCACHE, 0, SEC_FILE | SEC_NOCACHE }, 1511 { 1, SEC_RESERVE | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER }, /* 20 */ 1512 { 1, SEC_RESERVE | SEC_WRITECOMBINE, 0, SEC_FILE | SEC_WRITECOMBINE }, 1513 { 1, SEC_COMMIT, 0, SEC_FILE }, 1514 { 1, SEC_COMMIT | SEC_NOCACHE, 0, SEC_FILE | SEC_NOCACHE }, 1515 { 1, SEC_COMMIT | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER }, 1516 { 1, SEC_COMMIT | SEC_WRITECOMBINE, 0, SEC_FILE | SEC_WRITECOMBINE }, /* 25 */ 1517 { 1, SEC_RESERVE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, 1518 { 1, SEC_IMAGE, ERROR_BAD_EXE_FORMAT }, 1519 { 1, SEC_IMAGE | SEC_RESERVE, ERROR_INVALID_PARAMETER }, 1520 { 1, SEC_IMAGE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, 1521 { 1, SEC_NOCACHE, ERROR_INVALID_PARAMETER }, /* 30 */ 1522 { 1, SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER }, 1523 { 1, SEC_WRITECOMBINE, ERROR_INVALID_PARAMETER }, 1524 { 1, SEC_FILE, ERROR_INVALID_PARAMETER }, 1525 { 1, SEC_FILE | SEC_RESERVE, ERROR_INVALID_PARAMETER }, 1526 { 1, SEC_FILE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, /* 35 */ 1527 { 1, 0, 0, SEC_FILE }, 1528 /* PE image file */ 1529 { 2, SEC_IMAGE, 0, SEC_FILE | SEC_IMAGE }, 1530 { 2, SEC_IMAGE | SEC_FILE, ERROR_INVALID_PARAMETER }, 1531 { 2, SEC_IMAGE | SEC_NOCACHE, 0, SEC_FILE | SEC_IMAGE }, 1532 { 2, SEC_IMAGE | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER }, /* 40 */ 1533 { 2, SEC_IMAGE | SEC_WRITECOMBINE, ERROR_INVALID_PARAMETER }, 1534 { 2, SEC_IMAGE | SEC_RESERVE, ERROR_INVALID_PARAMETER }, 1535 { 2, SEC_IMAGE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, 1536 }; 1537 1538 /* test case sensitivity */ 1539 1540 SetLastError(0xdeadbeef); 1541 handle = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000, 1542 "Wine Test Mapping"); 1543 ok( handle != NULL, "CreateFileMapping failed with error %lu\n", GetLastError()); 1544 ok( GetLastError() == 0, "wrong error %lu\n", GetLastError()); 1545 1546 SetLastError(0xdeadbeef); 1547 handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000, 1548 "Wine Test Mapping"); 1549 ok( handle2 != NULL, "CreateFileMapping failed with error %ld\n", GetLastError()); 1550 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %lu\n", GetLastError()); 1551 CloseHandle( handle2 ); 1552 1553 SetLastError(0xdeadbeef); 1554 handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000, 1555 "WINE TEST MAPPING"); 1556 ok( handle2 != NULL, "CreateFileMapping failed with error %ld\n", GetLastError()); 1557 ok( GetLastError() == 0, "wrong error %lu\n", GetLastError()); 1558 CloseHandle( handle2 ); 1559 1560 SetLastError(0xdeadbeef); 1561 handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "Wine Test Mapping"); 1562 ok( handle2 != NULL, "OpenFileMapping failed with error %ld\n", GetLastError()); 1563 CloseHandle( handle2 ); 1564 1565 SetLastError(0xdeadbeef); 1566 handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "WINE TEST MAPPING"); 1567 ok( !handle2, "OpenFileMapping succeeded\n"); 1568 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError()); 1569 1570 CloseHandle( handle ); 1571 1572 /* test SEC_* flags */ 1573 1574 file[0] = INVALID_HANDLE_VALUE; 1575 GetTempPathA( MAX_PATH, path ); 1576 GetTempFileNameA( path, "map", 0, filename ); 1577 1578 file[1] = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); 1579 ok( file[1] != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError() ); 1580 SetFilePointer( file[1], 0x2000, NULL, FILE_BEGIN ); 1581 SetEndOfFile( file[1] ); 1582 1583 GetSystemDirectoryA( path, MAX_PATH ); 1584 strcat( path, "\\kernel32.dll" ); 1585 file[2] = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 ); 1586 ok( file[2] != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError() ); 1587 1588 for (i = 0; i < ARRAY_SIZE(sec_flag_tests); i++) 1589 { 1590 DWORD flags = sec_flag_tests[i].flags; 1591 DWORD perm = sec_flag_tests[i].file == 2 ? PAGE_READONLY : PAGE_READWRITE; 1592 SetLastError( 0xdeadbeef ); 1593 handle = CreateFileMappingA( file[sec_flag_tests[i].file], NULL, 1594 flags | perm, 0, 0x1000, "Wine Test Mapping" ); 1595 if (sec_flag_tests[i].error) 1596 { 1597 ok( !handle, "%u: CreateFileMapping succeeded\n", i ); 1598 ok( GetLastError() == sec_flag_tests[i].error, "%u: wrong error %lu\n", i, GetLastError()); 1599 } 1600 else 1601 { 1602 /* SEC_WRITECOMBINE and SEC_IMAGE_NO_EXECUTE not supported on older Windows */ 1603 BOOL new_flags = ((flags & SEC_WRITECOMBINE) || 1604 ((flags & SEC_IMAGE_NO_EXECUTE) == SEC_IMAGE_NO_EXECUTE)); 1605 ok( handle != NULL || broken(new_flags), 1606 "%u: CreateFileMapping failed with error %lu\n", i, GetLastError()); 1607 ok( GetLastError() == 0 || broken(new_flags && GetLastError() == ERROR_INVALID_PARAMETER), 1608 "%u: wrong error %lu\n", i, GetLastError()); 1609 } 1610 1611 if (handle) 1612 { 1613 SECTION_BASIC_INFORMATION info; 1614 DWORD expect = sec_flag_tests[i].attrs ? sec_flag_tests[i].attrs : sec_flag_tests[i].flags; 1615 1616 status = pNtQuerySection( handle, SectionBasicInformation, &info, sizeof(info), NULL ); 1617 ok( !status, "%u: NtQuerySection failed err %lx\n", i, status ); 1618 /* SEC_NOCACHE not supported on older Windows */ 1619 ok( info.Attributes == expect || broken( info.Attributes == (expect & ~SEC_NOCACHE) ), 1620 "%u: NtQuerySection wrong attr %08lx\n", i, info.Attributes ); 1621 CloseHandle( handle ); 1622 } 1623 } 1624 CloseHandle( file[1] ); 1625 CloseHandle( file[2] ); 1626 DeleteFileA( filename ); 1627} 1628 1629static void test_IsBadReadPtr(void) 1630{ 1631 BOOL ret; 1632 void *ptr = (void *)0xdeadbeef; 1633 char stackvar; 1634 1635 ret = IsBadReadPtr(NULL, 0); 1636 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret); 1637 1638 ret = IsBadReadPtr(NULL, 1); 1639 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret); 1640 1641 ret = IsBadReadPtr(ptr, 0); 1642 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret); 1643 1644 ret = IsBadReadPtr(ptr, 1); 1645 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret); 1646 1647 ret = IsBadReadPtr(&stackvar, 0); 1648 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret); 1649 1650 ret = IsBadReadPtr(&stackvar, sizeof(char)); 1651 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret); 1652 1653 ret = IsBadReadPtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD)); 1654 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret); 1655 1656 ret = IsBadReadPtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD)); 1657 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret); 1658} 1659 1660static void test_IsBadWritePtr(void) 1661{ 1662 BOOL ret; 1663 void *ptr = (void *)0xdeadbeef; 1664 char stackval; 1665 1666 ret = IsBadWritePtr(NULL, 0); 1667 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret); 1668 1669 ret = IsBadWritePtr(NULL, 1); 1670 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret); 1671 1672 ret = IsBadWritePtr(ptr, 0); 1673 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret); 1674 1675 ret = IsBadWritePtr(ptr, 1); 1676 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret); 1677 1678 ret = IsBadWritePtr(&stackval, 0); 1679 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret); 1680 1681 ret = IsBadWritePtr(&stackval, sizeof(char)); 1682 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret); 1683 1684 ret = IsBadWritePtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD)); 1685 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret); 1686 1687 ret = IsBadWritePtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD)); 1688 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret); 1689} 1690 1691static void test_IsBadCodePtr(void) 1692{ 1693 BOOL ret; 1694 void *ptr = (void *)0xdeadbeef; 1695 char stackval; 1696 1697 ret = IsBadCodePtr(NULL); 1698 ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret); 1699 1700 ret = IsBadCodePtr(ptr); 1701 ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret); 1702 1703 ret = IsBadCodePtr((void *)&stackval); 1704 ok(ret == FALSE, "Expected IsBadCodePtr to return FALSE, got %d\n", ret); 1705} 1706 1707struct read_pipe_args 1708{ 1709 HANDLE pipe; 1710 int index; 1711 void *base; 1712 DWORD size; 1713}; 1714 1715static const char testdata[] = "Hello World"; 1716 1717static DWORD CALLBACK read_pipe( void *arg ) 1718{ 1719 struct read_pipe_args *args = arg; 1720 DWORD num_bytes; 1721 BOOL success = ConnectNamedPipe( args->pipe, NULL ); 1722 ok( success || GetLastError() == ERROR_PIPE_CONNECTED, 1723 "%u: ConnectNamedPipe failed %lu\n", args->index, GetLastError() ); 1724 1725 success = ReadFile( args->pipe, args->base, args->size, &num_bytes, NULL ); 1726 ok( success, "%u: ReadFile failed %lu\n", args->index, GetLastError() ); 1727 ok( num_bytes == sizeof(testdata), "%u: wrong number of bytes read %lu\n", args->index, num_bytes ); 1728 ok( !memcmp( args->base, testdata, sizeof(testdata)), 1729 "%u: didn't receive expected data\n", args->index ); 1730 return 0; 1731} 1732 1733static void test_write_watch(void) 1734{ 1735 static const char pipename[] = "\\\\.\\pipe\\test_write_watch_pipe"; 1736 DWORD ret, size, old_prot, num_bytes; 1737 MEMORY_BASIC_INFORMATION info; 1738 HANDLE readpipe, writepipe, file; 1739 OVERLAPPED overlapped, *overlapped2; 1740 void *results[64]; 1741 ULONG_PTR count; 1742 ULONG i, pagesize; 1743 BOOL success; 1744 char path[MAX_PATH], filename[MAX_PATH], *base; 1745 1746 if (!pGetWriteWatch || !pResetWriteWatch) 1747 { 1748 win_skip( "GetWriteWatch not supported\n" ); 1749 return; 1750 } 1751 1752 size = 0x10000; 1753 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE ); 1754 if (!base && 1755 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED)) 1756 { 1757 win_skip( "MEM_WRITE_WATCH not supported\n" ); 1758 return; 1759 } 1760 ok( base != NULL, "VirtualAlloc failed %lu\n", GetLastError() ); 1761 ret = VirtualQuery( base, &info, sizeof(info) ); 1762 ok(ret, "VirtualQuery failed %lu\n", GetLastError()); 1763 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base ); 1764 ok( info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect %lx\n", info.AllocationProtect ); 1765 ok( info.RegionSize == size, "wrong RegionSize 0x%Ix\n", info.RegionSize ); 1766 ok( info.State == MEM_COMMIT, "wrong State 0x%lx\n", info.State ); 1767 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%lx\n", info.Protect ); 1768 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%lx\n", info.Type ); 1769 1770 count = 64; 1771 SetLastError( 0xdeadbeef ); 1772 ret = pGetWriteWatch( 0, NULL, size, results, &count, &pagesize ); 1773 ok( ret == ~0u, "GetWriteWatch succeeded %lu\n", ret ); 1774 ok( GetLastError() == ERROR_INVALID_PARAMETER || 1775 broken( GetLastError() == 0xdeadbeef ), /* win98 */ 1776 "wrong error %lu\n", GetLastError() ); 1777 1778 SetLastError( 0xdeadbeef ); 1779 ret = pGetWriteWatch( 0, GetModuleHandleW(NULL), size, results, &count, &pagesize ); 1780 if (ret) 1781 { 1782 ok( ret == ~0u, "GetWriteWatch succeeded %lu\n", ret ); 1783 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() ); 1784 } 1785 else /* win98 */ 1786 { 1787 ok( count == 0, "wrong count %Iu\n", count ); 1788 } 1789 1790 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 1791 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 1792 ok( count == 0, "wrong count %Iu\n", count ); 1793 1794 base[pagesize + 1] = 0x44; 1795 1796 count = 64; 1797 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 1798 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 1799 ok( count == 1, "wrong count %Iu\n", count ); 1800 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] ); 1801 1802 count = 64; 1803 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 1804 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 1805 ok( count == 1, "wrong count %Iu\n", count ); 1806 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] ); 1807 1808 count = 64; 1809 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 1810 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 1811 ok( count == 0, "wrong count %Iu\n", count ); 1812 1813 base[2*pagesize + 3] = 0x11; 1814 base[4*pagesize + 8] = 0x11; 1815 1816 count = 64; 1817 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 1818 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 1819 ok( count == 2, "wrong count %Iu\n", count ); 1820 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] ); 1821 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] ); 1822 1823 count = 64; 1824 ret = pGetWriteWatch( 0, base + 3*pagesize, 2*pagesize, results, &count, &pagesize ); 1825 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 1826 ok( count == 1, "wrong count %Iu\n", count ); 1827 ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] ); 1828 1829 ret = pResetWriteWatch( base, 3*pagesize ); 1830 ok( !ret, "pResetWriteWatch failed %lu\n", GetLastError() ); 1831 1832 count = 64; 1833 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 1834 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 1835 ok( count == 1, "wrong count %Iu\n", count ); 1836 ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] ); 1837 1838 *(DWORD *)(base + 2*pagesize - 2) = 0xdeadbeef; 1839 1840 count = 64; 1841 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 1842 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 1843 ok( count == 3, "wrong count %Iu\n", count ); 1844 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] ); 1845 ok( results[1] == base + 2*pagesize, "wrong result %p\n", results[1] ); 1846 ok( results[2] == base + 4*pagesize, "wrong result %p\n", results[2] ); 1847 1848 count = 1; 1849 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 1850 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 1851 ok( count == 1, "wrong count %Iu\n", count ); 1852 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] ); 1853 1854 count = 64; 1855 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 1856 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 1857 ok( count == 2, "wrong count %Iu\n", count ); 1858 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] ); 1859 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] ); 1860 1861 /* changing protections doesn't affect watches */ 1862 1863 ret = VirtualProtect( base, 3*pagesize, PAGE_READONLY, &old_prot ); 1864 ok( ret, "VirtualProtect failed error %lu\n", GetLastError() ); 1865 ok( old_prot == PAGE_READWRITE, "wrong old prot %lx\n", old_prot ); 1866 1867 ret = VirtualQuery( base, &info, sizeof(info) ); 1868 ok(ret, "VirtualQuery failed %lu\n", GetLastError()); 1869 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base ); 1870 ok( info.RegionSize == 3*pagesize, "wrong RegionSize 0x%Ix\n", info.RegionSize ); 1871 ok( info.State == MEM_COMMIT, "wrong State 0x%lx\n", info.State ); 1872 ok( info.Protect == PAGE_READONLY, "wrong Protect 0x%lx\n", info.Protect ); 1873 1874 ret = VirtualProtect( base, 3*pagesize, PAGE_READWRITE, &old_prot ); 1875 ok( ret, "VirtualProtect failed error %lu\n", GetLastError() ); 1876 ok( old_prot == PAGE_READONLY, "wrong old prot %lx\n", old_prot ); 1877 1878 count = 64; 1879 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 1880 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 1881 ok( count == 2, "wrong count %Iu\n", count ); 1882 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] ); 1883 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] ); 1884 1885 ret = VirtualQuery( base, &info, sizeof(info) ); 1886 ok(ret, "VirtualQuery failed %lu\n", GetLastError()); 1887 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base ); 1888 ok( info.RegionSize == size, "wrong RegionSize 0x%Ix\n", info.RegionSize ); 1889 ok( info.State == MEM_COMMIT, "wrong State 0x%lx\n", info.State ); 1890 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%lx\n", info.Protect ); 1891 1892 /* ReadFile should trigger write watches */ 1893 1894 for (i = 0; i < 2; i++) 1895 { 1896 memset( &overlapped, 0, sizeof(overlapped) ); 1897 overlapped.hEvent = CreateEventA( NULL, TRUE, FALSE, NULL ); 1898 1899 readpipe = CreateNamedPipeA( pipename, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_INBOUND, 1900 (i ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE) | PIPE_WAIT, 1, 1024, 1024, 1901 NMPWAIT_USE_DEFAULT_WAIT, NULL ); 1902 ok( readpipe != INVALID_HANDLE_VALUE, "CreateNamedPipeA failed %lu\n", GetLastError() ); 1903 1904 success = ConnectNamedPipe( readpipe, &overlapped ); 1905 ok( !success, "%lu: ConnectNamedPipe unexpectedly succeeded\n", i ); 1906 ok( GetLastError() == ERROR_IO_PENDING, "%lu: expected ERROR_IO_PENDING, got %lu\n", 1907 i, GetLastError() ); 1908 1909 writepipe = CreateFileA( pipename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); 1910 ok( writepipe != INVALID_HANDLE_VALUE, "%lu: CreateFileA failed %lu\n", i, GetLastError() ); 1911 1912 ret = WaitForSingleObject( overlapped.hEvent, 1000 ); 1913 ok( ret == WAIT_OBJECT_0, "%lu: expected WAIT_OBJECT_0, got %lu\n", i, ret ); 1914 1915 memset( base, 0, size ); 1916 1917 count = 64; 1918 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 1919 ok( !ret, "%lu: GetWriteWatch failed %lu\n", i, GetLastError() ); 1920 ok( count == 16, "%lu: wrong count %Iu\n", i, count ); 1921 1922 success = ReadFile( readpipe, base, size, NULL, &overlapped ); 1923 ok( !success, "%lu: ReadFile unexpectedly succeeded\n", i ); 1924 ok( GetLastError() == ERROR_IO_PENDING, "%lu: expected ERROR_IO_PENDING, got %lu\n", 1925 i, GetLastError() ); 1926 1927 count = 64; 1928 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 1929 ok( !ret, "%lu: GetWriteWatch failed %lu\n", i, GetLastError() ); 1930 ok( count == 16, "%lu: wrong count %Iu\n", i, count ); 1931 1932 num_bytes = 0; 1933 success = WriteFile( writepipe, testdata, sizeof(testdata), &num_bytes, NULL ); 1934 ok( success, "%lu: WriteFile failed %lu\n", i, GetLastError() ); 1935 ok( num_bytes == sizeof(testdata), "%lu: wrong number of bytes written %lu\n", i, num_bytes ); 1936 1937 num_bytes = 0; 1938 success = GetOverlappedResult( readpipe, &overlapped, &num_bytes, TRUE ); 1939 ok( success, "%lu: GetOverlappedResult failed %lu\n", i, GetLastError() ); 1940 ok( num_bytes == sizeof(testdata), "%lu: wrong number of bytes read %lu\n", i, num_bytes ); 1941 ok( !memcmp( base, testdata, sizeof(testdata)), "%lu: didn't receive expected data\n", i ); 1942 1943 count = 64; 1944 memset( results, 0, sizeof(results) ); 1945 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 1946 ok( !ret, "%lu: GetWriteWatch failed %lu\n", i, GetLastError() ); 1947 ok( count == 1, "%lu: wrong count %Iu\n", i, count ); 1948 ok( results[0] == base, "%lu: wrong result %p\n", i, results[0] ); 1949 1950 CloseHandle( readpipe ); 1951 CloseHandle( writepipe ); 1952 CloseHandle( overlapped.hEvent ); 1953 } 1954 1955 for (i = 0; i < 2; i++) 1956 { 1957 struct read_pipe_args args; 1958 HANDLE thread; 1959 1960 readpipe = CreateNamedPipeA( pipename, PIPE_ACCESS_INBOUND, 1961 (i ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE) | PIPE_WAIT, 1, 1024, 1024, 1962 NMPWAIT_USE_DEFAULT_WAIT, NULL ); 1963 ok( readpipe != INVALID_HANDLE_VALUE, "CreateNamedPipeA failed %lu\n", GetLastError() ); 1964 1965 memset( base, 0, size ); 1966 1967 count = 64; 1968 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 1969 ok( !ret, "%lu: GetWriteWatch failed %lu\n", i, GetLastError() ); 1970 ok( count == 16, "%lu: wrong count %Iu\n", i, count ); 1971 1972 args.pipe = readpipe; 1973 args.index = i; 1974 args.base = base; 1975 args.size = size; 1976 thread = CreateThread( NULL, 0, read_pipe, &args, 0, NULL ); 1977 1978 writepipe = CreateFileA( pipename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); 1979 ok( writepipe != INVALID_HANDLE_VALUE, "%lu: CreateFileA failed %lu\n", i, GetLastError() ); 1980 Sleep( 200 ); 1981 1982 count = 64; 1983 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 1984 ok( !ret, "%lu: GetWriteWatch failed %lu\n", i, GetLastError() ); 1985 ok( count == 16, "%lu: wrong count %Iu\n", i, count ); 1986 1987 num_bytes = 0; 1988 success = WriteFile( writepipe, testdata, sizeof(testdata), &num_bytes, NULL ); 1989 ok( success, "%lu: WriteFile failed %lu\n", i, GetLastError() ); 1990 ok( num_bytes == sizeof(testdata), "%lu: wrong number of bytes written %lu\n", i, num_bytes ); 1991 WaitForSingleObject( thread, 10000 ); 1992 1993 count = 64; 1994 memset( results, 0, sizeof(results) ); 1995 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 1996 ok( !ret, "%lu: GetWriteWatch failed %lu\n", i, GetLastError() ); 1997 ok( count == 1, "%lu: wrong count %Iu\n", i, count ); 1998 ok( results[0] == base, "%lu: wrong result %p\n", i, results[0] ); 1999 2000 CloseHandle( readpipe ); 2001 CloseHandle( writepipe ); 2002 CloseHandle( thread ); 2003 } 2004 2005 GetTempPathA( MAX_PATH, path ); 2006 GetTempFileNameA( path, "map", 0, filename ); 2007 file = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); 2008 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError() ); 2009 SetFilePointer( file, 2 * pagesize + 3, NULL, FILE_BEGIN ); 2010 SetEndOfFile( file ); 2011 SetFilePointer( file, 0, NULL, FILE_BEGIN ); 2012 2013 success = ReadFile( file, base, size, &num_bytes, NULL ); 2014 ok( success, "ReadFile failed %lu\n", GetLastError() ); 2015 ok( num_bytes == 2 * pagesize + 3, "wrong bytes %lu\n", num_bytes ); 2016 2017 count = 64; 2018 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 2019 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2020 ok( count == 16, "wrong count %Iu\n", count ); 2021 2022 success = ReadFile( file, base, size, &num_bytes, NULL ); 2023 ok( success, "ReadFile failed %lu\n", GetLastError() ); 2024 ok( num_bytes == 0, "wrong bytes %lu\n", num_bytes ); 2025 2026 count = 64; 2027 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 2028 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2029 ok( count == 16, "wrong count %Iu\n", count ); 2030 2031 CloseHandle( file ); 2032 DeleteFileA( filename ); 2033 2034 success = ReadFile( (HANDLE)0xdead, base, size, &num_bytes, NULL ); 2035 ok( !success, "ReadFile succeeded\n" ); 2036 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %lu\n", GetLastError() ); 2037 2038 count = 64; 2039 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 2040 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2041 ok( count == 0, "wrong count %Iu\n", count ); 2042 2043 /* OVERLAPPED structure write watch */ 2044 memset( &overlapped, 0, sizeof(overlapped) ); 2045 overlapped.hEvent = CreateEventA( NULL, TRUE, FALSE, NULL ); 2046 2047 readpipe = CreateNamedPipeA( pipename, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_INBOUND, 2048 PIPE_TYPE_MESSAGE | PIPE_WAIT, 1, 1024, 1024, 2049 NMPWAIT_USE_DEFAULT_WAIT, NULL ); 2050 ok( readpipe != INVALID_HANDLE_VALUE, "CreateNamedPipeA failed %lu\n", GetLastError() ); 2051 2052 success = ConnectNamedPipe( readpipe, &overlapped ); 2053 ok( !success, "ConnectNamedPipe unexpectedly succeeded\n" ); 2054 ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %lu\n", GetLastError() ); 2055 2056 writepipe = CreateFileA( pipename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); 2057 ok( writepipe != INVALID_HANDLE_VALUE, "CreateFileA failed %lu\n", GetLastError() ); 2058 2059 ret = WaitForSingleObject( overlapped.hEvent, 1000 ); 2060 ok( ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", ret ); 2061 2062 memset( base, 0, size ); 2063 overlapped2 = (OVERLAPPED*)(base + size - sizeof(*overlapped2)); 2064 overlapped2->hEvent = CreateEventA( NULL, TRUE, FALSE, NULL ); 2065 2066 count = 64; 2067 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 2068 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2069 ok( count == 16, "wrong count %Iu\n", count ); 2070 2071 success = ReadFile( readpipe, base, sizeof(testdata), NULL, overlapped2 ); 2072 ok( !success, "ReadFile unexpectedly succeeded\n" ); 2073 ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %lu\n", GetLastError() ); 2074 overlapped2->Internal = 0xdeadbeef; 2075 2076 count = 64; 2077 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 2078 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2079 ok( count == 2, "wrong count %Iu\n", count ); 2080 2081 num_bytes = 0; 2082 success = WriteFile( writepipe, testdata, sizeof(testdata), &num_bytes, NULL ); 2083 ok( success, "WriteFile failed %lu\n", GetLastError() ); 2084 ok( num_bytes == sizeof(testdata), "wrong number of bytes written %lu\n", num_bytes ); 2085 2086 num_bytes = 0; 2087 success = GetOverlappedResult( readpipe, overlapped2, &num_bytes, TRUE ); 2088 ok( success, "GetOverlappedResult failed %lu\n", GetLastError() ); 2089 ok( num_bytes == sizeof(testdata), "wrong number of bytes read %lu\n", num_bytes ); 2090 ok( !memcmp( base, testdata, sizeof(testdata)), "didn't receive expected data\n" ); 2091 2092 count = 64; 2093 memset( results, 0, sizeof(results) ); 2094 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 2095 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2096 ok( count == 2, "wrong count %Iu\n", count ); 2097 ok( results[0] == base, "wrong result %p\n", results[0] ); 2098 2099 CloseHandle( readpipe ); 2100 CloseHandle( writepipe ); 2101 CloseHandle( overlapped.hEvent ); 2102 CloseHandle( overlapped2->hEvent ); 2103 2104 /* some invalid parameter tests */ 2105 2106 SetLastError( 0xdeadbeef ); 2107 count = 0; 2108 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 2109 if (ret) 2110 { 2111 ok( ret == ~0u, "GetWriteWatch succeeded %lu\n", ret ); 2112 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() ); 2113 2114 SetLastError( 0xdeadbeef ); 2115 ret = pGetWriteWatch( 0, base, size, results, NULL, &pagesize ); 2116 ok( ret == ~0u, "GetWriteWatch succeeded %lu\n", ret ); 2117 ok( GetLastError() == ERROR_NOACCESS, "wrong error %lu\n", GetLastError() ); 2118 2119 SetLastError( 0xdeadbeef ); 2120 count = 64; 2121 ret = pGetWriteWatch( 0, base, size, results, &count, NULL ); 2122 ok( ret == ~0u, "GetWriteWatch succeeded %lu\n", ret ); 2123 ok( GetLastError() == ERROR_NOACCESS, "wrong error %lu\n", GetLastError() ); 2124 2125 SetLastError( 0xdeadbeef ); 2126 count = 64; 2127 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize ); 2128 ok( ret == ~0u, "GetWriteWatch succeeded %lu\n", ret ); 2129 ok( GetLastError() == ERROR_NOACCESS, "wrong error %lu\n", GetLastError() ); 2130 2131 SetLastError( 0xdeadbeef ); 2132 count = 0; 2133 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize ); 2134 ok( ret == ~0u, "GetWriteWatch succeeded %lu\n", ret ); 2135 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() ); 2136 2137 SetLastError( 0xdeadbeef ); 2138 count = 64; 2139 ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize ); 2140 ok( ret == ~0u, "GetWriteWatch succeeded %lu\n", ret ); 2141 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() ); 2142 2143 SetLastError( 0xdeadbeef ); 2144 count = 64; 2145 ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize ); 2146 ok( ret == ~0u, "GetWriteWatch succeeded %lu\n", ret ); 2147 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() ); 2148 2149 SetLastError( 0xdeadbeef ); 2150 count = 64; 2151 ret = pGetWriteWatch( 0, base, size * 2, results, &count, &pagesize ); 2152 ok( ret == ~0u, "GetWriteWatch succeeded %lu\n", ret ); 2153 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() ); 2154 2155 SetLastError( 0xdeadbeef ); 2156 count = 64; 2157 ret = pGetWriteWatch( 0, base + size - pagesize, pagesize + 1, results, &count, &pagesize ); 2158 ok( ret == ~0u, "GetWriteWatch succeeded %lu\n", ret ); 2159 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() ); 2160 2161 SetLastError( 0xdeadbeef ); 2162 ret = pResetWriteWatch( base, 0 ); 2163 ok( ret == ~0u, "ResetWriteWatch succeeded %lu\n", ret ); 2164 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() ); 2165 2166 SetLastError( 0xdeadbeef ); 2167 ret = pResetWriteWatch( GetModuleHandleW(NULL), size ); 2168 ok( ret == ~0u, "ResetWriteWatch succeeded %lu\n", ret ); 2169 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() ); 2170 } 2171 else /* win98 is completely different */ 2172 { 2173 SetLastError( 0xdeadbeef ); 2174 count = 64; 2175 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize ); 2176 ok( ret == ERROR_INVALID_PARAMETER, "GetWriteWatch succeeded %lu\n", ret ); 2177 ok( GetLastError() == 0xdeadbeef, "wrong error %lu\n", GetLastError() ); 2178 2179 count = 0; 2180 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize ); 2181 ok( !ret, "GetWriteWatch failed %lu\n", ret ); 2182 2183 count = 64; 2184 ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize ); 2185 ok( !ret, "GetWriteWatch failed %lu\n", ret ); 2186 2187 count = 64; 2188 ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize ); 2189 ok( !ret, "GetWriteWatch failed %lu\n", ret ); 2190 2191 ret = pResetWriteWatch( base, 0 ); 2192 ok( !ret, "ResetWriteWatch failed %lu\n", ret ); 2193 2194 ret = pResetWriteWatch( GetModuleHandleW(NULL), size ); 2195 ok( !ret, "ResetWriteWatch failed %lu\n", ret ); 2196 } 2197 2198 VirtualFree( base, 0, MEM_RELEASE ); 2199 2200 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_READWRITE ); 2201 ok( base != NULL, "VirtualAlloc failed %lu\n", GetLastError() ); 2202 VirtualFree( base, 0, MEM_RELEASE ); 2203 2204 base = VirtualAlloc( 0, size, MEM_WRITE_WATCH, PAGE_READWRITE ); 2205 ok( !base, "VirtualAlloc succeeded\n" ); 2206 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() ); 2207 2208 /* initial protect doesn't matter */ 2209 2210 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_NOACCESS ); 2211 ok( base != NULL, "VirtualAlloc failed %lu\n", GetLastError() ); 2212 base = VirtualAlloc( base, size, MEM_COMMIT, PAGE_NOACCESS ); 2213 ok( base != NULL, "VirtualAlloc failed %lu\n", GetLastError() ); 2214 2215 count = 64; 2216 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 2217 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2218 ok( count == 0, "wrong count %Iu\n", count ); 2219 2220 ret = VirtualProtect( base, 6*pagesize, PAGE_READWRITE, &old_prot ); 2221 ok( ret, "VirtualProtect failed error %lu\n", GetLastError() ); 2222 ok( old_prot == PAGE_NOACCESS, "wrong old prot %lx\n", old_prot ); 2223 2224 base[5*pagesize + 200] = 3; 2225 2226 ret = VirtualProtect( base, 6*pagesize, PAGE_NOACCESS, &old_prot ); 2227 ok( ret, "VirtualProtect failed error %lu\n", GetLastError() ); 2228 ok( old_prot == PAGE_READWRITE, "wrong old prot %lx\n", old_prot ); 2229 2230 count = 64; 2231 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 2232 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2233 ok( count == 1, "wrong count %Iu\n", count ); 2234 ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] ); 2235 2236 ret = VirtualFree( base, size, MEM_DECOMMIT ); 2237 ok( ret, "VirtualFree failed %lu\n", GetLastError() ); 2238 2239 count = 64; 2240 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 2241 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2242 ok( count == 1 || broken(count == 0), /* win98 */ 2243 "wrong count %Iu\n", count ); 2244 if (count) ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] ); 2245 2246 VirtualFree( base, 0, MEM_RELEASE ); 2247} 2248 2249#if defined(__i386__) || defined(__x86_64__) 2250 2251static DWORD WINAPI stack_commit_func( void *arg ) 2252{ 2253 volatile char *p = (char *)&p; 2254 2255 /* trigger all guard pages, to ensure that the pages are committed */ 2256 while (p >= (char *)NtCurrentTeb()->DeallocationStack + 4 * 0x1000) 2257 { 2258 p[0] |= 0; 2259 p -= 0x1000; 2260 } 2261 2262 ok( arg == (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg ); 2263 return 42; 2264} 2265 2266static void test_stack_commit(void) 2267{ 2268#ifdef __i386__ 2269 static const char code_call_on_stack[] = { 2270 0x55, /* pushl %ebp */ 2271 0x56, /* pushl %esi */ 2272 0x89, 0xe6, /* movl %esp,%esi */ 2273 0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */ 2274 0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */ 2275 0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */ 2276 0x83, 0xe0, 0xf0, /* andl $~15,%eax */ 2277 0x83, 0xe8, 0x0c, /* subl $12,%eax */ 2278 0x89, 0xc4, /* movl %eax,%esp */ 2279 0x52, /* pushl %edx */ 2280 0x31, 0xed, /* xorl %ebp,%ebp */ 2281 0xff, 0xd1, /* call *%ecx */ 2282 0x89, 0xf4, /* movl %esi,%esp */ 2283 0x5e, /* popl %esi */ 2284 0x5d, /* popl %ebp */ 2285 0xc2, 0x0c, 0x00 }; /* ret $12 */ 2286#else 2287 static const char code_call_on_stack[] = { 2288 0x55, /* pushq %rbp */ 2289 0x48, 0x89, 0xe5, /* movq %rsp,%rbp */ 2290 /* %rcx - func, %rdx - arg, %r8 - stack */ 2291 0x48, 0x87, 0xca, /* xchgq %rcx,%rdx */ 2292 0x49, 0x83, 0xe0, 0xf0, /* andq $~15,%r8 */ 2293 0x49, 0x83, 0xe8, 0x20, /* subq $0x20,%r8 */ 2294 0x4c, 0x89, 0xc4, /* movq %r8,%rsp */ 2295 0xff, 0xd2, /* callq *%rdx */ 2296 0x48, 0x89, 0xec, /* movq %rbp,%rsp */ 2297 0x5d, /* popq %rbp */ 2298 0xc3 }; /* ret */ 2299#endif 2300 DWORD (WINAPI *call_on_stack)( DWORD (WINAPI *func)(void *), void *arg, void *stack ); 2301 void *old_stack, *old_stack_base, *old_stack_limit; 2302 void *new_stack, *new_stack_base; 2303 DWORD result; 2304 2305 call_on_stack = VirtualAlloc( 0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE ); 2306 ok( call_on_stack != NULL, "VirtualAlloc failed %lu\n", GetLastError() ); 2307 memcpy( call_on_stack, code_call_on_stack, sizeof(code_call_on_stack) ); 2308 2309 /* allocate a new stack, only the first guard page is committed */ 2310 new_stack = VirtualAlloc( 0, 0x400000, MEM_RESERVE, PAGE_READWRITE ); 2311 ok( new_stack != NULL, "VirtualAlloc failed %lu\n", GetLastError() ); 2312 new_stack_base = (char *)new_stack + 0x400000; 2313 VirtualAlloc( (char *)new_stack_base - 0x1000, 0x1000, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD ); 2314 2315 old_stack = NtCurrentTeb()->DeallocationStack; 2316 old_stack_base = NtCurrentTeb()->Tib.StackBase; 2317 old_stack_limit = NtCurrentTeb()->Tib.StackLimit; 2318 2319 NtCurrentTeb()->DeallocationStack = new_stack; 2320 NtCurrentTeb()->Tib.StackBase = new_stack_base; 2321 NtCurrentTeb()->Tib.StackLimit = new_stack_base; 2322 2323 result = call_on_stack( stack_commit_func, (void *)0xdeadbeef, new_stack_base ); 2324 2325 NtCurrentTeb()->DeallocationStack = old_stack; 2326 NtCurrentTeb()->Tib.StackBase = old_stack_base; 2327 NtCurrentTeb()->Tib.StackLimit = old_stack_limit; 2328 2329 ok( result == 42, "expected 42, got %lu\n", result ); 2330 2331 VirtualFree( new_stack, 0, MEM_RELEASE ); 2332 VirtualFree( call_on_stack, 0, MEM_RELEASE ); 2333} 2334 2335#endif /* defined(__i386__) || defined(__x86_64__) */ 2336#ifdef __i386__ 2337 2338static LONG num_guard_page_calls; 2339 2340static DWORD guard_page_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame, 2341 CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher ) 2342{ 2343 trace( "exception: %08lx flags:%lx addr:%p\n", 2344 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress ); 2345 2346 ok( rec->NumberParameters == 2, "NumberParameters is %ld instead of 2\n", rec->NumberParameters ); 2347 ok( rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION, "ExceptionCode is %08lx instead of %08lx\n", 2348 rec->ExceptionCode, STATUS_GUARD_PAGE_VIOLATION ); 2349 2350 InterlockedIncrement( &num_guard_page_calls ); 2351 *(int *)rec->ExceptionInformation[1] += 0x100; 2352 2353 return ExceptionContinueExecution; 2354} 2355 2356static void test_guard_page(void) 2357{ 2358 EXCEPTION_REGISTRATION_RECORD frame; 2359 MEMORY_BASIC_INFORMATION info; 2360 DWORD ret, size, old_prot; 2361 LONG *value, old_value; 2362 void *results[64]; 2363 ULONG_PTR count; 2364 ULONG pagesize; 2365 BOOL success; 2366 char *base; 2367 2368 size = 0x1000; 2369 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD ); 2370 ok( base != NULL, "VirtualAlloc failed %lu\n", GetLastError() ); 2371 value = (LONG *)base; 2372 2373 /* verify info structure */ 2374 ret = VirtualQuery( base, &info, sizeof(info) ); 2375 ok( ret, "VirtualQuery failed %lu\n", GetLastError()); 2376 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base ); 2377 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %lx\n", info.AllocationProtect ); 2378 ok( info.RegionSize == size, "wrong RegionSize 0x%Ix\n", info.RegionSize ); 2379 ok( info.State == MEM_COMMIT, "wrong State 0x%lx\n", info.State ); 2380 ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%lx\n", info.Protect ); 2381 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%lx\n", info.Type ); 2382 2383 /* put some initial value into the memory */ 2384 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); 2385 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2386 ok( old_prot == (PAGE_READWRITE | PAGE_GUARD), "wrong old prot %lx\n", old_prot ); 2387 2388 *value = 1; 2389 *(value + 1) = 2; 2390 2391 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot ); 2392 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2393 ok( old_prot == PAGE_READWRITE, "wrong old prot %lx\n", old_prot ); 2394 2395 /* test behaviour of VirtualLock - first attempt should fail */ 2396 SetLastError( 0xdeadbeef ); 2397 success = VirtualLock( base, size ); 2398 ok( !success, "VirtualLock unexpectedly succeeded\n" ); 2399 todo_wine 2400 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %lu\n", GetLastError() ); 2401 2402 success = VirtualLock( base, size ); 2403 todo_wine 2404 ok( success, "VirtualLock failed %lu\n", GetLastError() ); 2405 if (success) 2406 { 2407 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%lx\n", *value ); 2408 success = VirtualUnlock( base, size ); 2409 ok( success, "VirtualUnlock failed %lu\n", GetLastError() ); 2410 } 2411 2412 /* check info structure again, PAGE_GUARD should be removed now */ 2413 ret = VirtualQuery( base, &info, sizeof(info) ); 2414 ok( ret, "VirtualQuery failed %lu\n", GetLastError()); 2415 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base ); 2416 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %lx\n", info.AllocationProtect ); 2417 ok( info.RegionSize == size, "wrong RegionSize 0x%Ix\n", info.RegionSize ); 2418 ok( info.State == MEM_COMMIT, "wrong State 0x%lx\n", info.State ); 2419 todo_wine 2420 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%lx\n", info.Protect ); 2421 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%lx\n", info.Type ); 2422 2423 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot ); 2424 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2425 todo_wine 2426 ok( old_prot == PAGE_READWRITE, "wrong old prot %lx\n", old_prot ); 2427 2428 /* test directly accessing the memory - we need to setup an exception handler first */ 2429 frame.Handler = guard_page_handler; 2430 frame.Prev = NtCurrentTeb()->Tib.ExceptionList; 2431 NtCurrentTeb()->Tib.ExceptionList = &frame; 2432 2433 InterlockedExchange( &num_guard_page_calls, 0 ); 2434 InterlockedExchange( &old_value, *value ); /* exception handler increments value by 0x100 */ 2435 *value = 2; 2436 ok( old_value == 0x101, "memory block contains wrong value, expected 0x101, got 0x%lx\n", old_value ); 2437 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %ld calls\n", num_guard_page_calls ); 2438 2439 NtCurrentTeb()->Tib.ExceptionList = frame.Prev; 2440 2441 /* check info structure again, PAGE_GUARD should be removed now */ 2442 ret = VirtualQuery( base, &info, sizeof(info) ); 2443 ok( ret, "VirtualQuery failed %lu\n", GetLastError()); 2444 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%lx\n", info.Protect ); 2445 2446 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot ); 2447 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2448 ok( old_prot == PAGE_READWRITE, "wrong old prot %lx\n", old_prot ); 2449 2450 /* test accessing second integer in memory */ 2451 frame.Handler = guard_page_handler; 2452 frame.Prev = NtCurrentTeb()->Tib.ExceptionList; 2453 NtCurrentTeb()->Tib.ExceptionList = &frame; 2454 2455 InterlockedExchange( &num_guard_page_calls, 0 ); 2456 old_value = *(value + 1); 2457 ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%lx\n", old_value ); 2458 ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%lx\n", *value ); 2459 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %ld calls\n", num_guard_page_calls ); 2460 2461 NtCurrentTeb()->Tib.ExceptionList = frame.Prev; 2462 2463 success = VirtualLock( base, size ); 2464 ok( success, "VirtualLock failed %lu\n", GetLastError() ); 2465 if (success) 2466 { 2467 ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%lx\n", *value ); 2468 success = VirtualUnlock( base, size ); 2469 ok( success, "VirtualUnlock failed %lu\n", GetLastError() ); 2470 } 2471 2472 VirtualFree( base, 0, MEM_RELEASE ); 2473 2474 /* combined guard page / write watch tests */ 2475 if (!pGetWriteWatch || !pResetWriteWatch) 2476 { 2477 win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" ); 2478 return; 2479 } 2480 2481 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE | PAGE_GUARD ); 2482 if (!base && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED)) 2483 { 2484 win_skip( "MEM_WRITE_WATCH not supported\n" ); 2485 return; 2486 } 2487 ok( base != NULL, "VirtualAlloc failed %lu\n", GetLastError() ); 2488 value = (LONG *)base; 2489 2490 ret = VirtualQuery( base, &info, sizeof(info) ); 2491 ok( ret, "VirtualQuery failed %lu\n", GetLastError() ); 2492 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base ); 2493 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %lx\n", info.AllocationProtect ); 2494 ok( info.RegionSize == size, "wrong RegionSize 0x%Ix\n", info.RegionSize ); 2495 ok( info.State == MEM_COMMIT, "wrong State 0x%lx\n", info.State ); 2496 ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%lx\n", info.Protect ); 2497 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%lx\n", info.Type ); 2498 2499 count = 64; 2500 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 2501 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2502 ok( count == 0, "wrong count %Iu\n", count ); 2503 2504 /* writing to a page should trigger should trigger guard page, even if write watch is set */ 2505 frame.Handler = guard_page_handler; 2506 frame.Prev = NtCurrentTeb()->Tib.ExceptionList; 2507 NtCurrentTeb()->Tib.ExceptionList = &frame; 2508 2509 InterlockedExchange( &num_guard_page_calls, 0 ); 2510 *value = 1; 2511 *(value + 1) = 2; 2512 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %ld calls\n", num_guard_page_calls ); 2513 2514 NtCurrentTeb()->Tib.ExceptionList = frame.Prev; 2515 2516 count = 64; 2517 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 2518 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2519 ok( count == 1, "wrong count %Iu\n", count ); 2520 ok( results[0] == base, "wrong result %p\n", results[0] ); 2521 2522 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot ); 2523 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2524 2525 /* write watch is triggered from inside of the guard page handler */ 2526 frame.Handler = guard_page_handler; 2527 frame.Prev = NtCurrentTeb()->Tib.ExceptionList; 2528 NtCurrentTeb()->Tib.ExceptionList = &frame; 2529 2530 InterlockedExchange( &num_guard_page_calls, 0 ); 2531 old_value = *(value + 1); /* doesn't trigger write watch */ 2532 ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%lx\n", old_value ); 2533 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%lx\n", *value ); 2534 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %ld calls\n", num_guard_page_calls ); 2535 2536 NtCurrentTeb()->Tib.ExceptionList = frame.Prev; 2537 2538 count = 64; 2539 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 2540 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2541 ok( count == 1, "wrong count %Iu\n", count ); 2542 ok( results[0] == base, "wrong result %p\n", results[0] ); 2543 2544 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot ); 2545 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2546 2547 /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */ 2548 SetLastError( 0xdeadbeef ); 2549 success = VirtualLock( base, size ); 2550 ok( !success, "VirtualLock unexpectedly succeeded\n" ); 2551 todo_wine 2552 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %lu\n", GetLastError() ); 2553 2554 count = 64; 2555 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize ); 2556 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2557 ok( count == 0, "wrong count %Iu\n", count ); 2558 2559 success = VirtualLock( base, size ); 2560 todo_wine 2561 ok( success, "VirtualLock failed %lu\n", GetLastError() ); 2562 if (success) 2563 { 2564 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%lx\n", *value ); 2565 success = VirtualUnlock( base, size ); 2566 ok( success, "VirtualUnlock failed %lu\n", GetLastError() ); 2567 } 2568 2569 count = 64; 2570 results[0] = (void *)0xdeadbeef; 2571 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 2572 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 2573 todo_wine 2574 ok( count == 1 || broken(count == 0) /* Windows 8 */, "wrong count %Iu\n", count ); 2575 todo_wine 2576 ok( results[0] == base || broken(results[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results[0] ); 2577 2578 VirtualFree( base, 0, MEM_RELEASE ); 2579} 2580 2581static LONG num_execute_fault_calls; 2582 2583static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame, 2584 CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher ) 2585{ 2586 ULONG flags = MEM_EXECUTE_OPTION_ENABLE; 2587 DWORD err; 2588 2589 trace( "exception: %08lx flags:%lx addr:%p info[0]:%Id info[1]:%p\n", 2590 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, 2591 rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] ); 2592 2593 ok( rec->NumberParameters == 2, "NumberParameters is %ld instead of 2\n", rec->NumberParameters ); 2594 ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION || rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION, 2595 "ExceptionCode is %08lx instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec->ExceptionCode ); 2596 2597 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags), NULL ); 2598 2599 if (rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) 2600 { 2601 2602 err = IsProcessorFeaturePresent( PF_NX_ENABLED ) ? EXCEPTION_EXECUTE_FAULT : EXCEPTION_READ_FAULT; 2603 ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %ld instead of %ld\n", 2604 (DWORD)rec->ExceptionInformation[0], err ); 2605 2606 InterlockedIncrement( &num_guard_page_calls ); 2607 } 2608 else if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION) 2609 { 2610 DWORD old_prot; 2611 BOOL success; 2612 2613 err = (flags & MEM_EXECUTE_OPTION_DISABLE) ? EXCEPTION_EXECUTE_FAULT : EXCEPTION_READ_FAULT; 2614#ifdef __REACTOS__ 2615 if (GetNTVersion() >= _WIN32_WINNT_VISTA) { 2616#endif 2617 ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %ld instead of %ld\n", 2618 (DWORD)rec->ExceptionInformation[0], err ); 2619#ifdef __REACTOS__ 2620 } 2621#endif 2622 2623 success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot ); 2624 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2625#ifdef __REACTOS__ 2626 ok( old_prot == PAGE_READWRITE || broken(old_prot == PAGE_NOACCESS) /* WS03 */, "wrong old prot %lx\n", old_prot ); 2627#else 2628 ok( old_prot == PAGE_READWRITE, "wrong old prot %lx\n", old_prot ); 2629#endif 2630 2631 InterlockedIncrement( &num_execute_fault_calls ); 2632 } 2633 2634 return ExceptionContinueExecution; 2635} 2636 2637static LONG CALLBACK execute_fault_vec_handler( EXCEPTION_POINTERS *ExceptionInfo ) 2638{ 2639 PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord; 2640 DWORD old_prot; 2641 BOOL success; 2642 2643 trace( "exception: %08lx flags:%lx addr:%p info[0]:%Id info[1]:%p\n", 2644 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, 2645 rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] ); 2646 2647 ok( rec->NumberParameters == 2, "NumberParameters is %ld instead of 2\n", rec->NumberParameters ); 2648 ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION, 2649 "ExceptionCode is %08lx instead of STATUS_ACCESS_VIOLATION\n", rec->ExceptionCode ); 2650 2651 if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION) 2652 InterlockedIncrement( &num_execute_fault_calls ); 2653 2654 if (rec->ExceptionInformation[0] == EXCEPTION_READ_FAULT) 2655 return EXCEPTION_CONTINUE_SEARCH; 2656 2657 success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot ); 2658 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2659 ok( old_prot == PAGE_NOACCESS, "wrong old prot %lx\n", old_prot ); 2660 2661 return EXCEPTION_CONTINUE_EXECUTION; 2662} 2663 2664static inline DWORD send_message_excpt( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 2665{ 2666 EXCEPTION_REGISTRATION_RECORD frame; 2667 DWORD ret; 2668 2669 frame.Handler = execute_fault_seh_handler; 2670 frame.Prev = NtCurrentTeb()->Tib.ExceptionList; 2671 NtCurrentTeb()->Tib.ExceptionList = &frame; 2672 2673 InterlockedExchange( &num_guard_page_calls, 0 ); 2674 InterlockedExchange( &num_execute_fault_calls, 0 ); 2675 ret = SendMessageA( hWnd, uMsg, wParam, lParam ); 2676 2677 NtCurrentTeb()->Tib.ExceptionList = frame.Prev; 2678 2679 return ret; 2680} 2681 2682static inline DWORD call_proc_excpt( DWORD (CALLBACK *code)(void *), void *arg ) 2683{ 2684 EXCEPTION_REGISTRATION_RECORD frame; 2685 DWORD ret; 2686 2687 frame.Handler = execute_fault_seh_handler; 2688 frame.Prev = NtCurrentTeb()->Tib.ExceptionList; 2689 NtCurrentTeb()->Tib.ExceptionList = &frame; 2690 2691 InterlockedExchange( &num_guard_page_calls, 0 ); 2692 InterlockedExchange( &num_execute_fault_calls, 0 ); 2693 ret = code( arg ); 2694 2695 NtCurrentTeb()->Tib.ExceptionList = frame.Prev; 2696 2697 return ret; 2698} 2699 2700static LRESULT CALLBACK jmp_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 2701{ 2702 if (uMsg == WM_USER) 2703 return 42; 2704 2705 return DefWindowProcA( hWnd, uMsg, wParam, lParam ); 2706} 2707 2708static LRESULT CALLBACK atl_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 2709{ 2710 DWORD arg = (DWORD)hWnd; 2711 if (uMsg == WM_USER) 2712 ok( arg == 0x11223344, "arg is 0x%08lx instead of 0x11223344\n", arg ); 2713 else 2714 ok( arg != 0x11223344, "arg is unexpectedly 0x11223344\n" ); 2715 return 43; 2716} 2717 2718static DWORD CALLBACK atl5_test_func( void ) 2719{ 2720 return 44; 2721} 2722 2723static void test_atl_thunk_emulation( ULONG dep_flags ) 2724{ 2725 static const char code_jmp[] = {0xE9, 0x00, 0x00, 0x00, 0x00}; 2726 static const char code_atl1[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00}; 2727 static const char code_atl2[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00}; 2728 static const char code_atl3[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1}; 2729 static const char code_atl4[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0}; 2730 static const char code_atl5[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04}; 2731 static const char cls_name[] = "atl_thunk_class"; 2732 DWORD ret, size, old_prot; 2733 ULONG old_flags = MEM_EXECUTE_OPTION_ENABLE; 2734 BOOL success, restore_flags = FALSE; 2735 void *results[64]; 2736 ULONG_PTR count; 2737 ULONG pagesize; 2738 WNDCLASSEXA wc; 2739 char *base; 2740 HWND hWnd; 2741 2742 trace( "Running DEP tests with ProcessExecuteFlags = %ld\n", dep_flags ); 2743 2744 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags), NULL ); 2745 if (old_flags != dep_flags) 2746 { 2747 ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &dep_flags, sizeof(dep_flags) ); 2748 if (ret == STATUS_INVALID_INFO_CLASS /* Windows 2000 */ || 2749 ret == STATUS_ACCESS_DENIED) 2750 { 2751 win_skip( "Skipping DEP tests with ProcessExecuteFlags = %ld\n", dep_flags ); 2752 return; 2753 } 2754 ok( !ret, "NtSetInformationProcess failed with status %08lx\n", ret ); 2755 restore_flags = TRUE; 2756 } 2757 2758 size = 0x1000; 2759 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); 2760 ok( base != NULL, "VirtualAlloc failed %lu\n", GetLastError() ); 2761 2762 /* Check result of GetProcessDEPPolicy */ 2763 if (!pGetProcessDEPPolicy) 2764 win_skip( "GetProcessDEPPolicy not supported\n" ); 2765 else 2766 { 2767 BOOL (WINAPI *get_dep_policy)(HANDLE, LPDWORD, PBOOL) = (void *)base; 2768 BOOL policy_permanent = 0xdeadbeef; 2769 DWORD policy_flags = 0xdeadbeef; 2770 2771 /* GetProcessDEPPolicy crashes on Windows when a NULL pointer is passed. 2772 * Moreover this function has a bug on Windows 8, which has the effect that 2773 * policy_permanent is set to the content of the CL register instead of 0, 2774 * when the policy is not permanent. To detect that we use an assembler 2775 * wrapper to call the function. */ 2776 2777 memcpy( base, code_atl2, sizeof(code_atl2) ); 2778 *(DWORD *)(base + 6) = (DWORD_PTR)pGetProcessDEPPolicy - (DWORD_PTR)(base + 10); 2779 2780 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot ); 2781 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2782 2783 success = get_dep_policy( GetCurrentProcess(), &policy_flags, &policy_permanent ); 2784 ok( success, "GetProcessDEPPolicy failed %lu\n", GetLastError() ); 2785 2786 ret = 0; 2787 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) 2788 ret |= PROCESS_DEP_ENABLE; 2789 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION) 2790 ret |= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION; 2791 2792 ok( policy_flags == ret, "expected policy flags %ld, got %ld\n", ret, policy_flags ); 2793 ok( !policy_permanent || broken(policy_permanent == 0x44), 2794 "expected policy permanent FALSE, got %d\n", policy_permanent ); 2795 } 2796 2797 memcpy( base, code_jmp, sizeof(code_jmp) ); 2798 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5); 2799 2800 /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions, 2801 * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario 2802 * where it is active, so that application which depend on that still work properly. 2803 * We have no exception handler enabled yet, so give proper EXECUTE permissions to 2804 * prevent crashes while creating the window. */ 2805 2806 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot ); 2807 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2808 2809 memset( &wc, 0, sizeof(wc) ); 2810 wc.cbSize = sizeof(wc); 2811 wc.style = CS_VREDRAW | CS_HREDRAW; 2812 wc.hInstance = GetModuleHandleA( 0 ); 2813 wc.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW ); 2814 wc.hbrBackground = NULL; 2815 wc.lpszClassName = cls_name; 2816 wc.lpfnWndProc = (WNDPROC)base; 2817 success = RegisterClassExA(&wc) != 0; 2818 ok( success, "RegisterClassExA failed %lu\n", GetLastError() ); 2819 2820 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0); 2821 ok( hWnd != 0, "CreateWindowExA failed %lu\n", GetLastError() ); 2822 2823 ret = SendMessageA(hWnd, WM_USER, 0, 0); 2824 ok( ret == 42, "SendMessage returned unexpected result %ld\n", ret ); 2825 2826 /* At first try with an instruction which is not recognized as proper ATL thunk 2827 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to 2828 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */ 2829 2830 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); 2831 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2832 2833 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 2834 ok( ret == 42, "call returned wrong result, expected 42, got %ld\n", ret ); 2835 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 2836 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && !IsProcessorFeaturePresent( PF_NX_ENABLED )) 2837 { 2838 trace( "DEP hardware support is not available\n" ); 2839 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2840 dep_flags = MEM_EXECUTE_OPTION_ENABLE; 2841 } 2842 else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) 2843 { 2844 trace( "DEP hardware support is available\n" ); 2845#ifdef __REACTOS__ 2846 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2847#else 2848 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2849#endif 2850 } 2851 else 2852 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2853 2854 /* Now a bit more complicated, the page containing the code is protected with 2855 * PAGE_GUARD memory protection. */ 2856 2857 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot ); 2858 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2859 2860 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 2861 ok( ret == 42, "call returned wrong result, expected 42, got %ld\n", ret ); 2862 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 2863 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) 2864#ifdef __REACTOS__ 2865 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2866#else 2867 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2868#endif 2869 else 2870 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2871 2872 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 2873 ok( ret == 42, "call returned wrong result, expected 42, got %ld\n", ret ); 2874 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 2875 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2876 2877 /* Now test with a proper ATL thunk instruction. */ 2878 2879 memcpy( base, code_atl1, sizeof(code_atl1) ); 2880 *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13); 2881 2882 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot ); 2883 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2884 2885 ret = SendMessageA(hWnd, WM_USER, 0, 0); 2886 ok( ret == 43, "SendMessage returned unexpected result %ld\n", ret ); 2887 2888 /* Try executing with PAGE_READWRITE protection. */ 2889 2890 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); 2891 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2892 2893 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 2894 ok( ret == 43, "call returned wrong result, expected 43, got %ld\n", ret ); 2895 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 2896 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) 2897#ifdef __REACTOS__ 2898 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2899#else 2900 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2901#endif 2902 else 2903 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2904 2905 /* Now a bit more complicated, the page containing the code is protected with 2906 * PAGE_GUARD memory protection. */ 2907 2908 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot ); 2909 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2910 2911 /* the same, but with PAGE_GUARD set */ 2912 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 2913 ok( ret == 43, "call returned wrong result, expected 43, got %ld\n", ret ); 2914 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 2915 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) 2916#ifdef __REACTOS__ 2917 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2918#else 2919 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2920#endif 2921 else 2922 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2923 2924 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 2925 ok( ret == 43, "call returned wrong result, expected 43, got %ld\n", ret ); 2926 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 2927 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2928 2929 /* The following test shows that on Windows, even a vectored exception handler 2930 * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */ 2931 2932 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && !(dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) 2933 { 2934 if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler) 2935 { 2936 PVOID vectored_handler; 2937 2938 success = VirtualProtect( base, size, PAGE_NOACCESS, &old_prot ); 2939 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2940 2941 vectored_handler = pRtlAddVectoredExceptionHandler( TRUE, &execute_fault_vec_handler ); 2942 ok( vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n" ); 2943 2944 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 2945 2946 pRtlRemoveVectoredExceptionHandler( vectored_handler ); 2947 2948 ok( ret == 43, "call returned wrong result, expected 43, got %ld\n", ret ); 2949#ifdef __REACTOS__ 2950 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 2) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2951#else 2952 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2953#endif 2954 } 2955 else 2956 win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" ); 2957 } 2958 2959 /* Test alternative ATL thunk instructions. */ 2960 2961 memcpy( base, code_atl2, sizeof(code_atl2) ); 2962 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 10); 2963 2964 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); 2965 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2966 2967 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 ); 2968 /* FIXME: we don't check the content of the register ECX yet */ 2969 ok( ret == 43, "call returned wrong result, expected 43, got %ld\n", ret ); 2970 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 2971 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) 2972#ifdef __REACTOS__ 2973 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2974#else 2975 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2976#endif 2977 else 2978 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2979 2980 memcpy( base, code_atl3, sizeof(code_atl3) ); 2981 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func; 2982 2983 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); 2984 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 2985 2986 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 ); 2987 /* FIXME: we don't check the content of the registers ECX/EDX yet */ 2988 ok( ret == 43, "call returned wrong result, expected 43, got %ld\n", ret ); 2989 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 2990 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) 2991#ifdef __REACTOS__ 2992 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2993#else 2994 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2995#endif 2996 else 2997 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 2998 2999 memcpy( base, code_atl4, sizeof(code_atl4) ); 3000 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func; 3001 3002 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); 3003 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 3004 3005 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 ); 3006 /* FIXME: We don't check the content of the registers EAX/ECX yet */ 3007 ok( ret == 43, "call returned wrong result, expected 43, got %ld\n", ret ); 3008 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 3009 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) 3010#ifdef __REACTOS__ 3011 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3012#else 3013 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3014#endif 3015 else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) 3016 ok( num_execute_fault_calls == 0 || broken(num_execute_fault_calls == 1) /* Windows XP */, 3017 "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3018 else 3019 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3020 3021 memcpy( base, code_atl5, sizeof(code_atl5) ); 3022 3023 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); 3024 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 3025 3026 results[1] = atl5_test_func; 3027 ret = call_proc_excpt( (void *)base, results ); 3028 /* FIXME: We don't check the content of the registers EAX/ECX yet */ 3029 ok( ret == 44, "call returned wrong result, expected 44, got %ld\n", ret ); 3030 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 3031 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) 3032#ifdef __REACTOS__ 3033 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3034#else 3035 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3036#endif 3037 else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) 3038 ok( num_execute_fault_calls == 0 || broken(num_execute_fault_calls == 1) /* Windows XP */, 3039 "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3040 else 3041 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3042 3043 /* Restore the JMP instruction, set to executable, and then destroy the Window */ 3044 3045 memcpy( base, code_jmp, sizeof(code_jmp) ); 3046 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5); 3047 3048 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot ); 3049 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 3050 3051 DestroyWindow( hWnd ); 3052 3053 success = UnregisterClassA( cls_name, GetModuleHandleA(0) ); 3054 ok( success, "UnregisterClass failed %lu\n", GetLastError() ); 3055 3056 VirtualFree( base, 0, MEM_RELEASE ); 3057 3058 /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */ 3059 3060 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE ); 3061 if (!base && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED)) 3062 { 3063 win_skip( "MEM_WRITE_WATCH not supported\n" ); 3064 goto out; 3065 } 3066 ok( base != NULL, "VirtualAlloc failed %lu\n", GetLastError() ); 3067 3068 count = 64; 3069 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 3070 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 3071 ok( count == 0, "wrong count %Iu\n", count ); 3072 3073 memcpy( base, code_jmp, sizeof(code_jmp) ); 3074 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5); 3075 3076 count = 64; 3077 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 3078 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 3079 ok( count == 1, "wrong count %Iu\n", count ); 3080 ok( results[0] == base, "wrong result %p\n", results[0] ); 3081 3082 /* Create a new window class and associated Window (see above) */ 3083 3084 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot ); 3085 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 3086 3087 memset( &wc, 0, sizeof(wc) ); 3088 wc.cbSize = sizeof(wc); 3089 wc.style = CS_VREDRAW | CS_HREDRAW; 3090 wc.hInstance = GetModuleHandleA( 0 ); 3091 wc.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW ); 3092 wc.hbrBackground = NULL; 3093 wc.lpszClassName = cls_name; 3094 wc.lpfnWndProc = (WNDPROC)base; 3095 success = RegisterClassExA(&wc) != 0; 3096 ok( success, "RegisterClassExA failed %lu\n", GetLastError() ); 3097 3098 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0); 3099 ok( hWnd != 0, "CreateWindowExA failed %lu\n", GetLastError() ); 3100 3101 ret = SendMessageA(hWnd, WM_USER, 0, 0); 3102 ok( ret == 42, "SendMessage returned unexpected result %ld\n", ret ); 3103 3104 count = 64; 3105 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 3106 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 3107 ok( count == 0, "wrong count %Iu\n", count ); 3108 3109 /* At first try with an instruction which is not recognized as proper ATL thunk 3110 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to 3111 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */ 3112 3113 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); 3114 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 3115 3116 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 3117 ok( ret == 42, "call returned wrong result, expected 42, got %ld\n", ret ); 3118 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 3119 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) 3120#ifdef __REACTOS__ 3121 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3122#else 3123 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3124#endif 3125 else 3126 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3127 3128 count = 64; 3129 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 3130 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 3131 ok( count == 0, "wrong count %Iu\n", count ); 3132 3133 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 3134 ok( ret == 42, "call returned wrong result, expected 42, got %ld\n", ret ); 3135 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 3136 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3137 3138 /* Now a bit more complicated, the page containing the code is protected with 3139 * PAGE_GUARD memory protection. */ 3140 3141 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot ); 3142 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 3143 3144 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 3145 ok( ret == 42, "call returned wrong result, expected 42, got %ld\n", ret ); 3146 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 3147 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) 3148#ifdef __REACTOS__ 3149 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3150#else 3151 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3152#endif 3153 else 3154 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3155 3156 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 3157 ok( ret == 42, "call returned wrong result, expected 42, got %ld\n", ret ); 3158 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 3159 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3160 3161 count = 64; 3162 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 3163 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 3164 ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %Iu\n", count ); 3165 3166 /* Now test with a proper ATL thunk instruction. */ 3167 3168 memcpy( base, code_atl1, sizeof(code_atl1) ); 3169 *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13); 3170 3171 count = 64; 3172 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 3173 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 3174 ok( count == 1, "wrong count %Iu\n", count ); 3175 ok( results[0] == base, "wrong result %p\n", results[0] ); 3176 3177 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot ); 3178 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 3179 3180 ret = SendMessageA(hWnd, WM_USER, 0, 0); 3181 ok( ret == 43, "SendMessage returned unexpected result %ld\n", ret ); 3182 3183 /* Try executing with PAGE_READWRITE protection. */ 3184 3185 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); 3186 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 3187 3188 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 3189 ok( ret == 43, "call returned wrong result, expected 43, got %ld\n", ret ); 3190 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 3191 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) 3192#ifdef __REACTOS__ 3193 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0), "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3194#else 3195 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3196#endif 3197 else 3198 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3199 3200 count = 64; 3201 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 3202 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 3203 ok( count == 0, "wrong count %Iu\n", count ); 3204 3205 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 3206 ok( ret == 43, "call returned wrong result, expected 43, got %ld\n", ret ); 3207 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 3208 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3209 3210 /* Now a bit more complicated, the page containing the code is protected with 3211 * PAGE_GUARD memory protection. */ 3212 3213 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot ); 3214 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 3215 3216 /* the same, but with PAGE_GUARD set */ 3217 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 3218 ok( ret == 43, "call returned wrong result, expected 43, got %ld\n", ret ); 3219 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 3220 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) 3221#ifdef __REACTOS__ 3222 ok( num_execute_fault_calls == 1 || broken(num_execute_fault_calls == 0) /* WS03 */, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3223#else 3224 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3225#endif 3226 else 3227 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3228 3229 ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); 3230 ok( ret == 43, "call returned wrong result, expected 43, got %ld\n", ret ); 3231 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %ld exceptions\n", num_guard_page_calls ); 3232 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %ld exceptions\n", num_execute_fault_calls ); 3233 3234 count = 64; 3235 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 3236 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 3237 ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %Iu\n", count ); 3238 3239 /* Restore the JMP instruction, set to executable, and then destroy the Window */ 3240 3241 memcpy( base, code_jmp, sizeof(code_jmp) ); 3242 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5); 3243 3244 count = 64; 3245 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize ); 3246 ok( !ret, "GetWriteWatch failed %lu\n", GetLastError() ); 3247 ok( count == 1, "wrong count %Iu\n", count ); 3248 ok( results[0] == base, "wrong result %p\n", results[0] ); 3249 3250 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot ); 3251 ok( success, "VirtualProtect failed %lu\n", GetLastError() ); 3252 3253 DestroyWindow( hWnd ); 3254 3255 success = UnregisterClassA( cls_name, GetModuleHandleA(0) ); 3256 ok( success, "UnregisterClass failed %lu\n", GetLastError() ); 3257 3258 VirtualFree( base, 0, MEM_RELEASE ); 3259 3260out: 3261 if (restore_flags) 3262 { 3263 ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags) ); 3264 ok( !ret, "NtSetInformationProcess failed with status %08lx\n", ret ); 3265 } 3266} 3267#endif /* __i386__ */ 3268 3269static void test_VirtualProtect(void) 3270{ 3271 static const struct test_data 3272 { 3273 DWORD prot_set, prot_get; 3274 } td[] = 3275 { 3276 { 0, 0 }, /* 0x00 */ 3277 { PAGE_NOACCESS, PAGE_NOACCESS }, /* 0x01 */ 3278 { PAGE_READONLY, PAGE_READONLY }, /* 0x02 */ 3279 { PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x03 */ 3280 { PAGE_READWRITE, PAGE_READWRITE }, /* 0x04 */ 3281 { PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x05 */ 3282 { PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x06 */ 3283 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x07 */ 3284 { PAGE_WRITECOPY, 0 }, /* 0x08 */ 3285 { PAGE_WRITECOPY | PAGE_NOACCESS, 0 }, /* 0x09 */ 3286 { PAGE_WRITECOPY | PAGE_READONLY, 0 }, /* 0x0a */ 3287 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, 0 }, /* 0x0b */ 3288 { PAGE_WRITECOPY | PAGE_READWRITE, 0 }, /* 0x0c */ 3289 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x0d */ 3290 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x0e */ 3291 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x0f */ 3292 3293 { PAGE_EXECUTE, PAGE_EXECUTE }, /* 0x10 */ 3294 { PAGE_EXECUTE_READ, PAGE_EXECUTE_READ }, /* 0x20 */ 3295 { PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x30 */ 3296 { PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_READWRITE }, /* 0x40 */ 3297 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0x50 */ 3298 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0x60 */ 3299 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x70 */ 3300 { PAGE_EXECUTE_WRITECOPY, 0 }, /* 0x80 */ 3301 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, 0 }, /* 0x90 */ 3302 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, 0 }, /* 0xa0 */ 3303 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0xb0 */ 3304 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, 0 }, /* 0xc0 */ 3305 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0xd0 */ 3306 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0xe0 */ 3307 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 } /* 0xf0 */ 3308 }; 3309 char *base, *ptr; 3310 DWORD ret, old_prot, rw_prot, exec_prot, i, j; 3311 MEMORY_BASIC_INFORMATION info; 3312 void *addr; 3313 SIZE_T size; 3314 NTSTATUS status; 3315 3316 SetLastError(0xdeadbeef); 3317 base = VirtualAlloc(0, si.dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS); 3318 ok(base != NULL, "VirtualAlloc failed %ld\n", GetLastError()); 3319 3320 SetLastError(0xdeadbeef); 3321 ret = VirtualProtect(base, si.dwPageSize, PAGE_READONLY, NULL); 3322 ok(!ret, "VirtualProtect should fail\n"); 3323 ok(GetLastError() == ERROR_NOACCESS, "expected ERROR_NOACCESS, got %ld\n", GetLastError()); 3324 old_prot = 0xdeadbeef; 3325 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot); 3326 ok(ret, "VirtualProtect failed %ld\n", GetLastError()); 3327 ok(old_prot == PAGE_NOACCESS, "got %#lx != expected PAGE_NOACCESS\n", old_prot); 3328 3329 addr = base; 3330 size = si.dwPageSize; 3331 status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_READONLY, NULL); 3332 ok(status == STATUS_ACCESS_VIOLATION, "NtProtectVirtualMemory should fail, got %08lx\n", status); 3333 addr = base; 3334 size = si.dwPageSize; 3335 old_prot = 0xdeadbeef; 3336 status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_NOACCESS, &old_prot); 3337 ok(status == STATUS_SUCCESS, "NtProtectVirtualMemory should succeed, got %08lx\n", status); 3338 ok(old_prot == PAGE_NOACCESS, "got %#lx != expected PAGE_NOACCESS\n", old_prot); 3339 3340 for (i = 0; i < ARRAY_SIZE(td); i++) 3341 { 3342 SetLastError(0xdeadbeef); 3343 ret = VirtualQuery(base, &info, sizeof(info)); 3344 ok(ret, "VirtualQuery failed %ld\n", GetLastError()); 3345 ok(info.BaseAddress == base, "%ld: got %p != expected %p\n", i, info.BaseAddress, base); 3346 ok(info.RegionSize == si.dwPageSize, "%ld: got %#Ix != expected %#lx\n", i, info.RegionSize, si.dwPageSize); 3347 ok(info.Protect == PAGE_NOACCESS, "%ld: got %#lx != expected PAGE_NOACCESS\n", i, info.Protect); 3348 ok(info.AllocationBase == base, "%ld: %p != %p\n", i, info.AllocationBase, base); 3349 ok(info.AllocationProtect == PAGE_NOACCESS, "%ld: %#lx != PAGE_NOACCESS\n", i, info.AllocationProtect); 3350 ok(info.State == MEM_COMMIT, "%ld: %#lx != MEM_COMMIT\n", i, info.State); 3351 ok(info.Type == MEM_PRIVATE, "%ld: %#lx != MEM_PRIVATE\n", i, info.Type); 3352 3353 old_prot = 0xdeadbeef; 3354 SetLastError(0xdeadbeef); 3355 ret = VirtualProtect(base, si.dwPageSize, td[i].prot_set, &old_prot); 3356 if (td[i].prot_get) 3357 { 3358 ok(ret, "%ld: VirtualProtect error %ld\n", i, GetLastError()); 3359 ok(old_prot == PAGE_NOACCESS, "%ld: got %#lx != expected PAGE_NOACCESS\n", i, old_prot); 3360 3361 SetLastError(0xdeadbeef); 3362 ret = VirtualQuery(base, &info, sizeof(info)); 3363 ok(ret, "VirtualQuery failed %ld\n", GetLastError()); 3364 ok(info.BaseAddress == base, "%ld: got %p != expected %p\n", i, info.BaseAddress, base); 3365 ok(info.RegionSize == si.dwPageSize, "%ld: got %#Ix != expected %#lx\n", i, info.RegionSize, si.dwPageSize); 3366 ok(info.Protect == td[i].prot_get, "%ld: got %#lx != expected %#lx\n", i, info.Protect, td[i].prot_get); 3367 ok(info.AllocationBase == base, "%ld: %p != %p\n", i, info.AllocationBase, base); 3368 ok(info.AllocationProtect == PAGE_NOACCESS, "%ld: %#lx != PAGE_NOACCESS\n", i, info.AllocationProtect); 3369 ok(info.State == MEM_COMMIT, "%ld: %#lx != MEM_COMMIT\n", i, info.State); 3370 ok(info.Type == MEM_PRIVATE, "%ld: %#lx != MEM_PRIVATE\n", i, info.Type); 3371 } 3372 else 3373 { 3374 ok(!ret, "%ld: VirtualProtect should fail\n", i); 3375 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%ld: expected ERROR_INVALID_PARAMETER, got %ld\n", i, GetLastError()); 3376 } 3377 3378 old_prot = 0xdeadbeef; 3379 SetLastError(0xdeadbeef); 3380 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot); 3381 ok(ret, "%ld: VirtualProtect error %ld\n", i, GetLastError()); 3382 if (td[i].prot_get) 3383 ok(old_prot == td[i].prot_get, "%ld: got %#lx != expected %#lx\n", i, old_prot, td[i].prot_get); 3384 else 3385 ok(old_prot == PAGE_NOACCESS, "%ld: got %#lx != expected PAGE_NOACCESS\n", i, old_prot); 3386 } 3387 3388 exec_prot = 0; 3389 3390 for (i = 0; i <= 4; i++) 3391 { 3392 rw_prot = 0; 3393 3394 for (j = 0; j <= 4; j++) 3395 { 3396 DWORD prot = exec_prot | rw_prot; 3397 3398 SetLastError(0xdeadbeef); 3399 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, prot); 3400 if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot)) 3401 { 3402 ok(!ptr, "VirtualAlloc(%02lx) should fail\n", prot); 3403 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError()); 3404 } 3405 else 3406 { 3407 if (prot & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY)) 3408 { 3409 ok(!ptr, "VirtualAlloc(%02lx) should fail\n", prot); 3410 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError()); 3411 } 3412 else 3413 { 3414 ok(ptr != NULL, "VirtualAlloc(%02lx) error %ld\n", prot, GetLastError()); 3415 ok(ptr == base, "expected %p, got %p\n", base, ptr); 3416 } 3417 } 3418 3419 SetLastError(0xdeadbeef); 3420 ret = VirtualProtect(base, si.dwPageSize, prot, &old_prot); 3421 if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot)) 3422 { 3423 ok(!ret, "VirtualProtect(%02lx) should fail\n", prot); 3424 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError()); 3425 } 3426 else 3427 { 3428 if (prot & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY)) 3429 { 3430 ok(!ret, "VirtualProtect(%02lx) should fail\n", prot); 3431 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError()); 3432 } 3433 else 3434 ok(ret, "VirtualProtect(%02lx) error %ld\n", prot, GetLastError()); 3435 } 3436 3437 rw_prot = 1 << j; 3438 } 3439 3440 exec_prot = 1 << (i + 4); 3441 } 3442 3443 VirtualFree(base, 0, MEM_RELEASE); 3444} 3445 3446static BOOL is_mem_writable(DWORD prot) 3447{ 3448 switch (prot & 0xff) 3449 { 3450 case PAGE_READWRITE: 3451 case PAGE_WRITECOPY: 3452 case PAGE_EXECUTE_READWRITE: 3453 case PAGE_EXECUTE_WRITECOPY: 3454 return TRUE; 3455 3456 default: 3457 return FALSE; 3458 } 3459} 3460 3461static void test_VirtualAlloc_protection(void) 3462{ 3463 static const struct test_data 3464 { 3465 DWORD prot; 3466 BOOL success; 3467 } td[] = 3468 { 3469 { 0, FALSE }, /* 0x00 */ 3470 { PAGE_NOACCESS, TRUE }, /* 0x01 */ 3471 { PAGE_READONLY, TRUE }, /* 0x02 */ 3472 { PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x03 */ 3473 { PAGE_READWRITE, TRUE }, /* 0x04 */ 3474 { PAGE_READWRITE | PAGE_NOACCESS, FALSE }, /* 0x05 */ 3475 { PAGE_READWRITE | PAGE_READONLY, FALSE }, /* 0x06 */ 3476 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x07 */ 3477 { PAGE_WRITECOPY, FALSE }, /* 0x08 */ 3478 { PAGE_WRITECOPY | PAGE_NOACCESS, FALSE }, /* 0x09 */ 3479 { PAGE_WRITECOPY | PAGE_READONLY, FALSE }, /* 0x0a */ 3480 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, FALSE }, /* 0x0b */ 3481 { PAGE_WRITECOPY | PAGE_READWRITE, FALSE }, /* 0x0c */ 3482 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, FALSE }, /* 0x0d */ 3483 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, FALSE }, /* 0x0e */ 3484 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x0f */ 3485 3486 { PAGE_EXECUTE, TRUE }, /* 0x10 */ 3487 { PAGE_EXECUTE_READ, TRUE }, /* 0x20 */ 3488 { PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0x30 */ 3489 { PAGE_EXECUTE_READWRITE, TRUE }, /* 0x40 */ 3490 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE }, /* 0x50 */ 3491 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE }, /* 0x60 */ 3492 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0x70 */ 3493 { PAGE_EXECUTE_WRITECOPY, FALSE }, /* 0x80 */ 3494 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, FALSE }, /* 0x90 */ 3495 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, FALSE }, /* 0xa0 */ 3496 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0xb0 */ 3497 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, FALSE }, /* 0xc0 */ 3498 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE }, /* 0xd0 */ 3499 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE }, /* 0xe0 */ 3500 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE } /* 0xf0 */ 3501 }; 3502 char *base, *ptr; 3503 DWORD ret, i; 3504 MEMORY_BASIC_INFORMATION info; 3505 3506 for (i = 0; i < ARRAY_SIZE(td); i++) 3507 { 3508 SetLastError(0xdeadbeef); 3509 base = VirtualAlloc(0, si.dwPageSize, MEM_COMMIT, td[i].prot); 3510 3511 if (td[i].success) 3512 { 3513 ok(base != NULL, "%ld: VirtualAlloc failed %ld\n", i, GetLastError()); 3514 3515 SetLastError(0xdeadbeef); 3516 ret = VirtualQuery(base, &info, sizeof(info)); 3517 ok(ret, "VirtualQuery failed %ld\n", GetLastError()); 3518 ok(info.BaseAddress == base, "%ld: got %p != expected %p\n", i, info.BaseAddress, base); 3519 ok(info.RegionSize == si.dwPageSize, "%ld: got %#Ix != expected %#lx\n", i, info.RegionSize, si.dwPageSize); 3520 ok(info.Protect == td[i].prot, "%ld: got %#lx != expected %#lx\n", i, info.Protect, td[i].prot); 3521 ok(info.AllocationBase == base, "%ld: %p != %p\n", i, info.AllocationBase, base); 3522 ok(info.AllocationProtect == td[i].prot, "%ld: %#lx != %#lx\n", i, info.AllocationProtect, td[i].prot); 3523 ok(info.State == MEM_COMMIT, "%ld: %#lx != MEM_COMMIT\n", i, info.State); 3524 ok(info.Type == MEM_PRIVATE, "%ld: %#lx != MEM_PRIVATE\n", i, info.Type); 3525 3526 if (is_mem_writable(info.Protect)) 3527 { 3528 base[0] = 0xfe; 3529 3530 SetLastError(0xdeadbeef); 3531 ret = VirtualQuery(base, &info, sizeof(info)); 3532 ok(ret, "VirtualQuery failed %ld\n", GetLastError()); 3533 ok(info.Protect == td[i].prot, "%ld: got %#lx != expected %#lx\n", i, info.Protect, td[i].prot); 3534 } 3535 3536 SetLastError(0xdeadbeef); 3537 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, td[i].prot); 3538 ok(ptr == base, "%ld: VirtualAlloc failed %ld\n", i, GetLastError()); 3539 3540 VirtualFree(base, 0, MEM_RELEASE); 3541 } 3542 else 3543 { 3544 ok(!base, "%ld: VirtualAlloc should fail\n", i); 3545 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%ld: expected ERROR_INVALID_PARAMETER, got %ld\n", i, GetLastError()); 3546 } 3547 } 3548} 3549 3550static void test_CreateFileMapping_protection(void) 3551{ 3552 static const struct test_data 3553 { 3554 DWORD prot; 3555 BOOL success; 3556 DWORD prot_after_write; 3557 } td[] = 3558 { 3559 { 0, FALSE, 0 }, /* 0x00 */ 3560 { PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x01 */ 3561 { PAGE_READONLY, TRUE, PAGE_READONLY }, /* 0x02 */ 3562 { PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x03 */ 3563 { PAGE_READWRITE, TRUE, PAGE_READWRITE }, /* 0x04 */ 3564 { PAGE_READWRITE | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x05 */ 3565 { PAGE_READWRITE | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x06 */ 3566 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x07 */ 3567 { PAGE_WRITECOPY, TRUE, PAGE_READWRITE }, /* 0x08 */ 3568 { PAGE_WRITECOPY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x09 */ 3569 { PAGE_WRITECOPY | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0a */ 3570 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0b */ 3571 { PAGE_WRITECOPY | PAGE_READWRITE, FALSE, PAGE_NOACCESS }, /* 0x0c */ 3572 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x0d */ 3573 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0e */ 3574 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x0f */ 3575 3576 { PAGE_EXECUTE, FALSE, PAGE_EXECUTE }, /* 0x10 */ 3577 { PAGE_EXECUTE_READ, TRUE, PAGE_EXECUTE_READ }, /* 0x20 */ 3578 { PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_EXECUTE_READ }, /* 0x30 */ 3579 { PAGE_EXECUTE_READWRITE, TRUE, PAGE_EXECUTE_READWRITE }, /* 0x40 */ 3580 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x50 */ 3581 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0x60 */ 3582 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x70 */ 3583 { PAGE_EXECUTE_WRITECOPY, TRUE, PAGE_EXECUTE_READWRITE }, /* 0x80 */ 3584 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x90 */ 3585 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0xa0 */ 3586 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0xb0 */ 3587 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, FALSE, PAGE_NOACCESS }, /* 0xc0 */ 3588 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0xd0 */ 3589 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0xe0 */ 3590 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS } /* 0xf0 */ 3591 }; 3592 char *base, *ptr; 3593 DWORD ret, i, alloc_prot, old_prot; 3594 MEMORY_BASIC_INFORMATION info; 3595 char temp_path[MAX_PATH]; 3596 char file_name[MAX_PATH]; 3597 HANDLE hfile, hmap; 3598 BOOL page_exec_supported = TRUE; 3599 3600 GetTempPathA(MAX_PATH, temp_path); 3601 GetTempFileNameA(temp_path, "map", 0, file_name); 3602 3603 SetLastError(0xdeadbeef); 3604 hfile = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0); 3605 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %ld\n", file_name, GetLastError()); 3606 SetFilePointer(hfile, si.dwPageSize, NULL, FILE_BEGIN); 3607 SetEndOfFile(hfile); 3608 3609 for (i = 0; i < ARRAY_SIZE(td); i++) 3610 { 3611 SetLastError(0xdeadbeef); 3612 hmap = CreateFileMappingW(hfile, NULL, td[i].prot | SEC_COMMIT, 0, si.dwPageSize, NULL); 3613 3614 if (td[i].success) 3615 { 3616 if (!hmap) 3617 { 3618 trace("%ld: CreateFileMapping(%04lx) failed: %ld\n", i, td[i].prot, GetLastError()); 3619 /* NT4 and win2k don't support EXEC on file mappings */ 3620 if (td[i].prot == PAGE_EXECUTE_READ || td[i].prot == PAGE_EXECUTE_READWRITE) 3621 { 3622 page_exec_supported = FALSE; 3623 ok(broken(!hmap), "%ld: CreateFileMapping doesn't support PAGE_EXECUTE\n", i); 3624 continue; 3625 } 3626 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */ 3627 if (td[i].prot == PAGE_EXECUTE_WRITECOPY) 3628 { 3629 page_exec_supported = FALSE; 3630 ok(broken(!hmap), "%ld: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i); 3631 continue; 3632 } 3633 } 3634 ok(hmap != 0, "%ld: CreateFileMapping(%04lx) error %ld\n", i, td[i].prot, GetLastError()); 3635 3636 base = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0); 3637 ok(base != NULL, "%ld: MapViewOfFile failed %ld\n", i, GetLastError()); 3638 3639 SetLastError(0xdeadbeef); 3640 ret = VirtualQuery(base, &info, sizeof(info)); 3641 ok(ret, "VirtualQuery failed %ld\n", GetLastError()); 3642 ok(info.BaseAddress == base, "%ld: got %p != expected %p\n", i, info.BaseAddress, base); 3643 ok(info.RegionSize == si.dwPageSize, "%ld: got %#Ix != expected %#lx\n", i, info.RegionSize, si.dwPageSize); 3644 ok(info.Protect == PAGE_READONLY, "%ld: got %#lx != expected PAGE_READONLY\n", i, info.Protect); 3645 ok(info.AllocationBase == base, "%ld: %p != %p\n", i, info.AllocationBase, base); 3646 ok(info.AllocationProtect == PAGE_READONLY, "%ld: %#lx != PAGE_READONLY\n", i, info.AllocationProtect); 3647 ok(info.State == MEM_COMMIT, "%ld: %#lx != MEM_COMMIT\n", i, info.State); 3648 ok(info.Type == MEM_MAPPED, "%ld: %#lx != MEM_MAPPED\n", i, info.Type); 3649 3650 SetLastError(0xdeadbeef); 3651 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, td[i].prot); 3652 ok(!ptr, "%ld: VirtualAlloc(%02lx) should fail\n", i, td[i].prot); 3653 ok(GetLastError() == ERROR_ACCESS_DENIED, "%ld: expected ERROR_ACCESS_DENIED, got %ld\n", i, GetLastError()); 3654 3655 SetLastError(0xdeadbeef); 3656 ret = VirtualProtect(base, si.dwPageSize, td[i].prot, &old_prot); 3657 if (td[i].prot == PAGE_READONLY || td[i].prot == PAGE_WRITECOPY) 3658 ok(ret, "%ld: VirtualProtect(%02lx) error %ld\n", i, td[i].prot, GetLastError()); 3659 else 3660 { 3661 ok(!ret, "%ld: VirtualProtect(%02lx) should fail\n", i, td[i].prot); 3662 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%ld: expected ERROR_INVALID_PARAMETER, got %ld\n", i, GetLastError()); 3663 } 3664 3665 UnmapViewOfFile(base); 3666 CloseHandle(hmap); 3667 } 3668 else 3669 { 3670 ok(!hmap, "%ld: CreateFileMapping should fail\n", i); 3671 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%ld: expected ERROR_INVALID_PARAMETER, got %ld\n", i, GetLastError()); 3672 } 3673 } 3674 3675 if (page_exec_supported) alloc_prot = PAGE_EXECUTE_READWRITE; 3676 else alloc_prot = PAGE_READWRITE; 3677 SetLastError(0xdeadbeef); 3678 hmap = CreateFileMappingW(hfile, NULL, alloc_prot, 0, si.dwPageSize, NULL); 3679 ok(hmap != 0, "%ld: CreateFileMapping error %ld\n", i, GetLastError()); 3680 3681 for (i = 0; i < ARRAY_SIZE(td); i++) 3682 { 3683 SetLastError(0xdeadbeef); 3684 base = MapViewOfFile(hmap, FILE_MAP_READ | FILE_MAP_WRITE | (page_exec_supported ? FILE_MAP_EXECUTE : 0), 0, 0, 0); 3685 ok(base != NULL, "MapViewOfFile failed %ld\n", GetLastError()); 3686 3687 old_prot = 0xdeadbeef; 3688 SetLastError(0xdeadbeef); 3689 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot); 3690 ok(ret, "VirtualProtect error %ld\n", GetLastError()); 3691 ok(old_prot == alloc_prot, "got %#lx != expected %#lx\n", old_prot, alloc_prot); 3692 3693 SetLastError(0xdeadbeef); 3694 ret = VirtualQuery(base, &info, sizeof(info)); 3695 ok(ret, "VirtualQuery failed %ld\n", GetLastError()); 3696 ok(info.BaseAddress == base, "%ld: got %p != expected %p\n", i, info.BaseAddress, base); 3697 ok(info.RegionSize == si.dwPageSize, "%ld: got %#Ix != expected %#lx\n", i, info.RegionSize, si.dwPageSize); 3698 ok(info.Protect == PAGE_NOACCESS, "%ld: got %#lx != expected PAGE_NOACCESS\n", i, info.Protect); 3699 ok(info.AllocationBase == base, "%ld: %p != %p\n", i, info.AllocationBase, base); 3700 ok(info.AllocationProtect == alloc_prot, "%ld: %#lx != %#lx\n", i, info.AllocationProtect, alloc_prot); 3701 ok(info.State == MEM_COMMIT, "%ld: %#lx != MEM_COMMIT\n", i, info.State); 3702 ok(info.Type == MEM_MAPPED, "%ld: %#lx != MEM_MAPPED\n", i, info.Type); 3703 3704 old_prot = 0xdeadbeef; 3705 SetLastError(0xdeadbeef); 3706 ret = VirtualProtect(base, si.dwPageSize, td[i].prot, &old_prot); 3707 if (td[i].success || td[i].prot == PAGE_NOACCESS || td[i].prot == PAGE_EXECUTE) 3708 { 3709 if (!ret) 3710 { 3711 /* win2k and XP don't support EXEC on file mappings */ 3712 if (td[i].prot == PAGE_EXECUTE) 3713 { 3714 ok(broken(!ret), "%ld: VirtualProtect doesn't support PAGE_EXECUTE\n", i); 3715 continue; 3716 } 3717 /* NT4 and win2k don't support EXEC on file mappings */ 3718 if (td[i].prot == PAGE_EXECUTE_READ || td[i].prot == PAGE_EXECUTE_READWRITE) 3719 { 3720 ok(broken(!ret), "%ld: VirtualProtect doesn't support PAGE_EXECUTE\n", i); 3721 continue; 3722 } 3723 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */ 3724 if (td[i].prot == PAGE_EXECUTE_WRITECOPY) 3725 { 3726 ok(broken(!ret), "%ld: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i); 3727 continue; 3728 } 3729 } 3730 3731 ok(ret, "%ld: VirtualProtect error %ld\n", i, GetLastError()); 3732 ok(old_prot == PAGE_NOACCESS, "%ld: got %#lx != expected PAGE_NOACCESS\n", i, old_prot); 3733 3734 SetLastError(0xdeadbeef); 3735 ret = VirtualQuery(base, &info, sizeof(info)); 3736 ok(ret, "VirtualQuery failed %ld\n", GetLastError()); 3737 ok(info.BaseAddress == base, "%ld: got %p != expected %p\n", i, info.BaseAddress, base); 3738 ok(info.RegionSize == si.dwPageSize, "%ld: got %#Ix != expected %#lx\n", i, info.RegionSize, si.dwPageSize); 3739 ok(info.Protect == td[i].prot, "%ld: got %#lx != expected %#lx\n", i, info.Protect, td[i].prot); 3740 ok(info.AllocationBase == base, "%ld: %p != %p\n", i, info.AllocationBase, base); 3741 ok(info.AllocationProtect == alloc_prot, "%ld: %#lx != %#lx\n", i, info.AllocationProtect, alloc_prot); 3742 ok(info.State == MEM_COMMIT, "%ld: %#lx != MEM_COMMIT\n", i, info.State); 3743 ok(info.Type == MEM_MAPPED, "%ld: %#lx != MEM_MAPPED\n", i, info.Type); 3744 3745 if (is_mem_writable(info.Protect)) 3746 { 3747 base[0] = 0xfe; 3748 3749 SetLastError(0xdeadbeef); 3750 ret = VirtualQuery(base, &info, sizeof(info)); 3751 ok(ret, "VirtualQuery failed %ld\n", GetLastError()); 3752 /* FIXME: remove the condition below once Wine is fixed */ 3753 todo_wine_if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY) 3754 ok(info.Protect == td[i].prot_after_write, "%ld: got %#lx != expected %#lx\n", i, info.Protect, td[i].prot_after_write); 3755 } 3756 } 3757 else 3758 { 3759 ok(!ret, "%ld: VirtualProtect should fail\n", i); 3760 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%ld: expected ERROR_INVALID_PARAMETER, got %ld\n", i, GetLastError()); 3761 continue; 3762 } 3763 3764 old_prot = 0xdeadbeef; 3765 SetLastError(0xdeadbeef); 3766 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot); 3767 ok(ret, "%ld: VirtualProtect error %ld\n", i, GetLastError()); 3768 /* FIXME: remove the condition below once Wine is fixed */ 3769 todo_wine_if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY) 3770 ok(old_prot == td[i].prot_after_write, "%ld: got %#lx != expected %#lx\n", i, old_prot, td[i].prot_after_write); 3771 3772 UnmapViewOfFile(base); 3773 } 3774 3775 CloseHandle(hmap); 3776 3777 CloseHandle(hfile); 3778 DeleteFileA(file_name); 3779} 3780 3781#define ACCESS_READ 0x01 3782#define ACCESS_WRITE 0x02 3783#define ACCESS_EXECUTE 0x04 3784 3785static DWORD page_prot_to_access(DWORD prot) 3786{ 3787 switch (prot) 3788 { 3789 case PAGE_READONLY: 3790 case PAGE_WRITECOPY: 3791 return ACCESS_READ; 3792 case PAGE_READWRITE: 3793 return ACCESS_READ | ACCESS_WRITE; 3794 case PAGE_EXECUTE: 3795 case PAGE_EXECUTE_READ: 3796 case PAGE_EXECUTE_WRITECOPY: 3797 return ACCESS_READ | ACCESS_EXECUTE; 3798 case PAGE_EXECUTE_READWRITE: 3799 return ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE; 3800 default: 3801 return 0; 3802 } 3803} 3804 3805static BOOL is_compatible_protection(DWORD view_prot, DWORD prot) 3806{ 3807 DWORD view_access, prot_access; 3808 3809 view_access = page_prot_to_access(view_prot); 3810 prot_access = page_prot_to_access(prot); 3811 3812 return ((view_access & prot_access) == prot_access); 3813} 3814 3815static DWORD map_prot_to_access(DWORD prot) 3816{ 3817 switch (prot) 3818 { 3819 case PAGE_READWRITE: 3820 return SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY; 3821 case PAGE_EXECUTE_READWRITE: 3822 return SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE | SECTION_QUERY; 3823 case PAGE_READONLY: 3824 case PAGE_WRITECOPY: 3825 return SECTION_MAP_READ | SECTION_QUERY; 3826 case PAGE_EXECUTE: 3827 case PAGE_EXECUTE_READ: 3828 case PAGE_EXECUTE_WRITECOPY: 3829 return SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_QUERY; 3830 default: 3831 return 0; 3832 } 3833} 3834 3835static DWORD map_prot_no_write(DWORD prot) 3836{ 3837 switch (prot) 3838 { 3839 case PAGE_READWRITE: return PAGE_WRITECOPY; 3840 case PAGE_EXECUTE_READWRITE: return PAGE_EXECUTE_WRITECOPY; 3841 default: return prot; 3842 } 3843} 3844 3845static DWORD map_prot_written(DWORD prot) 3846{ 3847 switch (prot) 3848 { 3849 case PAGE_WRITECOPY: return PAGE_READWRITE; 3850 case PAGE_EXECUTE_WRITECOPY: return PAGE_EXECUTE_READWRITE; 3851 default: return prot; 3852 } 3853} 3854 3855static DWORD file_access_to_prot( DWORD access ) 3856{ 3857 BOOL exec = access & FILE_MAP_EXECUTE; 3858 access &= ~FILE_MAP_EXECUTE; 3859 3860 if (access == FILE_MAP_COPY) return exec ? PAGE_EXECUTE_WRITECOPY : PAGE_WRITECOPY; 3861 if (access & FILE_MAP_WRITE) return exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 3862 if (access & FILE_MAP_READ) return exec ? PAGE_EXECUTE_READ : PAGE_READONLY; 3863 return PAGE_NOACCESS; 3864} 3865 3866static BOOL is_compatible_access(DWORD map_prot, DWORD view_prot) 3867{ 3868 DWORD access = map_prot_to_access(map_prot); 3869 DWORD view_access = map_prot_to_access( file_access_to_prot( view_prot )); 3870 if (!view_access) view_access = SECTION_MAP_READ; 3871 return (view_access & access) == view_access; 3872} 3873 3874static void *map_view_of_file(HANDLE handle, DWORD access) 3875{ 3876 NTSTATUS status; 3877 LARGE_INTEGER offset; 3878 SIZE_T count; 3879 ULONG protect; 3880 void *addr; 3881 3882 if (!pNtMapViewOfSection) return NULL; 3883 3884 count = 0; 3885 offset.u.LowPart = 0; 3886 offset.u.HighPart = 0; 3887 3888 protect = file_access_to_prot( access ); 3889 addr = NULL; 3890 status = pNtMapViewOfSection(handle, GetCurrentProcess(), &addr, 0, 0, &offset, 3891 &count, 1 /* ViewShare */, 0, protect); 3892 if ((int)status < 0) addr = NULL; 3893 return addr; 3894} 3895 3896static void test_mapping( HANDLE hfile, DWORD sec_flags, BOOL readonly ) 3897{ 3898 static const DWORD page_prot[] = 3899 { 3900 PAGE_NOACCESS, PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY, 3901 PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY 3902 }; 3903 static const struct 3904 { 3905 DWORD access, prot; 3906 } view[] = 3907 { 3908 { 0, PAGE_NOACCESS }, /* 0x00 */ 3909 { FILE_MAP_COPY, PAGE_WRITECOPY }, /* 0x01 */ 3910 { FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x02 */ 3911 { FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x03 */ 3912 { FILE_MAP_READ, PAGE_READONLY }, /* 0x04 */ 3913 { FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x05 */ 3914 { FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x06 */ 3915 { FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x07 */ 3916 { SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x08 */ 3917 { SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x09 */ 3918 { SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0a */ 3919 { SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0b */ 3920 { SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_READONLY }, /* 0x0c */ 3921 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x0d */ 3922 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0e */ 3923 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0f */ 3924 { FILE_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x20 */ 3925 { FILE_MAP_EXECUTE | FILE_MAP_COPY, PAGE_EXECUTE_WRITECOPY }, /* 0x21 */ 3926 { FILE_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x22 */ 3927 { FILE_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x23 */ 3928 { FILE_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x24 */ 3929 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x25 */ 3930 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x26 */ 3931 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x27 */ 3932 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x28 */ 3933 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x29 */ 3934 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2a */ 3935 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x2b */ 3936 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x2c */ 3937 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x2d */ 3938 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2e */ 3939 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE } /* 0x2f */ 3940 }; 3941 void *base, *nt_base, *ptr; 3942 DWORD i, j, k, ret, old_prot, prev_prot, alloc_prot; 3943 HANDLE hmap; 3944 MEMORY_BASIC_INFORMATION info, nt_info; 3945 BOOL anon_mapping = (hfile == INVALID_HANDLE_VALUE); 3946 3947 trace( "testing %s mapping flags %08lx %s\n", anon_mapping ? "anonymous" : "file", 3948 sec_flags, readonly ? "readonly file" : "" ); 3949 for (i = 0; i < ARRAY_SIZE(page_prot); i++) 3950 { 3951 SetLastError(0xdeadbeef); 3952 hmap = CreateFileMappingW(hfile, NULL, page_prot[i] | sec_flags, 0, 2*si.dwPageSize, NULL); 3953 3954 if (readonly && (page_prot[i] == PAGE_READWRITE || page_prot[i] == PAGE_EXECUTE_READ 3955 || page_prot[i] == PAGE_EXECUTE_READWRITE || page_prot[i] == PAGE_EXECUTE_WRITECOPY)) 3956 { 3957 todo_wine_if(page_prot[i] == PAGE_EXECUTE_READ || page_prot[i] == PAGE_EXECUTE_WRITECOPY) 3958 { 3959 ok(!hmap, "%ld: CreateFileMapping(%04lx) should fail\n", i, page_prot[i]); 3960 ok(GetLastError() == ERROR_ACCESS_DENIED || broken(GetLastError() == ERROR_INVALID_PARAMETER), 3961 "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 3962 } 3963 if (hmap) CloseHandle(hmap); 3964 continue; 3965 } 3966 3967 if (page_prot[i] == PAGE_NOACCESS) 3968 { 3969 HANDLE hmap2; 3970 3971 ok(!hmap, "CreateFileMapping(PAGE_NOACCESS) should fail\n"); 3972 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError()); 3973 3974 /* A trick to create a not accessible mapping */ 3975 SetLastError(0xdeadbeef); 3976 if (sec_flags & SEC_IMAGE) 3977 hmap = CreateFileMappingW(hfile, NULL, PAGE_WRITECOPY | sec_flags, 0, si.dwPageSize, NULL); 3978 else 3979 hmap = CreateFileMappingW(hfile, NULL, PAGE_READONLY | sec_flags, 0, si.dwPageSize, NULL); 3980 ok(hmap != 0, "CreateFileMapping(PAGE_READWRITE) error %ld\n", GetLastError()); 3981 SetLastError(0xdeadbeef); 3982 ret = DuplicateHandle(GetCurrentProcess(), hmap, GetCurrentProcess(), &hmap2, 0, FALSE, 0); 3983 ok(ret, "DuplicateHandle error %ld\n", GetLastError()); 3984 CloseHandle(hmap); 3985 hmap = hmap2; 3986 } 3987 if (page_prot[i] == PAGE_EXECUTE) 3988 { 3989 ok(!hmap, "CreateFileMapping(PAGE_EXECUTE) should fail\n"); 3990 ok(GetLastError() == ERROR_INVALID_PARAMETER, 3991 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError()); 3992 continue; 3993 } 3994 3995 if (!hmap) 3996 { 3997 trace("%ld: CreateFileMapping(%04lx) failed: %ld\n", i, page_prot[i], GetLastError()); 3998 3999 if ((sec_flags & SEC_IMAGE) && 4000 (page_prot[i] == PAGE_READWRITE || page_prot[i] == PAGE_EXECUTE_READWRITE)) 4001 continue; /* SEC_IMAGE doesn't support write access */ 4002 4003 /* NT4 and win2k don't support EXEC on file mappings */ 4004 if (page_prot[i] == PAGE_EXECUTE_READ || page_prot[i] == PAGE_EXECUTE_READWRITE) 4005 { 4006 ok(broken(!hmap), "%ld: CreateFileMapping doesn't support PAGE_EXECUTE\n", i); 4007 continue; 4008 } 4009 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */ 4010 if (page_prot[i] == PAGE_EXECUTE_WRITECOPY) 4011 { 4012 ok(broken(!hmap), "%ld: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i); 4013 continue; 4014 } 4015 } 4016 4017 ok(hmap != 0, "%ld: CreateFileMapping(%04lx) error %ld\n", i, page_prot[i], GetLastError()); 4018 4019 for (j = 0; j < ARRAY_SIZE(view); j++) 4020 { 4021 nt_base = map_view_of_file(hmap, view[j].access); 4022 if (nt_base) 4023 { 4024 SetLastError(0xdeadbeef); 4025 ret = VirtualQuery(nt_base, &nt_info, sizeof(nt_info)); 4026 ok(ret, "%ld: VirtualQuery failed %ld\n", j, GetLastError()); 4027 UnmapViewOfFile(nt_base); 4028 } 4029 4030 SetLastError(0xdeadbeef); 4031 base = MapViewOfFile(hmap, view[j].access, 0, 0, 0); 4032 4033 /* Vista+ supports FILE_MAP_EXECUTE properly, earlier versions don't */ 4034 ok(!nt_base == !base || 4035 broken((view[j].access & FILE_MAP_EXECUTE) && !nt_base != !base), 4036 "%ld: (%04lx/%04lx) NT %p kernel %p\n", j, page_prot[i], view[j].access, nt_base, base); 4037 4038 if (!is_compatible_access(page_prot[i], view[j].access)) 4039 { 4040 /* FILE_MAP_EXECUTE | FILE_MAP_COPY broken on XP */ 4041 if (base != NULL && view[j].access == (FILE_MAP_EXECUTE | FILE_MAP_COPY)) 4042 { 4043 ok( broken(base != NULL), "%ld: MapViewOfFile(%04lx/%04lx) should fail\n", 4044 j, page_prot[i], view[j].access); 4045 UnmapViewOfFile( base ); 4046 } 4047 else 4048 { 4049 ok(!base, "%ld: MapViewOfFile(%04lx/%04lx) should fail\n", 4050 j, page_prot[i], view[j].access); 4051 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %ld\n", GetLastError()); 4052 } 4053 continue; 4054 } 4055 4056 /* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */ 4057 if (!base && (view[j].access & FILE_MAP_EXECUTE)) 4058 { 4059 ok(broken(!base), "%ld: MapViewOfFile(%04lx/%04lx) failed %ld\n", j, page_prot[i], view[j].access, GetLastError()); 4060 continue; 4061 } 4062 4063 ok(base != NULL, "%ld: MapViewOfFile(%04lx/%04lx) failed %ld\n", j, page_prot[i], view[j].access, GetLastError()); 4064 4065 SetLastError(0xdeadbeef); 4066 ret = VirtualQuery(base, &info, sizeof(info)); 4067 ok(ret, "%ld: VirtualQuery failed %ld\n", j, GetLastError()); 4068 ok(info.BaseAddress == base, "%ld: (%04lx) got %p, expected %p\n", j, view[j].access, info.BaseAddress, base); 4069 ok(info.RegionSize == 2*si.dwPageSize || (info.RegionSize == si.dwPageSize && (sec_flags & SEC_IMAGE)), 4070 "%ld: (%04lx) got %#Ix != expected %#lx\n", j, view[j].access, info.RegionSize, 2*si.dwPageSize); 4071 if (sec_flags & SEC_IMAGE) 4072 ok(info.Protect == PAGE_READONLY, 4073 "%ld: (%04lx) got %#lx, expected %#lx\n", j, view[j].access, info.Protect, view[j].prot); 4074 else 4075 ok(info.Protect == view[j].prot || 4076 broken(view[j].prot == PAGE_EXECUTE_READ && info.Protect == PAGE_READONLY) || /* win2k */ 4077 broken(view[j].prot == PAGE_EXECUTE_READWRITE && info.Protect == PAGE_READWRITE) || /* win2k */ 4078 broken(view[j].prot == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */ 4079 "%ld: (%04lx) got %#lx, expected %#lx\n", j, view[j].access, info.Protect, view[j].prot); 4080 ok(info.AllocationBase == base, "%ld: (%04lx) got %p, expected %p\n", j, view[j].access, info.AllocationBase, base); 4081 if (sec_flags & SEC_IMAGE) 4082 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%ld: (%04lx) got %#lx, expected %#lx\n", 4083 j, view[j].access, info.AllocationProtect, info.Protect); 4084 else 4085 ok(info.AllocationProtect == info.Protect, "%ld: (%04lx) got %#lx, expected %#lx\n", 4086 j, view[j].access, info.AllocationProtect, info.Protect); 4087 ok(info.State == MEM_COMMIT, "%ld: (%04lx) got %#lx, expected MEM_COMMIT\n", j, view[j].access, info.State); 4088 ok(info.Type == (sec_flags & SEC_IMAGE) ? SEC_IMAGE : MEM_MAPPED, 4089 "%ld: (%04lx) got %#lx, expected MEM_MAPPED\n", j, view[j].access, info.Type); 4090 4091 if (nt_base && base) 4092 { 4093 ok(nt_info.RegionSize == info.RegionSize, "%ld: (%04lx) got %#Ix != expected %#Ix\n", j, view[j].access, nt_info.RegionSize, info.RegionSize); 4094 ok(nt_info.Protect == info.Protect /* Vista+ */ || 4095 broken(nt_info.AllocationProtect == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */ 4096 "%ld: (%04lx) got %#lx, expected %#lx\n", j, view[j].access, nt_info.Protect, info.Protect); 4097 ok(nt_info.AllocationProtect == info.AllocationProtect /* Vista+ */ || 4098 broken(nt_info.AllocationProtect == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */ 4099 "%ld: (%04lx) got %#lx, expected %#lx\n", j, view[j].access, nt_info.AllocationProtect, info.AllocationProtect); 4100 ok(nt_info.State == info.State, "%ld: (%04lx) got %#lx, expected %#lx\n", j, view[j].access, nt_info.State, info.State); 4101 ok(nt_info.Type == info.Type, "%ld: (%04lx) got %#lx, expected %#lx\n", j, view[j].access, nt_info.Type, info.Type); 4102 } 4103 4104 prev_prot = info.Protect; 4105 alloc_prot = info.AllocationProtect; 4106 4107 for (k = 0; k < ARRAY_SIZE(page_prot); k++) 4108 { 4109 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/ 4110 DWORD actual_prot = (sec_flags & SEC_IMAGE) ? map_prot_no_write(page_prot[k]) : page_prot[k]; 4111 SetLastError(0xdeadbeef); 4112 old_prot = 0xdeadbeef; 4113 ret = VirtualProtect(base, si.dwPageSize, page_prot[k], &old_prot); 4114 if (is_compatible_protection(alloc_prot, actual_prot)) 4115 { 4116 /* win2k and XP don't support EXEC on file mappings */ 4117 if (!ret && (page_prot[k] == PAGE_EXECUTE || page_prot[k] == PAGE_EXECUTE_WRITECOPY || view[j].prot == PAGE_EXECUTE_WRITECOPY)) 4118 { 4119 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n"); 4120 continue; 4121 } 4122 4123 todo_wine_if(readonly && page_prot[k] == PAGE_WRITECOPY && view[j].prot != PAGE_WRITECOPY) 4124 ok(ret, "VirtualProtect error %ld, map %#lx, view %#lx, requested prot %#lx\n", GetLastError(), page_prot[i], view[j].prot, page_prot[k]); 4125 todo_wine_if(readonly && page_prot[k] == PAGE_WRITECOPY && view[j].prot != PAGE_WRITECOPY) 4126 ok(old_prot == prev_prot, "got %#lx, expected %#lx\n", old_prot, prev_prot); 4127 prev_prot = actual_prot; 4128 4129 ret = VirtualQuery(base, &info, sizeof(info)); 4130 ok(ret, "%ld: VirtualQuery failed %ld\n", j, GetLastError()); 4131 todo_wine_if(readonly && page_prot[k] == PAGE_WRITECOPY && view[j].prot != PAGE_WRITECOPY) 4132 ok(info.Protect == actual_prot, 4133 "VirtualProtect wrong prot, map %#lx, view %#lx, requested prot %#lx got %#lx\n", 4134 page_prot[i], view[j].prot, page_prot[k], info.Protect ); 4135 } 4136 else 4137 { 4138 ok(!ret, "VirtualProtect should fail, map %#lx, view %#lx, requested prot %#lx\n", page_prot[i], view[j].prot, page_prot[k]); 4139 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError()); 4140 } 4141 } 4142 4143 for (k = 0; k < ARRAY_SIZE(page_prot); k++) 4144 { 4145 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/ 4146 SetLastError(0xdeadbeef); 4147 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, page_prot[k]); 4148 if (anon_mapping) 4149 { 4150 if (is_compatible_protection(view[j].prot, page_prot[k])) 4151 { 4152 ok(ptr != NULL, "VirtualAlloc error %lu, map %#lx, view %#lx, requested prot %#lx\n", 4153 GetLastError(), page_prot[i], view[j].prot, page_prot[k]); 4154 } 4155 else 4156 { 4157 /* versions <= Vista accept all protections without checking */ 4158 ok(!ptr || broken(ptr != NULL), 4159 "VirtualAlloc should fail, map %#lx, view %#lx, requested prot %#lx\n", 4160 page_prot[i], view[j].prot, page_prot[k]); 4161 if (!ptr) ok( GetLastError() == ERROR_INVALID_PARAMETER, 4162 "wrong error %lu\n", GetLastError()); 4163 } 4164 if (ptr) 4165 { 4166 ret = VirtualQuery(base, &info, sizeof(info)); 4167 ok(ret, "%ld: VirtualQuery failed %ld\n", j, GetLastError()); 4168 ok(info.Protect == page_prot[k] || 4169 /* if the mapping doesn't have write access, 4170 * broken versions silently switch to WRITECOPY */ 4171 broken( info.Protect == map_prot_no_write(page_prot[k]) ), 4172 "VirtualAlloc wrong prot, map %#lx, view %#lx, requested prot %#lx got %#lx\n", 4173 page_prot[i], view[j].prot, page_prot[k], info.Protect ); 4174 } 4175 } 4176 else 4177 { 4178 ok(!ptr, "VirtualAlloc(%02lx) should fail\n", page_prot[k]); 4179 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 4180 } 4181 } 4182 4183 if (!anon_mapping && is_compatible_protection(alloc_prot, PAGE_WRITECOPY)) 4184 { 4185 ret = VirtualProtect(base, sec_flags & SEC_IMAGE ? si.dwPageSize : 2*si.dwPageSize, PAGE_WRITECOPY, &old_prot); 4186 todo_wine_if(readonly && view[j].prot != PAGE_WRITECOPY) 4187 ok(ret, "VirtualProtect error %ld, map %#lx, view %#lx\n", GetLastError(), page_prot[i], view[j].prot); 4188 if (ret) *(DWORD*)base = 0xdeadbeef; 4189 ret = VirtualQuery(base, &info, sizeof(info)); 4190 ok(ret, "%ld: VirtualQuery failed %ld\n", j, GetLastError()); 4191 todo_wine 4192 ok(info.Protect == PAGE_READWRITE, "VirtualProtect wrong prot, map %#lx, view %#lx got %#lx\n", 4193 page_prot[i], view[j].prot, info.Protect ); 4194 todo_wine_if (!(sec_flags & SEC_IMAGE)) 4195 ok(info.RegionSize == si.dwPageSize, "wrong region size %#Ix after write, map %#lx, view %#lx got %#lx\n", 4196 info.RegionSize, page_prot[i], view[j].prot, info.Protect ); 4197 4198 prev_prot = info.Protect; 4199 alloc_prot = info.AllocationProtect; 4200 4201 if (!(sec_flags & SEC_IMAGE)) 4202 { 4203 ret = VirtualQuery((char*)base + si.dwPageSize, &info, sizeof(info)); 4204 ok(ret, "%ld: VirtualQuery failed %ld\n", j, GetLastError()); 4205 todo_wine_if(readonly && view[j].prot != PAGE_WRITECOPY) 4206 ok(info.Protect == PAGE_WRITECOPY, "wrong prot, map %#lx, view %#lx got %#lx\n", 4207 page_prot[i], view[j].prot, info.Protect); 4208 } 4209 4210 for (k = 0; k < ARRAY_SIZE(page_prot); k++) 4211 { 4212 DWORD actual_prot = (sec_flags & SEC_IMAGE) ? map_prot_no_write(page_prot[k]) : page_prot[k]; 4213 SetLastError(0xdeadbeef); 4214 old_prot = 0xdeadbeef; 4215 ret = VirtualProtect(base, si.dwPageSize, page_prot[k], &old_prot); 4216 if (is_compatible_protection(alloc_prot, actual_prot)) 4217 { 4218 /* win2k and XP don't support EXEC on file mappings */ 4219 if (!ret && (page_prot[k] == PAGE_EXECUTE || page_prot[k] == PAGE_EXECUTE_WRITECOPY || view[j].prot == PAGE_EXECUTE_WRITECOPY)) 4220 { 4221 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n"); 4222 continue; 4223 } 4224 4225 todo_wine_if(readonly && page_prot[k] == PAGE_WRITECOPY && view[j].prot != PAGE_WRITECOPY) 4226 ok(ret, "VirtualProtect error %ld, map %#lx, view %#lx, requested prot %#lx\n", GetLastError(), page_prot[i], view[j].prot, page_prot[k]); 4227 todo_wine_if(readonly && page_prot[k] == PAGE_WRITECOPY && view[j].prot != PAGE_WRITECOPY) 4228 ok(old_prot == prev_prot, "got %#lx, expected %#lx\n", old_prot, prev_prot); 4229 4230 ret = VirtualQuery(base, &info, sizeof(info)); 4231 ok(ret, "%ld: VirtualQuery failed %ld\n", j, GetLastError()); 4232 todo_wine_if( map_prot_written( page_prot[k] ) != actual_prot ) 4233 ok(info.Protect == map_prot_written( page_prot[k] ), 4234 "VirtualProtect wrong prot, map %#lx, view %#lx, requested prot %#lx got %#lx\n", 4235 page_prot[i], view[j].prot, page_prot[k], info.Protect ); 4236 prev_prot = info.Protect; 4237 } 4238 else 4239 { 4240 ok(!ret, "VirtualProtect should fail, map %#lx, view %#lx, requested prot %#lx\n", page_prot[i], view[j].prot, page_prot[k]); 4241 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError()); 4242 } 4243 } 4244 } 4245 UnmapViewOfFile(base); 4246 } 4247 4248 CloseHandle(hmap); 4249 } 4250} 4251 4252static void test_mappings(void) 4253{ 4254 char temp_path[MAX_PATH]; 4255 char file_name[MAX_PATH]; 4256 DWORD data, num_bytes; 4257 HANDLE hfile; 4258 4259 GetTempPathA(MAX_PATH, temp_path); 4260 GetTempFileNameA(temp_path, "map", 0, file_name); 4261 4262 hfile = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0); 4263 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %ld\n", file_name, GetLastError()); 4264 SetFilePointer(hfile, 2*si.dwPageSize, NULL, FILE_BEGIN); 4265 SetEndOfFile(hfile); 4266 4267 test_mapping( hfile, SEC_COMMIT, FALSE ); 4268 4269 /* test that file was not modified */ 4270 SetFilePointer(hfile, 0, NULL, FILE_BEGIN); 4271 ok(ReadFile(hfile, &data, sizeof(data), &num_bytes, NULL), "ReadFile failed\n"); 4272 ok(num_bytes == sizeof(data), "num_bytes = %ld\n", num_bytes); 4273 todo_wine 4274 ok(!data, "data = %lx\n", data); 4275 4276 CloseHandle( hfile ); 4277 4278 hfile = CreateFileA(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0); 4279 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %ld\n", file_name, GetLastError()); 4280 4281 test_mapping( hfile, SEC_COMMIT, TRUE ); 4282 4283 CloseHandle( hfile ); 4284 DeleteFileA( file_name ); 4285 4286 /* SEC_IMAGE mapping */ 4287 GetSystemDirectoryA( file_name, MAX_PATH ); 4288 strcat( file_name, "\\kernel32.dll" ); 4289 4290 hfile = CreateFileA( file_name, GENERIC_READ|GENERIC_EXECUTE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); 4291 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %ld\n", file_name, GetLastError()); 4292 4293 test_mapping( hfile, SEC_IMAGE, FALSE ); 4294 4295 CloseHandle( hfile ); 4296 4297 /* now anonymous mappings */ 4298 test_mapping( INVALID_HANDLE_VALUE, SEC_COMMIT, FALSE ); 4299} 4300 4301static void test_shared_memory(BOOL is_child) 4302{ 4303 HANDLE mapping; 4304 LONG *p; 4305 4306 SetLastError(0xdeadbef); 4307 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_virtual.c"); 4308 ok(mapping != 0, "CreateFileMapping error %ld\n", GetLastError()); 4309 if (is_child) 4310 ok(GetLastError() == ERROR_ALREADY_EXISTS, "expected ERROR_ALREADY_EXISTS, got %ld\n", GetLastError()); 4311 4312 SetLastError(0xdeadbef); 4313 p = MapViewOfFile(mapping, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 4096); 4314 ok(p != NULL, "MapViewOfFile error %ld\n", GetLastError()); 4315 4316 if (is_child) 4317 { 4318 ok(*p == 0x1a2b3c4d, "expected 0x1a2b3c4d in child, got %#lx\n", *p); 4319 } 4320 else 4321 { 4322 char **argv; 4323 char cmdline[MAX_PATH]; 4324 PROCESS_INFORMATION pi; 4325 STARTUPINFOA si = { sizeof(si) }; 4326 DWORD ret; 4327 4328 *p = 0x1a2b3c4d; 4329 4330 winetest_get_mainargs(&argv); 4331 sprintf(cmdline, "\"%s\" virtual sharedmem", argv[0]); 4332 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 4333 ok(ret, "CreateProcess(%s) error %ld\n", cmdline, GetLastError()); 4334 wait_child_process(pi.hProcess); 4335 CloseHandle(pi.hThread); 4336 CloseHandle(pi.hProcess); 4337 } 4338 4339 UnmapViewOfFile(p); 4340 CloseHandle(mapping); 4341} 4342 4343static void test_shared_memory_ro(BOOL is_child, DWORD child_access) 4344{ 4345 HANDLE mapping; 4346 LONG *p; 4347 4348 SetLastError(0xdeadbef); 4349 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_virtual.c_ro"); 4350 ok(mapping != 0, "CreateFileMapping error %ld\n", GetLastError()); 4351 if (is_child) 4352 ok(GetLastError() == ERROR_ALREADY_EXISTS, "expected ERROR_ALREADY_EXISTS, got %ld\n", GetLastError()); 4353 4354 SetLastError(0xdeadbef); 4355 p = MapViewOfFile(mapping, is_child ? child_access : FILE_MAP_READ, 0, 0, 4096); 4356 ok(p != NULL, "MapViewOfFile error %ld\n", GetLastError()); 4357 4358 if (is_child) 4359 { 4360 *p = 0xdeadbeef; 4361 } 4362 else 4363 { 4364 char **argv; 4365 char cmdline[MAX_PATH]; 4366 PROCESS_INFORMATION pi; 4367 STARTUPINFOA si = { sizeof(si) }; 4368 DWORD ret; 4369 4370 winetest_get_mainargs(&argv); 4371 sprintf(cmdline, "\"%s\" virtual sharedmemro %lx", argv[0], child_access); 4372 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 4373 ok(ret, "CreateProcess(%s) error %ld\n", cmdline, GetLastError()); 4374 wait_child_process(pi.hProcess); 4375 CloseHandle(pi.hThread); 4376 CloseHandle(pi.hProcess); 4377 4378 if(child_access & FILE_MAP_WRITE) 4379 ok(*p == 0xdeadbeef, "*p = %lx, expected 0xdeadbeef\n", *p); 4380 else 4381 ok(!*p, "*p = %lx, expected 0\n", *p); 4382 } 4383 4384 UnmapViewOfFile(p); 4385 CloseHandle(mapping); 4386} 4387 4388static void test_PrefetchVirtualMemory(void) 4389{ 4390#ifdef __REACTOS__ 4391 skip("Cannot build test_PrefetchVirtualMemory() until kernelbase is synced.\n"); 4392#else 4393 WIN32_MEMORY_RANGE_ENTRY entries[2]; 4394 char stackmem[] = "Test stack mem"; 4395 static char testmem[] = "Test memory range data"; 4396 unsigned int page_size = si.dwPageSize; 4397 BOOL ret; 4398 4399 if (!pPrefetchVirtualMemory) 4400 { 4401 skip("no PrefetchVirtualMemory in kernelbase\n"); 4402 return; 4403 } 4404 4405 ok( !pPrefetchVirtualMemory( GetCurrentProcess(), 0, NULL, 0 ), 4406 "PrefetchVirtualMemory unexpected success on 0 entries\n" ); 4407 4408 entries[0].VirtualAddress = ULongToPtr(PtrToUlong(testmem) & -(ULONG_PTR)page_size); 4409 entries[0].NumberOfBytes = page_size; 4410 ret = pPrefetchVirtualMemory( GetCurrentProcess(), 1, entries, 0 ); 4411 ok( ret || broken( is_wow64 && GetLastError() == ERROR_INVALID_PARAMETER ) /* win10 1507 */, 4412 "PrefetchVirtualMemory unexpected status on 1 page-aligned entry: %ld\n", GetLastError() ); 4413 4414 entries[0].VirtualAddress = testmem; 4415 entries[0].NumberOfBytes = sizeof(testmem); 4416 ret = pPrefetchVirtualMemory( GetCurrentProcess(), 1, entries, 0 ); 4417 ok( ret || broken( is_wow64 && GetLastError() == ERROR_INVALID_PARAMETER ) /* win10 1507 */, 4418 "PrefetchVirtualMemory unexpected status on 1 entry: %ld\n", GetLastError() ); 4419 4420 entries[0].VirtualAddress = NULL; 4421 entries[0].NumberOfBytes = page_size; 4422 ret = pPrefetchVirtualMemory( GetCurrentProcess(), 1, entries, 0 ); 4423 ok( ret ||broken( is_wow64 && GetLastError() == ERROR_INVALID_PARAMETER ) /* win10 1507 */, 4424 "PrefetchVirtualMemory unexpected status on 1 unmapped entry: %ld\n", GetLastError() ); 4425 4426 entries[0].VirtualAddress = ULongToPtr(PtrToUlong(testmem) & -(ULONG_PTR)page_size); 4427 entries[0].NumberOfBytes = page_size; 4428 entries[1].VirtualAddress = ULongToPtr(PtrToUlong(stackmem) & -(ULONG_PTR)page_size); 4429 entries[1].NumberOfBytes = page_size; 4430 ret = pPrefetchVirtualMemory( GetCurrentProcess(), 2, entries, 0 ); 4431 ok( ret ||broken( is_wow64 && GetLastError() == ERROR_INVALID_PARAMETER ) /* win10 1507 */, 4432 "PrefetchVirtualMemory unexpected status on 2 page-aligned entries: %ld\n", GetLastError() ); 4433#endif 4434} 4435 4436static void test_ReadProcessMemory(void) 4437{ 4438 BYTE *buf; 4439 DWORD old_prot; 4440 SIZE_T copied; 4441 HANDLE hproc; 4442 void *ptr; 4443 BOOL ret; 4444 4445 buf = malloc(2 * si.dwPageSize); 4446 ok(buf != NULL, "OOM\n"); 4447 ret = DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), 4448 &hproc, 0, FALSE, DUPLICATE_SAME_ACCESS); 4449 ok(ret, "DuplicateHandle failed %lu\n", GetLastError()); 4450 ptr = VirtualAlloc(NULL, 2 * si.dwPageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 4451 ok(ptr != NULL, "Virtual failed %lu\n", GetLastError()); 4452 ret = VirtualProtect(((BYTE *)ptr) + si.dwPageSize, si.dwPageSize, PAGE_NOACCESS, &old_prot); 4453 ok(ret, "VirtualProtect failed %lu\n", GetLastError()); 4454 4455 copied = 1; 4456 ret = ReadProcessMemory(GetCurrentProcess(), ptr, buf, 2 * si.dwPageSize, &copied); 4457 ok(!ret, "ReadProcessMemory succeeded\n"); 4458 ok(!copied, "copied = %Id\n", copied); 4459 ok(GetLastError() == ERROR_PARTIAL_COPY, "GetLastError() = %lu\n", GetLastError()); 4460 4461 ret = ReadProcessMemory(GetCurrentProcess(), ptr, buf, si.dwPageSize, &copied); 4462 ok(ret, "ReadProcessMemory failed %lu\n", GetLastError()); 4463 ok(copied == si.dwPageSize, "copied = %Id\n", copied); 4464 4465 ret = ReadProcessMemory(hproc, ptr, buf, 2 * si.dwPageSize, &copied); 4466 todo_wine ok(!ret, "ReadProcessMemory succeeded\n"); 4467 4468 ret = ReadProcessMemory(hproc, ptr, buf, si.dwPageSize, &copied); 4469 ok(ret, "ReadProcessMemory failed %lu\n", GetLastError()); 4470 ok(copied == si.dwPageSize, "copied = %Id\n", copied); 4471 4472 ret = VirtualFree(ptr, 0, MEM_RELEASE); 4473 ok(ret, "VirtualFree failed %lu\n", GetLastError()); 4474 CloseHandle(hproc); 4475 free(buf); 4476} 4477 4478START_TEST(virtual) 4479{ 4480 int argc; 4481 char **argv; 4482 argc = winetest_get_mainargs( &argv ); 4483 4484#if defined(__REACTOS__) && defined(SKIPBADHEAP_K32_WINETEST) 4485 if (is_reactos()) { 4486 ok(FALSE, "FIXME: These tests are too rough on ReactOS heap manager on x64. It will eventually finish but it takes over an hour to complete the test suite with it which isn't acceptable.\n"); 4487 return; 4488 } 4489#endif 4490 if (argc >= 3) 4491 { 4492 if (!strcmp(argv[2], "sleep")) 4493 { 4494 Sleep(5000); /* spawned process runs for at most 5 seconds */ 4495 return; 4496 } 4497 if (!strcmp(argv[2], "sharedmem")) 4498 { 4499 test_shared_memory(TRUE); 4500 return; 4501 } 4502 if (!strcmp(argv[2], "sharedmemro")) 4503 { 4504 test_shared_memory_ro(TRUE, strtol(argv[3], NULL, 16)); 4505 return; 4506 } 4507 while (1) 4508 { 4509 void *mem; 4510 BOOL ret; 4511 mem = VirtualAlloc(NULL, 1<<20, MEM_COMMIT|MEM_RESERVE, 4512 PAGE_EXECUTE_READWRITE); 4513 ok(mem != NULL, "VirtualAlloc failed %lu\n", GetLastError()); 4514 if (mem == NULL) break; 4515 ret = VirtualFree(mem, 0, MEM_RELEASE); 4516 ok(ret, "VirtualFree failed %lu\n", GetLastError()); 4517 if (!ret) break; 4518 } 4519 return; 4520 } 4521 4522 hkernel32 = GetModuleHandleA("kernel32.dll"); 4523 hkernelbase = GetModuleHandleA("kernelbase.dll"); 4524 hntdll = GetModuleHandleA("ntdll.dll"); 4525 4526 pGetWriteWatch = (void *) GetProcAddress(hkernel32, "GetWriteWatch"); 4527 pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch"); 4528 pGetProcessDEPPolicy = (void *)GetProcAddress( hkernel32, "GetProcessDEPPolicy" ); 4529 pIsWow64Process = (void *)GetProcAddress( hkernel32, "IsWow64Process" ); 4530 pNtAreMappedFilesTheSame = (void *)GetProcAddress( hntdll, "NtAreMappedFilesTheSame" ); 4531 pNtCreateSection = (void *)GetProcAddress( hntdll, "NtCreateSection" ); 4532 pNtMapViewOfSection = (void *)GetProcAddress( hntdll, "NtMapViewOfSection" ); 4533 pNtUnmapViewOfSection = (void *)GetProcAddress( hntdll, "NtUnmapViewOfSection" ); 4534 pNtQuerySection = (void *)GetProcAddress( hntdll, "NtQuerySection" ); 4535 pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlAddVectoredExceptionHandler" ); 4536 pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlRemoveVectoredExceptionHandler" ); 4537 pNtProtectVirtualMemory = (void *)GetProcAddress( hntdll, "NtProtectVirtualMemory" ); 4538 pNtReadVirtualMemory = (void *)GetProcAddress( hntdll, "NtReadVirtualMemory" ); 4539 pNtWriteVirtualMemory = (void *)GetProcAddress( hntdll, "NtWriteVirtualMemory" ); 4540#ifndef __REACTOS__ // TODO: Enable when kernelbase is fixed. ROSTESTS-414 4541 pPrefetchVirtualMemory = (void *)GetProcAddress( hkernelbase, "PrefetchVirtualMemory" ); 4542#endif 4543 4544 GetSystemInfo(&si); 4545 trace("system page size %#lx\n", si.dwPageSize); 4546 4547 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE; 4548 4549 test_shared_memory(FALSE); 4550 test_shared_memory_ro(FALSE, FILE_MAP_READ|FILE_MAP_WRITE); 4551 test_shared_memory_ro(FALSE, FILE_MAP_COPY); 4552 test_shared_memory_ro(FALSE, FILE_MAP_COPY|FILE_MAP_WRITE); 4553 test_mappings(); 4554 test_CreateFileMapping_protection(); 4555 test_VirtualAlloc_protection(); 4556 test_VirtualProtect(); 4557 test_VirtualAllocEx(); 4558 test_VirtualAlloc(); 4559 test_MapViewOfFile(); 4560 test_NtAreMappedFilesTheSame(); 4561 test_CreateFileMapping(); 4562 test_IsBadReadPtr(); 4563 test_IsBadWritePtr(); 4564 test_IsBadCodePtr(); 4565 test_write_watch(); 4566 test_PrefetchVirtualMemory(); 4567 test_ReadProcessMemory(); 4568#if defined(__i386__) || defined(__x86_64__) 4569 test_stack_commit(); 4570#endif 4571#ifdef __i386__ 4572 test_guard_page(); 4573 /* The following tests should be executed as a last step, and in exactly this 4574 * order, since ATL thunk emulation cannot be enabled anymore on Windows. */ 4575 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE ); 4576 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE ); 4577 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION ); 4578#endif 4579}