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