ntdll: Improve check_atl_thunk to prevent passing exceptions to the usermode application.
[wine/wine-gecko.git] / dlls / kernel32 / tests / virtual.c
blob73b753ea321d703bd67c53bd60f5bac41516488c
1 /*
2 * Unit test suite for Virtual* family of APIs.
4 * Copyright 2004 Dmitry Timoshkov
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.
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.
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
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnt.h"
29 #include "winternl.h"
30 #include "winerror.h"
31 #include "winuser.h"
32 #include "excpt.h"
33 #include "wine/test.h"
35 #define NUM_THREADS 4
36 #define MAPPING_SIZE 0x100000
38 static HINSTANCE hkernel32, hntdll;
39 static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
40 static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
41 static UINT (WINAPI *pGetWriteWatch)(DWORD,LPVOID,SIZE_T,LPVOID*,ULONG_PTR*,ULONG*);
42 static UINT (WINAPI *pResetWriteWatch)(LPVOID,SIZE_T);
43 static NTSTATUS (WINAPI *pNtAreMappedFilesTheSame)(PVOID,PVOID);
44 static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG);
45 static DWORD (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID);
46 static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
47 static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG, PVECTORED_EXCEPTION_HANDLER);
48 static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
50 /* ############################### */
52 static HANDLE create_target_process(const char *arg)
54 char **argv;
55 char cmdline[MAX_PATH];
56 PROCESS_INFORMATION pi;
57 BOOL ret;
58 STARTUPINFOA si = { 0 };
59 si.cb = sizeof(si);
61 winetest_get_mainargs( &argv );
62 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
63 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
64 ok(ret, "error: %u\n", GetLastError());
65 ret = CloseHandle(pi.hThread);
66 ok(ret, "error %u\n", GetLastError());
67 return pi.hProcess;
70 static void test_VirtualAllocEx(void)
72 const unsigned int alloc_size = 1<<15;
73 char *src, *dst;
74 SIZE_T bytes_written = 0, bytes_read = 0, i;
75 void *addr1, *addr2;
76 BOOL b;
77 DWORD old_prot;
78 MEMORY_BASIC_INFORMATION info;
79 HANDLE hProcess;
81 /* not exported in all windows-versions */
82 if ((!pVirtualAllocEx) || (!pVirtualFreeEx)) {
83 win_skip("Virtual{Alloc,Free}Ex not available\n");
84 return;
87 hProcess = create_target_process("sleep");
88 ok(hProcess != NULL, "Can't start process\n");
90 SetLastError(0xdeadbeef);
91 addr1 = pVirtualAllocEx(hProcess, NULL, alloc_size, MEM_COMMIT,
92 PAGE_EXECUTE_READWRITE);
93 if (!addr1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
94 { /* Win9x */
95 win_skip("VirtualAllocEx not implemented\n");
96 TerminateProcess(hProcess, 0);
97 CloseHandle(hProcess);
98 return;
101 src = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE );
102 dst = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE );
103 for (i = 0; i < alloc_size; i++)
104 src[i] = i & 0xff;
106 ok(addr1 != NULL, "VirtualAllocEx error %u\n", GetLastError());
107 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
108 ok(b && (bytes_written == alloc_size), "%lu bytes written\n",
109 bytes_written);
110 b = ReadProcessMemory(hProcess, addr1, dst, alloc_size, &bytes_read);
111 ok(b && (bytes_read == alloc_size), "%lu bytes read\n", bytes_read);
112 ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n");
114 /* test invalid source buffers */
116 b = VirtualProtect( src + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot );
117 ok( b, "VirtualProtect failed error %u\n", GetLastError() );
118 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
119 ok( !b, "WriteProcessMemory succeeded\n" );
120 ok( GetLastError() == ERROR_NOACCESS ||
121 GetLastError() == ERROR_PARTIAL_COPY, /* vista */
122 "wrong error %u\n", GetLastError() );
123 ok( bytes_written == 0, "%lu bytes written\n", bytes_written );
124 b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
125 ok( !b, "ReadProcessMemory succeeded\n" );
126 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
127 ok( bytes_read == 0, "%lu bytes written\n", bytes_read );
129 b = VirtualProtect( src, 0x2000, PAGE_NOACCESS, &old_prot );
130 ok( b, "VirtualProtect failed error %u\n", GetLastError() );
131 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
132 ok( !b, "WriteProcessMemory succeeded\n" );
133 ok( GetLastError() == ERROR_NOACCESS ||
134 GetLastError() == ERROR_PARTIAL_COPY, /* vista */
135 "wrong error %u\n", GetLastError() );
136 ok( bytes_written == 0, "%lu bytes written\n", bytes_written );
137 b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
138 ok( !b, "ReadProcessMemory succeeded\n" );
139 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
140 ok( bytes_read == 0, "%lu bytes written\n", bytes_read );
142 b = pVirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE);
143 ok(b != 0, "VirtualFreeEx, error %u\n", GetLastError());
145 VirtualFree( src, 0, MEM_FREE );
146 VirtualFree( dst, 0, MEM_FREE );
149 * The following tests parallel those in test_VirtualAlloc()
152 SetLastError(0xdeadbeef);
153 addr1 = pVirtualAllocEx(hProcess, 0, 0, MEM_RESERVE, PAGE_NOACCESS);
154 ok(addr1 == NULL, "VirtualAllocEx should fail on zero-sized allocation\n");
155 ok(GetLastError() == ERROR_INVALID_PARAMETER /* NT */ ||
156 GetLastError() == ERROR_NOT_ENOUGH_MEMORY, /* Win9x */
157 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
159 addr1 = pVirtualAllocEx(hProcess, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
160 ok(addr1 != NULL, "VirtualAllocEx failed\n");
162 /* test a not committed memory */
163 memset(&info, 'q', sizeof(info));
164 ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info), "VirtualQueryEx failed\n");
165 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
166 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
167 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
168 ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
169 ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
170 /* NT reports Protect == 0 for a not committed memory block */
171 ok(info.Protect == 0 /* NT */ ||
172 info.Protect == PAGE_NOACCESS, /* Win9x */
173 "%x != PAGE_NOACCESS\n", info.Protect);
174 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
176 SetLastError(0xdeadbeef);
177 ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
178 "VirtualProtectEx should fail on a not committed memory\n");
179 ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
180 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
181 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
183 addr2 = pVirtualAllocEx(hProcess, addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS);
184 ok(addr1 == addr2, "VirtualAllocEx failed\n");
186 /* test a committed memory */
187 ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info),
188 "VirtualQueryEx failed\n");
189 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
190 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
191 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
192 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
193 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
194 /* this time NT reports PAGE_NOACCESS as well */
195 ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
196 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
198 /* this should fail, since not the whole range is committed yet */
199 SetLastError(0xdeadbeef);
200 ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
201 "VirtualProtectEx should fail on a not committed memory\n");
202 ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
203 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
204 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
206 old_prot = 0;
207 ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtectEx failed\n");
208 ok(old_prot == PAGE_NOACCESS, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
210 old_prot = 0;
211 ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtectEx failed\n");
212 ok(old_prot == PAGE_READONLY, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
214 ok(!pVirtualFreeEx(hProcess, addr1, 0x10000, 0),
215 "VirtualFreeEx should fail with type 0\n");
216 ok(GetLastError() == ERROR_INVALID_PARAMETER,
217 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
219 ok(pVirtualFreeEx(hProcess, addr1, 0x10000, MEM_DECOMMIT), "VirtualFreeEx failed\n");
221 /* if the type is MEM_RELEASE, size must be 0 */
222 ok(!pVirtualFreeEx(hProcess, addr1, 1, MEM_RELEASE),
223 "VirtualFreeEx should fail\n");
224 ok(GetLastError() == ERROR_INVALID_PARAMETER,
225 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
227 ok(pVirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE), "VirtualFreeEx failed\n");
229 TerminateProcess(hProcess, 0);
230 CloseHandle(hProcess);
233 static void test_VirtualAlloc(void)
235 void *addr1, *addr2;
236 DWORD old_prot;
237 MEMORY_BASIC_INFORMATION info;
239 SetLastError(0xdeadbeef);
240 addr1 = VirtualAlloc(0, 0, MEM_RESERVE, PAGE_NOACCESS);
241 ok(addr1 == NULL, "VirtualAlloc should fail on zero-sized allocation\n");
242 ok(GetLastError() == ERROR_INVALID_PARAMETER /* NT */ ||
243 GetLastError() == ERROR_NOT_ENOUGH_MEMORY, /* Win9x */
244 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
246 addr1 = VirtualAlloc(0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
247 ok(addr1 != NULL, "VirtualAlloc failed\n");
249 /* test a not committed memory */
250 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
251 "VirtualQuery failed\n");
252 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
253 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
254 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
255 ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
256 ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
257 /* NT reports Protect == 0 for a not committed memory block */
258 ok(info.Protect == 0 /* NT */ ||
259 info.Protect == PAGE_NOACCESS, /* Win9x */
260 "%x != PAGE_NOACCESS\n", info.Protect);
261 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
263 SetLastError(0xdeadbeef);
264 ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
265 "VirtualProtect should fail on a not committed memory\n");
266 ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
267 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
268 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
270 addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS);
271 ok(addr1 == addr2, "VirtualAlloc failed\n");
273 /* test a committed memory */
274 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
275 "VirtualQuery failed\n");
276 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
277 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
278 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
279 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
280 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
281 /* this time NT reports PAGE_NOACCESS as well */
282 ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
283 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
285 /* this should fail, since not the whole range is committed yet */
286 SetLastError(0xdeadbeef);
287 ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
288 "VirtualProtect should fail on a not committed memory\n");
289 ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
290 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
291 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
293 ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtect failed\n");
294 ok(old_prot == PAGE_NOACCESS,
295 "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
297 ok(VirtualProtect(addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtect failed\n");
298 ok(old_prot == PAGE_READONLY,
299 "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
301 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
302 "VirtualQuery failed\n");
303 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
304 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
305 ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
306 memset( addr1, 0x55, 20 );
307 ok( *(DWORD *)addr1 == 0x55555555, "wrong data %x\n", *(DWORD *)addr1 );
309 addr2 = VirtualAlloc( addr1, 0x1000, MEM_RESET, PAGE_NOACCESS );
310 ok( addr2 == addr1 || broken( !addr2 && GetLastError() == ERROR_INVALID_PARAMETER), /* win9x */
311 "VirtualAlloc failed err %u\n", GetLastError() );
312 ok( *(DWORD *)addr1 == 0x55555555 || *(DWORD *)addr1 == 0, "wrong data %x\n", *(DWORD *)addr1 );
313 if (addr2)
315 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
316 "VirtualQuery failed\n");
317 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
318 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
319 ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
321 addr2 = VirtualAlloc( (char *)addr1 + 0x1000, 0x1000, MEM_RESET, PAGE_NOACCESS );
322 ok( (char *)addr2 == (char *)addr1 + 0x1000, "VirtualAlloc failed\n" );
324 ok(VirtualQuery(addr2, &info, sizeof(info)) == sizeof(info),
325 "VirtualQuery failed\n");
326 ok(info.RegionSize == 0xf000, "%lx != 0xf000\n", info.RegionSize);
327 ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
328 ok(info.Protect == 0, "%x != 0\n", info.Protect);
330 addr2 = VirtualAlloc( (char *)addr1 + 0xf000, 0x2000, MEM_RESET, PAGE_NOACCESS );
331 ok( !addr2, "VirtualAlloc failed\n" );
332 ok( GetLastError() == ERROR_INVALID_ADDRESS, "wrong error %u\n", GetLastError() );
335 /* invalid protection values */
336 SetLastError(0xdeadbeef);
337 addr2 = VirtualAlloc(NULL, 0x1000, MEM_RESERVE, 0);
338 ok(!addr2, "VirtualAlloc succeeded\n");
339 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
341 SetLastError(0xdeadbeef);
342 addr2 = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, 0);
343 ok(!addr2, "VirtualAlloc succeeded\n");
344 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
346 SetLastError(0xdeadbeef);
347 addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_READONLY | PAGE_EXECUTE);
348 ok(!addr2, "VirtualAlloc succeeded\n");
349 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
351 SetLastError(0xdeadbeef);
352 ok(!VirtualProtect(addr1, 0x1000, PAGE_READWRITE | PAGE_EXECUTE_WRITECOPY, &old_prot),
353 "VirtualProtect succeeded\n");
354 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
356 SetLastError(0xdeadbeef);
357 ok(!VirtualProtect(addr1, 0x1000, 0, &old_prot), "VirtualProtect succeeded\n");
358 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
360 SetLastError(0xdeadbeef);
361 ok(!VirtualFree(addr1, 0x10000, 0), "VirtualFree should fail with type 0\n");
362 ok(GetLastError() == ERROR_INVALID_PARAMETER,
363 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
365 ok(VirtualFree(addr1, 0x10000, MEM_DECOMMIT), "VirtualFree failed\n");
367 /* if the type is MEM_RELEASE, size must be 0 */
368 ok(!VirtualFree(addr1, 1, MEM_RELEASE), "VirtualFree should fail\n");
369 ok(GetLastError() == ERROR_INVALID_PARAMETER,
370 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
372 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
375 static void test_MapViewOfFile(void)
377 static const char testfile[] = "testfile.xxx";
378 const char *name;
379 HANDLE file, mapping, map2;
380 void *ptr, *ptr2, *addr;
381 MEMORY_BASIC_INFORMATION info;
382 BOOL ret;
384 SetLastError(0xdeadbeef);
385 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
386 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
387 SetFilePointer( file, 4096, NULL, FILE_BEGIN );
388 SetEndOfFile( file );
390 /* read/write mapping */
392 SetLastError(0xdeadbeef);
393 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
394 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
396 SetLastError(0xdeadbeef);
397 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
398 ok( ptr != NULL, "MapViewOfFile FILE_MAPE_READ error %u\n", GetLastError() );
399 UnmapViewOfFile( ptr );
401 /* this fails on win9x but succeeds on NT */
402 SetLastError(0xdeadbeef);
403 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
404 if (ptr) UnmapViewOfFile( ptr );
405 else ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
407 SetLastError(0xdeadbeef);
408 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
409 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
410 UnmapViewOfFile( ptr );
412 SetLastError(0xdeadbeef);
413 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
414 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
415 UnmapViewOfFile( ptr );
417 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
418 FILE_MAP_READ|FILE_MAP_WRITE, FALSE, 0 );
419 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
420 ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
421 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
422 UnmapViewOfFile( ptr );
423 CloseHandle( map2 );
425 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
426 FILE_MAP_READ, FALSE, 0 );
427 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
428 SetLastError(0xdeadbeef);
429 ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
430 if (!ptr)
432 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
433 CloseHandle( map2 );
434 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2, 0, FALSE, 0 );
435 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
436 SetLastError(0xdeadbeef);
437 ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
438 ok( !ptr, "MapViewOfFile succeeded\n" );
439 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
440 CloseHandle( map2 );
441 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
442 FILE_MAP_READ, FALSE, 0 );
443 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
444 ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
445 ok( ptr != NULL, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
447 else win_skip( "no access checks on win9x\n" );
449 UnmapViewOfFile( ptr );
450 CloseHandle( map2 );
451 CloseHandle( mapping );
453 /* read-only mapping */
455 SetLastError(0xdeadbeef);
456 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
457 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
459 SetLastError(0xdeadbeef);
460 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
461 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
462 UnmapViewOfFile( ptr );
464 /* this fails on win9x but succeeds on NT */
465 SetLastError(0xdeadbeef);
466 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
467 if (ptr) UnmapViewOfFile( ptr );
468 else ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
470 SetLastError(0xdeadbeef);
471 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
472 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
473 UnmapViewOfFile( ptr );
475 SetLastError(0xdeadbeef);
476 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
477 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
478 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
479 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
480 CloseHandle( mapping );
482 /* copy-on-write mapping */
484 SetLastError(0xdeadbeef);
485 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
486 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
488 SetLastError(0xdeadbeef);
489 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
490 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
491 UnmapViewOfFile( ptr );
493 SetLastError(0xdeadbeef);
494 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
495 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
496 UnmapViewOfFile( ptr );
498 SetLastError(0xdeadbeef);
499 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
500 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
501 UnmapViewOfFile( ptr );
503 SetLastError(0xdeadbeef);
504 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
505 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
506 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
507 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
508 CloseHandle( mapping );
510 /* no access mapping */
512 SetLastError(0xdeadbeef);
513 mapping = CreateFileMappingA( file, NULL, PAGE_NOACCESS, 0, 4096, NULL );
514 /* fails on NT but succeeds on win9x */
515 if (!mapping) ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
516 else
518 SetLastError(0xdeadbeef);
519 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
520 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
521 UnmapViewOfFile( ptr );
523 SetLastError(0xdeadbeef);
524 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
525 ok( !ptr, "MapViewOfFile FILE_MAP_COPY succeeded\n" );
526 ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
528 SetLastError(0xdeadbeef);
529 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
530 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
531 UnmapViewOfFile( ptr );
533 SetLastError(0xdeadbeef);
534 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
535 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
536 ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
538 CloseHandle( mapping );
541 CloseHandle( file );
543 /* now try read-only file */
545 SetLastError(0xdeadbeef);
546 file = CreateFileA( testfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
547 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
549 SetLastError(0xdeadbeef);
550 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
551 ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
552 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
553 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
555 SetLastError(0xdeadbeef);
556 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
557 ok( mapping != 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
558 CloseHandle( mapping );
560 SetLastError(0xdeadbeef);
561 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
562 ok( mapping != 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
563 CloseHandle( mapping );
564 CloseHandle( file );
566 /* now try no access file */
568 SetLastError(0xdeadbeef);
569 file = CreateFileA( testfile, 0, 0, NULL, OPEN_EXISTING, 0, 0 );
570 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
572 SetLastError(0xdeadbeef);
573 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
574 ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
575 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
576 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
578 SetLastError(0xdeadbeef);
579 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
580 ok( !mapping, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
581 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
582 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
584 SetLastError(0xdeadbeef);
585 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
586 ok( !mapping, "CreateFileMapping PAGE_READONLY succeeded\n" );
587 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
588 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
590 CloseHandle( file );
591 DeleteFileA( testfile );
593 SetLastError(0xdeadbeef);
594 name = "Local\\Foo";
595 file = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, name );
596 /* nt4 doesn't have Local\\ */
597 if (!file && GetLastError() == ERROR_PATH_NOT_FOUND)
599 name = "Foo";
600 file = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, name );
602 ok( file != 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
604 SetLastError(0xdeadbeef);
605 mapping = OpenFileMappingA( FILE_MAP_READ, FALSE, name );
606 ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
607 SetLastError(0xdeadbeef);
608 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
609 if (!ptr)
611 SIZE_T size;
612 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
613 SetLastError(0xdeadbeef);
614 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
615 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
616 SetLastError(0xdeadbeef);
617 size = VirtualQuery( ptr, &info, sizeof(info) );
618 ok( size == sizeof(info),
619 "VirtualQuery error %u\n", GetLastError() );
620 ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
621 ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
622 ok( info.AllocationProtect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.AllocationProtect );
623 ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
624 ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
625 ok( info.Protect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.Protect );
627 else win_skip( "no access checks on win9x\n" );
628 UnmapViewOfFile( ptr );
629 CloseHandle( mapping );
631 SetLastError(0xdeadbeef);
632 mapping = OpenFileMappingA( FILE_MAP_WRITE, FALSE, name );
633 ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
634 SetLastError(0xdeadbeef);
635 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
636 if (!ptr)
638 SIZE_T size;
639 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
640 SetLastError(0xdeadbeef);
641 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
642 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
643 SetLastError(0xdeadbeef);
644 size = VirtualQuery( ptr, &info, sizeof(info) );
645 ok( size == sizeof(info),
646 "VirtualQuery error %u\n", GetLastError() );
647 ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
648 ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
649 ok( info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect );
650 ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
651 ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
652 ok( info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect );
654 else win_skip( "no access checks on win9x\n" );
655 UnmapViewOfFile( ptr );
656 CloseHandle( mapping );
658 CloseHandle( file );
660 /* read/write mapping with SEC_RESERVE */
661 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_RESERVE, 0, MAPPING_SIZE, NULL);
662 ok(mapping != INVALID_HANDLE_VALUE, "CreateFileMappingA failed with error %d\n", GetLastError());
664 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
665 ok(ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
667 ptr2 = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
668 /* on NT ptr != ptr2 but on Win9x ptr == ptr2 */
669 ok(ptr2 != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
670 trace("mapping same section resulted in views %p and %p\n", ptr, ptr2);
672 ret = VirtualQuery(ptr, &info, sizeof(info));
673 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
674 ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
675 ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
676 ok(info.RegionSize == MAPPING_SIZE, "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE, info.RegionSize);
677 ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
678 if (info.Type == MEM_PRIVATE) /* win9x is different for uncommitted mappings */
680 ok(info.AllocationProtect == PAGE_NOACCESS,
681 "AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info.AllocationProtect);
682 ok(info.Protect == PAGE_NOACCESS,
683 "Protect should have been PAGE_NOACCESS instead of 0x%x\n", info.Protect);
685 else
687 ok(info.AllocationProtect == PAGE_READWRITE,
688 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
689 ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
690 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
693 if (ptr != ptr2)
695 ret = VirtualQuery(ptr2, &info, sizeof(info));
696 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
697 ok(info.BaseAddress == ptr2,
698 "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
699 ok(info.AllocationBase == ptr2,
700 "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
701 ok(info.AllocationProtect == PAGE_READWRITE,
702 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
703 ok(info.RegionSize == MAPPING_SIZE,
704 "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE, info.RegionSize);
705 ok(info.State == MEM_RESERVE,
706 "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
707 ok(info.Protect == 0,
708 "Protect should have been 0 instead of 0x%x\n", info.Protect);
709 ok(info.Type == MEM_MAPPED,
710 "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
713 ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY);
714 ok(ptr != NULL, "VirtualAlloc failed with error %d\n", GetLastError());
716 ret = VirtualQuery(ptr, &info, sizeof(info));
717 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
718 ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
719 ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
720 ok(info.RegionSize == 0x10000, "RegionSize should have been 0x10000 but was 0x%lx\n", info.RegionSize);
721 ok(info.State == MEM_COMMIT, "State should have been MEM_COMMIT instead of 0x%x\n", info.State);
722 ok(info.Protect == PAGE_READONLY, "Protect should have been PAGE_READONLY instead of 0x%x\n", info.Protect);
723 if (info.Type == MEM_PRIVATE) /* win9x is different for uncommitted mappings */
725 ok(info.AllocationProtect == PAGE_NOACCESS,
726 "AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info.AllocationProtect);
728 else
730 ok(info.AllocationProtect == PAGE_READWRITE,
731 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
732 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
735 /* shows that the VirtualAlloc above affects the mapping, not just the
736 * virtual memory in this process - it also affects all other processes
737 * with a view of the mapping, but that isn't tested here */
738 if (ptr != ptr2)
740 ret = VirtualQuery(ptr2, &info, sizeof(info));
741 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
742 ok(info.BaseAddress == ptr2,
743 "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
744 ok(info.AllocationBase == ptr2,
745 "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
746 ok(info.AllocationProtect == PAGE_READWRITE,
747 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
748 ok(info.RegionSize == 0x10000,
749 "RegionSize should have been 0x10000 but was 0x%lx\n", info.RegionSize);
750 ok(info.State == MEM_COMMIT,
751 "State should have been MEM_COMMIT instead of 0x%x\n", info.State);
752 ok(info.Protect == PAGE_READWRITE,
753 "Protect should have been PAGE_READWRITE instead of 0x%x\n", info.Protect);
754 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
757 addr = VirtualAlloc( ptr, MAPPING_SIZE, MEM_RESET, PAGE_READONLY );
758 ok( addr == ptr || broken(!addr && GetLastError() == ERROR_INVALID_PARAMETER), /* win9x */
759 "VirtualAlloc failed with error %u\n", GetLastError() );
761 ret = VirtualFree( ptr, 0x10000, MEM_DECOMMIT );
762 ok( !ret || broken(ret) /* win9x */, "VirtualFree succeeded\n" );
763 if (!ret)
764 ok( GetLastError() == ERROR_INVALID_PARAMETER, "VirtualFree failed with %u\n", GetLastError() );
766 ret = UnmapViewOfFile(ptr2);
767 ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
768 ret = UnmapViewOfFile(ptr);
769 ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
770 CloseHandle(mapping);
772 addr = VirtualAlloc(NULL, 0x10000, MEM_COMMIT, PAGE_READONLY );
773 ok( addr != NULL, "VirtualAlloc failed with error %u\n", GetLastError() );
775 SetLastError(0xdeadbeef);
776 ok( !UnmapViewOfFile(addr), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
777 ok( GetLastError() == ERROR_INVALID_ADDRESS,
778 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
779 SetLastError(0xdeadbeef);
780 ok( !UnmapViewOfFile((char *)addr + 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
781 ok( GetLastError() == ERROR_INVALID_ADDRESS,
782 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
783 SetLastError(0xdeadbeef);
784 ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
785 ok( GetLastError() == ERROR_INVALID_ADDRESS,
786 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
788 ok( VirtualFree(addr, 0, MEM_RELEASE), "VirtualFree failed\n" );
790 /* close named mapping handle without unmapping */
791 name = "Foo";
792 SetLastError(0xdeadbeef);
793 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
794 ok( mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
795 SetLastError(0xdeadbeef);
796 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
797 ok( ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError() );
798 SetLastError(0xdeadbeef);
799 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
800 ok( map2 != 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
801 SetLastError(0xdeadbeef);
802 ret = CloseHandle(map2);
803 ok(ret, "CloseHandle error %d\n", GetLastError());
804 SetLastError(0xdeadbeef);
805 ret = CloseHandle(mapping);
806 ok(ret, "CloseHandle error %d\n", GetLastError());
808 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
809 ok( !ret, "memory is not accessible\n" );
811 ret = VirtualQuery(ptr, &info, sizeof(info));
812 ok(ret, "VirtualQuery error %d\n", GetLastError());
813 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
814 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
815 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
816 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
817 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
818 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
819 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
821 SetLastError(0xdeadbeef);
822 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
823 todo_wine
824 ok( map2 == 0, "OpenFileMappingA succeeded\n" );
825 todo_wine
826 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %d\n", GetLastError() );
827 if (map2) CloseHandle(map2); /* FIXME: remove once Wine is fixed */
828 SetLastError(0xdeadbeef);
829 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
830 ok( mapping != 0, "CreateFileMappingA failed\n" );
831 todo_wine
832 ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %d\n", GetLastError() );
833 SetLastError(0xdeadbeef);
834 ret = CloseHandle(mapping);
835 ok(ret, "CloseHandle error %d\n", GetLastError());
837 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
838 ok( !ret, "memory is not accessible\n" );
840 ret = VirtualQuery(ptr, &info, sizeof(info));
841 ok(ret, "VirtualQuery error %d\n", GetLastError());
842 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
843 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
844 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
845 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
846 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
847 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
848 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
850 SetLastError(0xdeadbeef);
851 ret = UnmapViewOfFile(ptr);
852 ok( ret, "UnmapViewOfFile failed with error %d\n", GetLastError() );
854 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
855 ok( ret, "memory is accessible\n" );
857 ret = VirtualQuery(ptr, &info, sizeof(info));
858 ok(ret, "VirtualQuery error %d\n", GetLastError());
859 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
860 ok(info.Protect == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", info.Protect);
861 ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase);
862 ok(info.AllocationProtect == 0, "%#x != 0\n", info.AllocationProtect);
863 ok(info.State == MEM_FREE, "%#x != MEM_FREE\n", info.State);
864 ok(info.Type == 0, "%#x != 0\n", info.Type);
866 SetLastError(0xdeadbeef);
867 file = CreateFileA(testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
868 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
869 SetFilePointer(file, 4096, NULL, FILE_BEGIN);
870 SetEndOfFile(file);
872 SetLastError(0xdeadbeef);
873 mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
874 ok( mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
875 SetLastError(0xdeadbeef);
876 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
877 ok( ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError() );
878 SetLastError(0xdeadbeef);
879 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
880 ok( map2 != 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
881 SetLastError(0xdeadbeef);
882 ret = CloseHandle(map2);
883 ok(ret, "CloseHandle error %d\n", GetLastError());
884 SetLastError(0xdeadbeef);
885 ret = CloseHandle(mapping);
886 ok(ret, "CloseHandle error %d\n", GetLastError());
888 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
889 ok( !ret, "memory is not accessible\n" );
891 ret = VirtualQuery(ptr, &info, sizeof(info));
892 ok(ret, "VirtualQuery error %d\n", GetLastError());
893 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
894 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
895 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
896 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
897 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
898 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
899 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
901 SetLastError(0xdeadbeef);
902 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
903 todo_wine
904 ok( map2 == 0, "OpenFileMappingA succeeded\n" );
905 todo_wine
906 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %d\n", GetLastError() );
907 CloseHandle(map2);
908 SetLastError(0xdeadbeef);
909 mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
910 ok( mapping != 0, "CreateFileMappingA failed\n" );
911 todo_wine
912 ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %d\n", GetLastError() );
913 SetLastError(0xdeadbeef);
914 ret = CloseHandle(mapping);
915 ok(ret, "CloseHandle error %d\n", GetLastError());
917 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
918 ok( !ret, "memory is not accessible\n" );
920 ret = VirtualQuery(ptr, &info, sizeof(info));
921 ok(ret, "VirtualQuery error %d\n", GetLastError());
922 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
923 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
924 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
925 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
926 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
927 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
928 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
930 SetLastError(0xdeadbeef);
931 ret = UnmapViewOfFile(ptr);
932 ok( ret, "UnmapViewOfFile failed with error %d\n", GetLastError() );
934 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
935 ok( ret, "memory is accessible\n" );
937 ret = VirtualQuery(ptr, &info, sizeof(info));
938 ok(ret, "VirtualQuery error %d\n", GetLastError());
939 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
940 ok(info.Protect == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", info.Protect);
941 ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase);
942 ok(info.AllocationProtect == 0, "%#x != 0\n", info.AllocationProtect);
943 ok(info.State == MEM_FREE, "%#x != MEM_FREE\n", info.State);
944 ok(info.Type == 0, "%#x != 0\n", info.Type);
946 CloseHandle(file);
947 DeleteFileA(testfile);
950 static void test_NtMapViewOfSection(void)
952 HANDLE hProcess;
954 static const char testfile[] = "testfile.xxx";
955 static const char data[] = "test data for NtMapViewOfSection";
956 char buffer[sizeof(data)];
957 HANDLE file, mapping;
958 void *ptr;
959 BOOL ret;
960 DWORD status, written;
961 SIZE_T size, result;
962 LARGE_INTEGER offset;
964 if (!pNtMapViewOfSection || !pNtUnmapViewOfSection)
966 win_skip( "NtMapViewOfSection not available\n" );
967 return;
970 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
971 ok( file != INVALID_HANDLE_VALUE, "Failed to create test file\n" );
972 WriteFile( file, data, sizeof(data), &written, NULL );
973 SetFilePointer( file, 4096, NULL, FILE_BEGIN );
974 SetEndOfFile( file );
976 /* read/write mapping */
978 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
979 ok( mapping != 0, "CreateFileMapping failed\n" );
981 hProcess = create_target_process("sleep");
982 ok(hProcess != NULL, "Can't start process\n");
984 ptr = NULL;
985 size = 0;
986 offset.QuadPart = 0;
987 status = pNtMapViewOfSection( mapping, hProcess, &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
988 ok( !status, "NtMapViewOfSection failed status %x\n", status );
990 ret = ReadProcessMemory( hProcess, ptr, buffer, sizeof(buffer), &result );
991 ok( ret, "ReadProcessMemory failed\n" );
992 ok( result == sizeof(buffer), "ReadProcessMemory didn't read all data (%lx)\n", result );
993 ok( !memcmp( buffer, data, sizeof(buffer) ), "Wrong data read\n" );
995 status = pNtUnmapViewOfSection( hProcess, ptr );
996 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
998 CloseHandle( mapping );
999 CloseHandle( file );
1000 DeleteFileA( testfile );
1002 TerminateProcess(hProcess, 0);
1003 CloseHandle(hProcess);
1006 static void test_NtAreMappedFilesTheSame(void)
1008 static const char testfile[] = "testfile.xxx";
1009 HANDLE file, file2, mapping, map2;
1010 void *ptr, *ptr2;
1011 NTSTATUS status;
1012 char path[MAX_PATH];
1014 if (!pNtAreMappedFilesTheSame)
1016 win_skip( "NtAreMappedFilesTheSame not available\n" );
1017 return;
1020 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
1021 NULL, CREATE_ALWAYS, 0, 0 );
1022 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1023 SetFilePointer( file, 4096, NULL, FILE_BEGIN );
1024 SetEndOfFile( file );
1026 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
1027 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1029 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1030 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1032 file2 = CreateFileA( testfile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1033 NULL, OPEN_EXISTING, 0, 0 );
1034 ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1036 map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY, 0, 4096, NULL );
1037 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1038 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
1039 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1040 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1041 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1042 UnmapViewOfFile( ptr2 );
1044 ptr2 = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1045 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1046 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1047 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1048 UnmapViewOfFile( ptr2 );
1049 CloseHandle( map2 );
1051 map2 = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
1052 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1053 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
1054 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1055 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1056 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1057 UnmapViewOfFile( ptr2 );
1058 CloseHandle( map2 );
1059 CloseHandle( file2 );
1061 status = pNtAreMappedFilesTheSame( ptr, ptr );
1062 ok( status == STATUS_SUCCESS || broken(status == STATUS_NOT_SAME_DEVICE),
1063 "NtAreMappedFilesTheSame returned %x\n", status );
1065 status = pNtAreMappedFilesTheSame( ptr, (char *)ptr + 30 );
1066 ok( status == STATUS_SUCCESS || broken(status == STATUS_NOT_SAME_DEVICE),
1067 "NtAreMappedFilesTheSame returned %x\n", status );
1069 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1070 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1072 status = pNtAreMappedFilesTheSame( ptr, (void *)0xdeadbeef );
1073 ok( status == STATUS_CONFLICTING_ADDRESSES || status == STATUS_INVALID_ADDRESS,
1074 "NtAreMappedFilesTheSame returned %x\n", status );
1076 status = pNtAreMappedFilesTheSame( ptr, NULL );
1077 ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
1079 status = pNtAreMappedFilesTheSame( ptr, (void *)GetProcessHeap() );
1080 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
1082 status = pNtAreMappedFilesTheSame( NULL, NULL );
1083 ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
1085 ptr2 = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE );
1086 ok( ptr2 != NULL, "VirtualAlloc error %u\n", GetLastError() );
1087 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1088 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
1089 VirtualFree( ptr2, 0, MEM_RELEASE );
1091 UnmapViewOfFile( ptr );
1092 CloseHandle( mapping );
1093 CloseHandle( file );
1095 status = pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
1096 GetModuleHandleA("kernel32.dll") );
1097 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1098 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1099 GetModuleHandleA("kernel32.dll") );
1100 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1101 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1102 (char *)GetModuleHandleA("kernel32.dll") + 4096 );
1103 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1105 GetSystemDirectoryA( path, MAX_PATH );
1106 strcat( path, "\\kernel32.dll" );
1107 file = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
1108 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1110 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
1111 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1112 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1113 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1114 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1115 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1116 UnmapViewOfFile( ptr );
1117 CloseHandle( mapping );
1119 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
1120 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1121 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
1122 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1123 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1124 todo_wine
1125 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1127 file2 = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
1128 ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1129 map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
1130 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1131 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 0 );
1132 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1133 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1134 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1135 UnmapViewOfFile( ptr2 );
1136 CloseHandle( map2 );
1137 CloseHandle( file2 );
1139 UnmapViewOfFile( ptr );
1140 CloseHandle( mapping );
1142 CloseHandle( file );
1143 DeleteFileA( testfile );
1146 static void test_CreateFileMapping(void)
1148 HANDLE handle, handle2;
1150 /* test case sensitivity */
1152 SetLastError(0xdeadbeef);
1153 handle = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1154 "Wine Test Mapping");
1155 ok( handle != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
1156 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1158 SetLastError(0xdeadbeef);
1159 handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1160 "Wine Test Mapping");
1161 ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
1162 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
1163 CloseHandle( handle2 );
1165 SetLastError(0xdeadbeef);
1166 handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1167 "WINE TEST MAPPING");
1168 ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
1169 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1170 CloseHandle( handle2 );
1172 SetLastError(0xdeadbeef);
1173 handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "Wine Test Mapping");
1174 ok( handle2 != NULL, "OpenFileMapping failed with error %d\n", GetLastError());
1175 CloseHandle( handle2 );
1177 SetLastError(0xdeadbeef);
1178 handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "WINE TEST MAPPING");
1179 ok( !handle2, "OpenFileMapping succeeded\n");
1180 ok( GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME /* win9x */,
1181 "wrong error %u\n", GetLastError());
1183 CloseHandle( handle );
1186 static void test_IsBadReadPtr(void)
1188 BOOL ret;
1189 void *ptr = (void *)0xdeadbeef;
1190 char stackvar;
1192 ret = IsBadReadPtr(NULL, 0);
1193 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1195 ret = IsBadReadPtr(NULL, 1);
1196 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1198 ret = IsBadReadPtr(ptr, 0);
1199 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1201 ret = IsBadReadPtr(ptr, 1);
1202 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1204 ret = IsBadReadPtr(&stackvar, 0);
1205 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1207 ret = IsBadReadPtr(&stackvar, sizeof(char));
1208 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1211 static void test_IsBadWritePtr(void)
1213 BOOL ret;
1214 void *ptr = (void *)0xdeadbeef;
1215 char stackval;
1217 ret = IsBadWritePtr(NULL, 0);
1218 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1220 ret = IsBadWritePtr(NULL, 1);
1221 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1223 ret = IsBadWritePtr(ptr, 0);
1224 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1226 ret = IsBadWritePtr(ptr, 1);
1227 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1229 ret = IsBadWritePtr(&stackval, 0);
1230 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1232 ret = IsBadWritePtr(&stackval, sizeof(char));
1233 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1236 static void test_IsBadCodePtr(void)
1238 BOOL ret;
1239 void *ptr = (void *)0xdeadbeef;
1240 char stackval;
1242 ret = IsBadCodePtr(NULL);
1243 ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1245 ret = IsBadCodePtr(ptr);
1246 ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1248 ret = IsBadCodePtr((void *)&stackval);
1249 ok(ret == FALSE, "Expected IsBadCodePtr to return FALSE, got %d\n", ret);
1252 static void test_write_watch(void)
1254 char *base;
1255 DWORD ret, size, old_prot;
1256 MEMORY_BASIC_INFORMATION info;
1257 void *results[64];
1258 ULONG_PTR count;
1259 ULONG pagesize;
1261 if (!pGetWriteWatch || !pResetWriteWatch)
1263 win_skip( "GetWriteWatch not supported\n" );
1264 return;
1267 size = 0x10000;
1268 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE );
1269 if (!base &&
1270 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
1272 win_skip( "MEM_WRITE_WATCH not supported\n" );
1273 return;
1275 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1276 ret = VirtualQuery( base, &info, sizeof(info) );
1277 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1278 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1279 ok( info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect %x\n", info.AllocationProtect );
1280 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1281 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1282 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1283 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
1285 count = 64;
1286 SetLastError( 0xdeadbeef );
1287 ret = pGetWriteWatch( 0, NULL, size, results, &count, &pagesize );
1288 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1289 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
1290 broken( GetLastError() == 0xdeadbeef ), /* win98 */
1291 "wrong error %u\n", GetLastError() );
1293 SetLastError( 0xdeadbeef );
1294 ret = pGetWriteWatch( 0, GetModuleHandleW(NULL), size, results, &count, &pagesize );
1295 if (ret)
1297 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1298 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1300 else /* win98 */
1302 ok( count == 0, "wrong count %lu\n", count );
1305 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1306 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1307 ok( count == 0, "wrong count %lu\n", count );
1309 base[pagesize + 1] = 0x44;
1311 count = 64;
1312 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1313 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1314 ok( count == 1, "wrong count %lu\n", count );
1315 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1317 count = 64;
1318 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1319 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1320 ok( count == 1, "wrong count %lu\n", count );
1321 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1323 count = 64;
1324 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1325 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1326 ok( count == 0, "wrong count %lu\n", count );
1328 base[2*pagesize + 3] = 0x11;
1329 base[4*pagesize + 8] = 0x11;
1331 count = 64;
1332 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1333 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1334 ok( count == 2, "wrong count %lu\n", count );
1335 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1336 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1338 count = 64;
1339 ret = pGetWriteWatch( 0, base + 3*pagesize, 2*pagesize, results, &count, &pagesize );
1340 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1341 ok( count == 1, "wrong count %lu\n", count );
1342 ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1344 ret = pResetWriteWatch( base, 3*pagesize );
1345 ok( !ret, "pResetWriteWatch failed %u\n", GetLastError() );
1347 count = 64;
1348 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1349 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1350 ok( count == 1, "wrong count %lu\n", count );
1351 ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1353 *(DWORD *)(base + 2*pagesize - 2) = 0xdeadbeef;
1355 count = 64;
1356 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1357 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1358 ok( count == 3, "wrong count %lu\n", count );
1359 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1360 ok( results[1] == base + 2*pagesize, "wrong result %p\n", results[1] );
1361 ok( results[2] == base + 4*pagesize, "wrong result %p\n", results[2] );
1363 count = 1;
1364 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1365 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1366 ok( count == 1, "wrong count %lu\n", count );
1367 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1369 count = 64;
1370 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1371 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1372 ok( count == 2, "wrong count %lu\n", count );
1373 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1374 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1376 /* changing protections doesn't affect watches */
1378 ret = VirtualProtect( base, 3*pagesize, PAGE_READONLY, &old_prot );
1379 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1380 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1382 ret = VirtualQuery( base, &info, sizeof(info) );
1383 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1384 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1385 ok( info.RegionSize == 3*pagesize, "wrong RegionSize 0x%lx\n", info.RegionSize );
1386 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1387 ok( info.Protect == PAGE_READONLY, "wrong Protect 0x%x\n", info.Protect );
1389 ret = VirtualProtect( base, 3*pagesize, PAGE_READWRITE, &old_prot );
1390 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1391 ok( old_prot == PAGE_READONLY, "wrong old prot %x\n", old_prot );
1393 count = 64;
1394 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1395 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1396 ok( count == 2, "wrong count %lu\n", count );
1397 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1398 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1400 ret = VirtualQuery( base, &info, sizeof(info) );
1401 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1402 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1403 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1404 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1405 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1407 /* some invalid parameter tests */
1409 SetLastError( 0xdeadbeef );
1410 count = 0;
1411 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1412 if (ret)
1414 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1415 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1417 SetLastError( 0xdeadbeef );
1418 ret = pGetWriteWatch( 0, base, size, results, NULL, &pagesize );
1419 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1420 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1422 SetLastError( 0xdeadbeef );
1423 count = 64;
1424 ret = pGetWriteWatch( 0, base, size, results, &count, NULL );
1425 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1426 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1428 SetLastError( 0xdeadbeef );
1429 count = 64;
1430 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1431 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1432 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1434 SetLastError( 0xdeadbeef );
1435 count = 0;
1436 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1437 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1438 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1440 SetLastError( 0xdeadbeef );
1441 count = 64;
1442 ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
1443 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1444 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1446 SetLastError( 0xdeadbeef );
1447 count = 64;
1448 ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
1449 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1450 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1452 SetLastError( 0xdeadbeef );
1453 count = 64;
1454 ret = pGetWriteWatch( 0, base, size * 2, results, &count, &pagesize );
1455 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1456 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1458 SetLastError( 0xdeadbeef );
1459 count = 64;
1460 ret = pGetWriteWatch( 0, base + size - pagesize, pagesize + 1, results, &count, &pagesize );
1461 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1462 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1464 SetLastError( 0xdeadbeef );
1465 ret = pResetWriteWatch( base, 0 );
1466 ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
1467 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1469 SetLastError( 0xdeadbeef );
1470 ret = pResetWriteWatch( GetModuleHandleW(NULL), size );
1471 ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
1472 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1474 else /* win98 is completely different */
1476 SetLastError( 0xdeadbeef );
1477 count = 64;
1478 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1479 ok( ret == ERROR_INVALID_PARAMETER, "GetWriteWatch succeeded %u\n", ret );
1480 ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
1482 count = 0;
1483 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1484 ok( !ret, "GetWriteWatch failed %u\n", ret );
1486 count = 64;
1487 ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
1488 ok( !ret, "GetWriteWatch failed %u\n", ret );
1490 count = 64;
1491 ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
1492 ok( !ret, "GetWriteWatch failed %u\n", ret );
1494 ret = pResetWriteWatch( base, 0 );
1495 ok( !ret, "ResetWriteWatch failed %u\n", ret );
1497 ret = pResetWriteWatch( GetModuleHandleW(NULL), size );
1498 ok( !ret, "ResetWriteWatch failed %u\n", ret );
1501 VirtualFree( base, 0, MEM_FREE );
1503 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_READWRITE );
1504 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1505 VirtualFree( base, 0, MEM_FREE );
1507 base = VirtualAlloc( 0, size, MEM_WRITE_WATCH, PAGE_READWRITE );
1508 ok( !base, "VirtualAlloc succeeded\n" );
1509 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1511 /* initial protect doesn't matter */
1513 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_NOACCESS );
1514 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1515 base = VirtualAlloc( base, size, MEM_COMMIT, PAGE_NOACCESS );
1516 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1518 count = 64;
1519 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1520 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1521 ok( count == 0, "wrong count %lu\n", count );
1523 ret = VirtualProtect( base, 6*pagesize, PAGE_READWRITE, &old_prot );
1524 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1525 ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
1527 base[5*pagesize + 200] = 3;
1529 ret = VirtualProtect( base, 6*pagesize, PAGE_NOACCESS, &old_prot );
1530 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1531 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1533 count = 64;
1534 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1535 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1536 ok( count == 1, "wrong count %lu\n", count );
1537 ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
1539 ret = VirtualFree( base, size, MEM_DECOMMIT );
1540 ok( ret, "VirtualFree failed %u\n", GetLastError() );
1542 count = 64;
1543 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1544 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1545 ok( count == 1 || broken(count == 0), /* win98 */
1546 "wrong count %lu\n", count );
1547 if (count) ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
1549 VirtualFree( base, 0, MEM_FREE );
1552 #ifdef __i386__
1554 static DWORD num_guard_page_calls;
1556 static DWORD guard_page_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
1557 CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
1559 trace( "exception: %08x flags:%x addr:%p\n",
1560 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
1562 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
1563 ok( rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION, "ExceptionCode is %08x instead of %08x\n",
1564 rec->ExceptionCode, STATUS_GUARD_PAGE_VIOLATION );
1566 num_guard_page_calls++;
1567 *(int *)rec->ExceptionInformation[1] += 0x100;
1569 return ExceptionContinueExecution;
1572 static void test_guard_page(void)
1574 EXCEPTION_REGISTRATION_RECORD frame;
1575 MEMORY_BASIC_INFORMATION info;
1576 DWORD ret, size, old_prot;
1577 int *value, old_value;
1578 void *results[64];
1579 ULONG_PTR count;
1580 ULONG pagesize;
1581 BOOL success;
1582 char *base;
1584 if (!pNtCurrentTeb)
1586 win_skip( "NtCurrentTeb not supported\n" );
1587 return;
1590 size = 0x1000;
1591 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
1592 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1593 value = (int *)base;
1595 /* verify info structure */
1596 ret = VirtualQuery( base, &info, sizeof(info) );
1597 ok( ret, "VirtualQuery failed %u\n", GetLastError());
1598 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1599 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
1600 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1601 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1602 ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%x\n", info.Protect );
1603 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
1605 /* put some initial value into the memory */
1606 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
1607 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1608 ok( old_prot == (PAGE_READWRITE | PAGE_GUARD), "wrong old prot %x\n", old_prot );
1610 *value = 1;
1611 *(value + 1) = 2;
1613 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
1614 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1615 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1617 /* test behaviour of VirtualLock - first attempt should fail */
1618 SetLastError( 0xdeadbeef );
1619 success = VirtualLock( base, size );
1620 ok( !success, "VirtualLock unexpectedly succeded\n" );
1621 todo_wine
1622 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %u\n", GetLastError() );
1624 success = VirtualLock( base, size );
1625 todo_wine
1626 ok( success, "VirtualLock failed %u\n", GetLastError() );
1627 if (success)
1629 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
1630 success = VirtualUnlock( base, size );
1631 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
1634 /* check info structure again, PAGE_GUARD should be removed now */
1635 ret = VirtualQuery( base, &info, sizeof(info) );
1636 ok( ret, "VirtualQuery failed %u\n", GetLastError());
1637 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1638 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
1639 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1640 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1641 todo_wine
1642 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1643 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
1645 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
1646 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1647 todo_wine
1648 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1650 /* test directly accessing the memory - we need to setup an exception handler first */
1651 frame.Handler = guard_page_handler;
1652 frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
1653 pNtCurrentTeb()->Tib.ExceptionList = &frame;
1655 num_guard_page_calls = 0;
1656 old_value = *value; /* exception handler increments value by 0x100 */
1657 *value = 2;
1658 ok( old_value == 0x101, "memory block contains wrong value, expected 0x101, got 0x%x\n", old_value );
1659 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
1661 pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
1663 /* check info structure again, PAGE_GUARD should be removed now */
1664 ret = VirtualQuery( base, &info, sizeof(info) );
1665 ok( ret, "VirtualQuery failed %u\n", GetLastError());
1666 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1668 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
1669 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1670 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1672 /* test accessing second integer in memory */
1673 frame.Handler = guard_page_handler;
1674 frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
1675 pNtCurrentTeb()->Tib.ExceptionList = &frame;
1677 num_guard_page_calls = 0;
1678 old_value = *(value + 1);
1679 ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value );
1680 ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value );
1681 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
1683 pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
1685 success = VirtualLock( base, size );
1686 ok( success, "VirtualLock failed %u\n", GetLastError() );
1687 if (success)
1689 ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value );
1690 success = VirtualUnlock( base, size );
1691 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
1694 VirtualFree( base, 0, MEM_FREE );
1696 /* combined guard page / write watch tests */
1697 if (!pGetWriteWatch || !pResetWriteWatch)
1699 win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" );
1700 return;
1703 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE | PAGE_GUARD );
1704 if (!base && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
1706 win_skip( "MEM_WRITE_WATCH not supported\n" );
1707 return;
1709 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1710 value = (int *)base;
1712 ret = VirtualQuery( base, &info, sizeof(info) );
1713 ok( ret, "VirtualQuery failed %u\n", GetLastError() );
1714 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1715 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
1716 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1717 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1718 ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%x\n", info.Protect );
1719 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
1721 count = 64;
1722 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1723 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1724 ok( count == 0, "wrong count %lu\n", count );
1726 /* writing to a page should trigger should trigger guard page, even if write watch is set */
1727 frame.Handler = guard_page_handler;
1728 frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
1729 pNtCurrentTeb()->Tib.ExceptionList = &frame;
1731 num_guard_page_calls = 0;
1732 *value = 1;
1733 *(value + 1) = 2;
1734 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
1736 pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
1738 count = 64;
1739 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1740 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1741 ok( count == 1, "wrong count %lu\n", count );
1742 ok( results[0] == base, "wrong result %p\n", results[0] );
1744 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
1745 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1747 /* write watch is triggered from inside of the guard page handler */
1748 frame.Handler = guard_page_handler;
1749 frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
1750 pNtCurrentTeb()->Tib.ExceptionList = &frame;
1752 num_guard_page_calls = 0;
1753 old_value = *(value + 1); /* doesn't trigger write watch */
1754 ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value );
1755 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
1756 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
1758 pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
1760 count = 64;
1761 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1762 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1763 ok( count == 1, "wrong count %lu\n", count );
1764 ok( results[0] == base, "wrong result %p\n", results[0] );
1766 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
1767 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1769 /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */
1770 SetLastError( 0xdeadbeef );
1771 success = VirtualLock( base, size );
1772 ok( !success, "VirtualLock unexpectedly succeded\n" );
1773 todo_wine
1774 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %u\n", GetLastError() );
1776 count = 64;
1777 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1778 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1779 ok( count == 0, "wrong count %lu\n", count );
1781 success = VirtualLock( base, size );
1782 todo_wine
1783 ok( success, "VirtualLock failed %u\n", GetLastError() );
1784 if (success)
1786 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
1787 success = VirtualUnlock( base, size );
1788 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
1791 count = 64;
1792 results[0] = (void *)0xdeadbeef;
1793 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1794 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1795 todo_wine
1796 ok( count == 1 || broken(count == 0) /* Windows 8 */, "wrong count %lu\n", count );
1797 todo_wine
1798 ok( results[0] == base || broken(results[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results[0] );
1800 VirtualFree( base, 0, MEM_FREE );
1803 DWORD num_execute_fault_calls;
1805 static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
1806 CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
1808 ULONG flags = MEM_EXECUTE_OPTION_ENABLE;
1810 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
1811 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
1812 rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] );
1814 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
1815 ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION || rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION,
1816 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec->ExceptionCode );
1818 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags), NULL );
1820 if (rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
1823 ok( rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT ||
1824 broken(!(flags & MEM_EXECUTE_OPTION_DISABLE) && rec->ExceptionInformation[0] == EXCEPTION_READ_FAULT), /* Windows 2000 */
1825 "ExceptionInformation[0] is %d instead of %d\n", (DWORD)rec->ExceptionInformation[0], EXCEPTION_EXECUTE_FAULT );
1827 num_guard_page_calls++;
1829 else if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION)
1831 DWORD err, old_prot;
1832 BOOL success;
1834 err = (flags & MEM_EXECUTE_OPTION_DISABLE) ? EXCEPTION_EXECUTE_FAULT : EXCEPTION_READ_FAULT;
1835 ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %d instead of %d\n",
1836 (DWORD)rec->ExceptionInformation[0], err );
1838 success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
1839 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1840 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1842 num_execute_fault_calls++;
1845 return ExceptionContinueExecution;
1848 static LONG CALLBACK execute_fault_vec_handler( EXCEPTION_POINTERS *ExceptionInfo )
1850 PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
1851 DWORD old_prot;
1852 BOOL success;
1854 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
1855 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
1856 rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] );
1858 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
1859 ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION,
1860 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec->ExceptionCode );
1862 if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION)
1863 num_execute_fault_calls++;
1865 if (rec->ExceptionInformation[0] == EXCEPTION_READ_FAULT)
1866 return EXCEPTION_CONTINUE_SEARCH;
1868 success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
1869 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1870 ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
1872 return EXCEPTION_CONTINUE_EXECUTION;
1875 static inline DWORD send_message_excpt( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
1877 EXCEPTION_REGISTRATION_RECORD frame;
1878 DWORD ret;
1880 frame.Handler = execute_fault_seh_handler;
1881 frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
1882 pNtCurrentTeb()->Tib.ExceptionList = &frame;
1884 num_guard_page_calls = num_execute_fault_calls = 0;
1885 ret = SendMessageA( hWnd, WM_USER, 0, 0 );
1887 pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
1889 return ret;
1892 static LRESULT CALLBACK jmp_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
1894 if (uMsg == WM_USER)
1895 return 42;
1897 return DefWindowProcA( hWnd, uMsg, wParam, lParam );
1900 static LRESULT CALLBACK atl_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
1902 DWORD arg = (DWORD)hWnd;
1903 ok( arg == 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg );
1904 return 43;
1907 static void test_atl_thunk_emulation( ULONG dep_flags )
1909 static const char code_jmp[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
1910 static const char code_atl[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
1911 static const char cls_name[] = "atl_thunk_class";
1912 DWORD ret, size, old_prot;
1913 ULONG old_flags = MEM_EXECUTE_OPTION_ENABLE;
1914 void *results[64];
1915 ULONG_PTR count;
1916 ULONG pagesize;
1917 WNDCLASSEXA wc;
1918 BOOL success;
1919 char *base;
1920 HWND hWnd;
1922 if (!pNtCurrentTeb)
1924 win_skip( "NtCurrentTeb not supported\n" );
1925 return;
1928 trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
1930 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags), NULL );
1931 if (old_flags != dep_flags)
1933 ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &dep_flags, sizeof(dep_flags) );
1934 if (ret == STATUS_INVALID_INFO_CLASS) /* Windows 2000 */
1936 win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
1937 return;
1939 ok( !ret, "NtSetInformationProcess failed with status %08x\n", ret );
1942 size = 0x1000;
1943 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
1944 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1946 memcpy( base, code_jmp, sizeof(code_jmp) );
1947 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
1949 /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
1950 * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
1951 * where it is active, so that application which depend on that still work properly.
1952 * We have no exception handler enabled yet, so give proper EXECUTE permissions to
1953 * prevent crashes while creating the window. */
1955 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
1956 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1958 memset( &wc, 0, sizeof(wc) );
1959 wc.cbSize = sizeof(wc);
1960 wc.style = CS_VREDRAW | CS_HREDRAW;
1961 wc.hInstance = GetModuleHandleA( 0 );
1962 wc.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW );
1963 wc.hbrBackground = NULL;
1964 wc.lpszClassName = cls_name;
1965 wc.lpfnWndProc = (WNDPROC)base;
1966 success = RegisterClassExA(&wc) != 0;
1967 ok( success, "RegisterClassExA failed %u\n", GetLastError() );
1969 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
1970 ok( hWnd != 0, "CreateWindowExA failed %u\n", GetLastError() );
1972 ret = SendMessageA(hWnd, WM_USER, 0, 0);
1973 ok( ret == 42, "SendMessage returned unexpected result %d\n", ret );
1975 /* At first try with an instruction which is not recognized as proper ATL thunk
1976 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
1977 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
1979 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
1980 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1982 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
1983 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
1984 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
1985 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
1986 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
1987 else
1988 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
1990 /* Now a bit more complicated, the page containing the code is protected with
1991 * PAGE_GUARD memory protection. */
1993 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
1994 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1996 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
1997 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
1998 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
1999 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2000 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2001 else
2002 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2004 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2005 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2006 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2007 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2009 /* Now test with a proper ATL thunk instruction. */
2011 memcpy( base, code_atl, sizeof(code_atl) );
2012 *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
2014 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2015 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2017 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2018 ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
2020 /* Try executing with PAGE_READWRITE protection. */
2022 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2023 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2025 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2026 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2027 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2028 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2029 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2030 else
2031 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2033 /* Now a bit more complicated, the page containing the code is protected with
2034 * PAGE_GUARD memory protection. */
2036 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2037 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2039 /* the same, but with PAGE_GUARD set */
2040 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2041 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2042 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2043 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2044 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2045 else
2046 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2048 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2049 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2050 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2051 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2053 /* The following test shows that on Windows, even a vectored exception handler
2054 * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */
2056 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && !(dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2058 if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
2060 PVOID vectored_handler;
2062 success = VirtualProtect( base, size, PAGE_NOACCESS, &old_prot );
2063 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2065 vectored_handler = pRtlAddVectoredExceptionHandler( TRUE, &execute_fault_vec_handler );
2066 ok( vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n" );
2068 num_execute_fault_calls = 0;
2069 ret = SendMessageA( hWnd, WM_USER, 0, 0 );
2071 pRtlRemoveVectoredExceptionHandler( vectored_handler );
2073 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2074 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2076 else
2077 win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" );
2080 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2082 memcpy( base, code_jmp, sizeof(code_jmp) );
2083 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2085 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2086 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2088 DestroyWindow( hWnd );
2090 success = UnregisterClassA( cls_name, GetModuleHandleA(0) );
2091 ok( success, "UnregisterClass failed %u\n", GetLastError() );
2093 VirtualFree( base, 0, MEM_FREE );
2095 /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */
2097 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE );
2098 if (!base && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
2100 win_skip( "MEM_WRITE_WATCH not supported\n" );
2101 goto out;
2103 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2105 count = 64;
2106 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2107 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2108 ok( count == 0, "wrong count %lu\n", count );
2110 memcpy( base, code_jmp, sizeof(code_jmp) );
2111 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2113 count = 64;
2114 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2115 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2116 ok( count == 1, "wrong count %lu\n", count );
2117 ok( results[0] == base, "wrong result %p\n", results[0] );
2119 /* Create a new window class and associcated Window (see above) */
2121 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2122 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2124 memset( &wc, 0, sizeof(wc) );
2125 wc.cbSize = sizeof(wc);
2126 wc.style = CS_VREDRAW | CS_HREDRAW;
2127 wc.hInstance = GetModuleHandleA( 0 );
2128 wc.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW );
2129 wc.hbrBackground = NULL;
2130 wc.lpszClassName = cls_name;
2131 wc.lpfnWndProc = (WNDPROC)base;
2132 success = RegisterClassExA(&wc) != 0;
2133 ok( success, "RegisterClassExA failed %u\n", GetLastError() );
2135 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2136 ok( hWnd != 0, "CreateWindowExA failed %u\n", GetLastError() );
2138 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2139 ok( ret == 42, "SendMessage returned unexpected result %d\n", ret );
2141 count = 64;
2142 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2143 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2144 ok( count == 0, "wrong count %lu\n", count );
2146 /* At first try with an instruction which is not recognized as proper ATL thunk
2147 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2148 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2150 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2151 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2153 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2154 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2155 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2156 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2157 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2158 else
2159 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2161 count = 64;
2162 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2163 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2164 ok( count == 0, "wrong count %lu\n", count );
2166 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2167 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2168 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2169 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2171 /* Now a bit more complicated, the page containing the code is protected with
2172 * PAGE_GUARD memory protection. */
2174 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2175 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2177 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2178 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2179 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2180 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2181 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2182 else
2183 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2185 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2186 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2187 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2188 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2190 count = 64;
2191 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2192 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2193 ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
2195 /* Now test with a proper ATL thunk instruction. */
2197 memcpy( base, code_atl, sizeof(code_atl) );
2198 *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
2200 count = 64;
2201 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2202 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2203 ok( count == 1, "wrong count %lu\n", count );
2204 ok( results[0] == base, "wrong result %p\n", results[0] );
2206 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2207 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2209 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2210 ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
2212 /* Try executing with PAGE_READWRITE protection. */
2214 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2215 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2217 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2218 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2219 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2220 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2221 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2222 else
2223 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2225 count = 64;
2226 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2227 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2228 ok( count == 0, "wrong count %lu\n", count );
2230 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2231 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2232 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2233 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2234 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2235 else
2236 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2238 /* Now a bit more complicated, the page containing the code is protected with
2239 * PAGE_GUARD memory protection. */
2241 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2242 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2244 /* the same, but with PAGE_GUARD set */
2245 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2246 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2247 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2248 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2249 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2250 else
2251 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2253 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2254 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2255 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2256 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2258 count = 64;
2259 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2260 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2261 ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
2263 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2265 memcpy( base, code_jmp, sizeof(code_jmp) );
2266 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2268 count = 64;
2269 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2270 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2271 ok( count == 1, "wrong count %lu\n", count );
2272 ok( results[0] == base, "wrong result %p\n", results[0] );
2274 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2275 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2277 DestroyWindow( hWnd );
2279 success = UnregisterClassA( cls_name, GetModuleHandleA(0) );
2280 ok( success, "UnregisterClass failed %u\n", GetLastError() );
2282 VirtualFree( base, 0, MEM_FREE );
2284 out:
2285 if (old_flags != dep_flags)
2287 ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags) );
2288 ok( !ret, "NtSetInformationProcess failed with status %08x\n", ret );
2292 #endif /* __i386__ */
2294 static void test_VirtualProtect(void)
2296 static const struct test_data
2298 DWORD prot_set, prot_get;
2299 } td[] =
2301 { 0, 0 }, /* 0x00 */
2302 { PAGE_NOACCESS, PAGE_NOACCESS }, /* 0x01 */
2303 { PAGE_READONLY, PAGE_READONLY }, /* 0x02 */
2304 { PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x03 */
2305 { PAGE_READWRITE, PAGE_READWRITE }, /* 0x04 */
2306 { PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x05 */
2307 { PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x06 */
2308 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x07 */
2309 { PAGE_WRITECOPY, 0 }, /* 0x08 */
2310 { PAGE_WRITECOPY | PAGE_NOACCESS, 0 }, /* 0x09 */
2311 { PAGE_WRITECOPY | PAGE_READONLY, 0 }, /* 0x0a */
2312 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, 0 }, /* 0x0b */
2313 { PAGE_WRITECOPY | PAGE_READWRITE, 0 }, /* 0x0c */
2314 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x0d */
2315 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x0e */
2316 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x0f */
2318 { PAGE_EXECUTE, PAGE_EXECUTE }, /* 0x10 */
2319 { PAGE_EXECUTE_READ, PAGE_EXECUTE_READ }, /* 0x20 */
2320 { PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x30 */
2321 { PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_READWRITE }, /* 0x40 */
2322 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0x50 */
2323 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0x60 */
2324 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x70 */
2325 { PAGE_EXECUTE_WRITECOPY, 0 }, /* 0x80 */
2326 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, 0 }, /* 0x90 */
2327 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, 0 }, /* 0xa0 */
2328 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0xb0 */
2329 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, 0 }, /* 0xc0 */
2330 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0xd0 */
2331 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0xe0 */
2332 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 } /* 0xf0 */
2334 char *base, *ptr;
2335 DWORD ret, old_prot, rw_prot, exec_prot, i, j;
2336 MEMORY_BASIC_INFORMATION info;
2337 SYSTEM_INFO si;
2339 GetSystemInfo(&si);
2340 trace("system page size %#x\n", si.dwPageSize);
2342 SetLastError(0xdeadbeef);
2343 base = VirtualAlloc(0, si.dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
2344 ok(base != NULL, "VirtualAlloc failed %d\n", GetLastError());
2346 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2348 SetLastError(0xdeadbeef);
2349 ret = VirtualQuery(base, &info, sizeof(info));
2350 ok(ret, "VirtualQuery failed %d\n", GetLastError());
2351 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
2352 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
2353 ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect);
2354 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
2355 ok(info.AllocationProtect == PAGE_NOACCESS, "%d: %#x != PAGE_NOACCESS\n", i, info.AllocationProtect);
2356 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
2357 ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
2359 old_prot = 0xdeadbeef;
2360 SetLastError(0xdeadbeef);
2361 ret = VirtualProtect(base, si.dwPageSize, td[i].prot_set, &old_prot);
2362 if (td[i].prot_get)
2364 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
2365 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
2367 SetLastError(0xdeadbeef);
2368 ret = VirtualQuery(base, &info, sizeof(info));
2369 ok(ret, "VirtualQuery failed %d\n", GetLastError());
2370 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
2371 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
2372 ok(info.Protect == td[i].prot_get, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_get);
2373 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
2374 ok(info.AllocationProtect == PAGE_NOACCESS, "%d: %#x != PAGE_NOACCESS\n", i, info.AllocationProtect);
2375 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
2376 ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
2378 else
2380 ok(!ret, "%d: VirtualProtect should fail\n", i);
2381 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
2384 old_prot = 0xdeadbeef;
2385 SetLastError(0xdeadbeef);
2386 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
2387 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
2388 if (td[i].prot_get)
2389 ok(old_prot == td[i].prot_get, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_get);
2390 else
2391 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
2394 exec_prot = 0;
2396 for (i = 0; i <= 4; i++)
2398 rw_prot = 0;
2400 for (j = 0; j <= 4; j++)
2402 DWORD prot = exec_prot | rw_prot;
2404 SetLastError(0xdeadbeef);
2405 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, prot);
2406 if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
2408 ok(!ptr, "VirtualAlloc(%02x) should fail\n", prot);
2409 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2411 else
2413 if (prot & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))
2415 ok(!ptr, "VirtualAlloc(%02x) should fail\n", prot);
2416 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2418 else
2420 ok(ptr != NULL, "VirtualAlloc(%02x) error %d\n", prot, GetLastError());
2421 ok(ptr == base, "expected %p, got %p\n", base, ptr);
2425 SetLastError(0xdeadbeef);
2426 ret = VirtualProtect(base, si.dwPageSize, prot, &old_prot);
2427 if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
2429 ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
2430 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2432 else
2434 if (prot & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))
2436 ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
2437 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2439 else
2440 ok(ret, "VirtualProtect(%02x) error %d\n", prot, GetLastError());
2443 rw_prot = 1 << j;
2446 exec_prot = 1 << (i + 4);
2449 VirtualFree(base, 0, MEM_FREE);
2452 static BOOL is_mem_writable(DWORD prot)
2454 switch (prot & 0xff)
2456 case PAGE_READWRITE:
2457 case PAGE_WRITECOPY:
2458 case PAGE_EXECUTE_READWRITE:
2459 case PAGE_EXECUTE_WRITECOPY:
2460 return TRUE;
2462 default:
2463 return FALSE;
2467 static void test_VirtualAlloc_protection(void)
2469 static const struct test_data
2471 DWORD prot;
2472 BOOL success;
2473 } td[] =
2475 { 0, FALSE }, /* 0x00 */
2476 { PAGE_NOACCESS, TRUE }, /* 0x01 */
2477 { PAGE_READONLY, TRUE }, /* 0x02 */
2478 { PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x03 */
2479 { PAGE_READWRITE, TRUE }, /* 0x04 */
2480 { PAGE_READWRITE | PAGE_NOACCESS, FALSE }, /* 0x05 */
2481 { PAGE_READWRITE | PAGE_READONLY, FALSE }, /* 0x06 */
2482 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x07 */
2483 { PAGE_WRITECOPY, FALSE }, /* 0x08 */
2484 { PAGE_WRITECOPY | PAGE_NOACCESS, FALSE }, /* 0x09 */
2485 { PAGE_WRITECOPY | PAGE_READONLY, FALSE }, /* 0x0a */
2486 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, FALSE }, /* 0x0b */
2487 { PAGE_WRITECOPY | PAGE_READWRITE, FALSE }, /* 0x0c */
2488 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, FALSE }, /* 0x0d */
2489 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, FALSE }, /* 0x0e */
2490 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x0f */
2492 { PAGE_EXECUTE, TRUE }, /* 0x10 */
2493 { PAGE_EXECUTE_READ, TRUE }, /* 0x20 */
2494 { PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0x30 */
2495 { PAGE_EXECUTE_READWRITE, TRUE }, /* 0x40 */
2496 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE }, /* 0x50 */
2497 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE }, /* 0x60 */
2498 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0x70 */
2499 { PAGE_EXECUTE_WRITECOPY, FALSE }, /* 0x80 */
2500 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, FALSE }, /* 0x90 */
2501 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, FALSE }, /* 0xa0 */
2502 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0xb0 */
2503 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, FALSE }, /* 0xc0 */
2504 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE }, /* 0xd0 */
2505 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE }, /* 0xe0 */
2506 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE } /* 0xf0 */
2508 char *base, *ptr;
2509 DWORD ret, i;
2510 MEMORY_BASIC_INFORMATION info;
2511 SYSTEM_INFO si;
2513 GetSystemInfo(&si);
2514 trace("system page size %#x\n", si.dwPageSize);
2516 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2518 SetLastError(0xdeadbeef);
2519 base = VirtualAlloc(0, si.dwPageSize, MEM_COMMIT, td[i].prot);
2521 if (td[i].success)
2523 ok(base != NULL, "%d: VirtualAlloc failed %d\n", i, GetLastError());
2525 SetLastError(0xdeadbeef);
2526 ret = VirtualQuery(base, &info, sizeof(info));
2527 ok(ret, "VirtualQuery failed %d\n", GetLastError());
2528 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
2529 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
2530 ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
2531 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
2532 ok(info.AllocationProtect == td[i].prot, "%d: %#x != %#x\n", i, info.AllocationProtect, td[i].prot);
2533 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
2534 ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
2536 if (is_mem_writable(info.Protect))
2538 base[0] = 0xfe;
2540 SetLastError(0xdeadbeef);
2541 ret = VirtualQuery(base, &info, sizeof(info));
2542 ok(ret, "VirtualQuery failed %d\n", GetLastError());
2543 ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
2546 SetLastError(0xdeadbeef);
2547 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, td[i].prot);
2548 ok(ptr == base, "%d: VirtualAlloc failed %d\n", i, GetLastError());
2550 VirtualFree(base, 0, MEM_FREE);
2552 else
2554 ok(!base, "%d: VirtualAlloc should fail\n", i);
2555 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
2560 static void test_CreateFileMapping_protection(void)
2562 static const struct test_data
2564 DWORD prot;
2565 BOOL success;
2566 DWORD prot_after_write;
2567 } td[] =
2569 { 0, FALSE, 0 }, /* 0x00 */
2570 { PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x01 */
2571 { PAGE_READONLY, TRUE, PAGE_READONLY }, /* 0x02 */
2572 { PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x03 */
2573 { PAGE_READWRITE, TRUE, PAGE_READWRITE }, /* 0x04 */
2574 { PAGE_READWRITE | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x05 */
2575 { PAGE_READWRITE | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x06 */
2576 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x07 */
2577 { PAGE_WRITECOPY, TRUE, PAGE_READWRITE }, /* 0x08 */
2578 { PAGE_WRITECOPY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x09 */
2579 { PAGE_WRITECOPY | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0a */
2580 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0b */
2581 { PAGE_WRITECOPY | PAGE_READWRITE, FALSE, PAGE_NOACCESS }, /* 0x0c */
2582 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x0d */
2583 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0e */
2584 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x0f */
2586 { PAGE_EXECUTE, FALSE, PAGE_EXECUTE }, /* 0x10 */
2587 { PAGE_EXECUTE_READ, TRUE, PAGE_EXECUTE_READ }, /* 0x20 */
2588 { PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_EXECUTE_READ }, /* 0x30 */
2589 { PAGE_EXECUTE_READWRITE, TRUE, PAGE_EXECUTE_READWRITE }, /* 0x40 */
2590 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x50 */
2591 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0x60 */
2592 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x70 */
2593 { PAGE_EXECUTE_WRITECOPY, TRUE, PAGE_EXECUTE_READWRITE }, /* 0x80 */
2594 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x90 */
2595 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0xa0 */
2596 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0xb0 */
2597 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, FALSE, PAGE_NOACCESS }, /* 0xc0 */
2598 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0xd0 */
2599 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0xe0 */
2600 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS } /* 0xf0 */
2602 char *base, *ptr;
2603 DWORD ret, i, alloc_prot, prot, old_prot;
2604 MEMORY_BASIC_INFORMATION info;
2605 SYSTEM_INFO si;
2606 char temp_path[MAX_PATH];
2607 char file_name[MAX_PATH];
2608 HANDLE hfile, hmap;
2609 BOOL page_exec_supported = TRUE;
2611 GetSystemInfo(&si);
2612 trace("system page size %#x\n", si.dwPageSize);
2614 GetTempPathA(MAX_PATH, temp_path);
2615 GetTempFileNameA(temp_path, "map", 0, file_name);
2617 SetLastError(0xdeadbeef);
2618 hfile = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
2619 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
2620 SetFilePointer(hfile, si.dwPageSize, NULL, FILE_BEGIN);
2621 SetEndOfFile(hfile);
2623 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2625 SetLastError(0xdeadbeef);
2626 hmap = CreateFileMappingW(hfile, NULL, td[i].prot | SEC_COMMIT, 0, si.dwPageSize, NULL);
2628 if (td[i].success)
2630 if (!hmap)
2632 trace("%d: CreateFileMapping(%04x) failed: %d\n", i, td[i].prot, GetLastError());
2633 /* NT4 and win2k don't support EXEC on file mappings */
2634 if (td[i].prot == PAGE_EXECUTE_READ || td[i].prot == PAGE_EXECUTE_READWRITE)
2636 page_exec_supported = FALSE;
2637 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i);
2638 continue;
2640 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
2641 if (td[i].prot == PAGE_EXECUTE_WRITECOPY)
2643 page_exec_supported = FALSE;
2644 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
2645 continue;
2648 ok(hmap != 0, "%d: CreateFileMapping(%04x) error %d\n", i, td[i].prot, GetLastError());
2650 base = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0);
2651 ok(base != NULL, "%d: MapViewOfFile failed %d\n", i, GetLastError());
2653 SetLastError(0xdeadbeef);
2654 ret = VirtualQuery(base, &info, sizeof(info));
2655 ok(ret, "VirtualQuery failed %d\n", GetLastError());
2656 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
2657 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
2658 ok(info.Protect == PAGE_READONLY, "%d: got %#x != expected PAGE_READONLY\n", i, info.Protect);
2659 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
2660 ok(info.AllocationProtect == PAGE_READONLY, "%d: %#x != PAGE_READONLY\n", i, info.AllocationProtect);
2661 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
2662 ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
2664 if (is_mem_writable(info.Protect))
2666 base[0] = 0xfe;
2668 SetLastError(0xdeadbeef);
2669 ret = VirtualQuery(base, &info, sizeof(info));
2670 ok(ret, "VirtualQuery failed %d\n", GetLastError());
2671 ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
2674 SetLastError(0xdeadbeef);
2675 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, td[i].prot);
2676 ok(!ptr, "%d: VirtualAlloc(%02x) should fail\n", i, td[i].prot);
2677 /* FIXME: remove once Wine is fixed */
2678 if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
2679 todo_wine
2680 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
2681 else
2682 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
2684 SetLastError(0xdeadbeef);
2685 ret = VirtualProtect(base, si.dwPageSize, td[i].prot, &old_prot);
2686 if (td[i].prot == PAGE_READONLY || td[i].prot == PAGE_WRITECOPY)
2687 ok(ret, "%d: VirtualProtect(%02x) error %d\n", i, td[i].prot, GetLastError());
2688 else
2690 ok(!ret, "%d: VirtualProtect(%02x) should fail\n", i, td[i].prot);
2691 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
2694 UnmapViewOfFile(base);
2695 CloseHandle(hmap);
2697 else
2699 ok(!hmap, "%d: CreateFileMapping should fail\n", i);
2700 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
2704 if (page_exec_supported) alloc_prot = PAGE_EXECUTE_READWRITE;
2705 else alloc_prot = PAGE_READWRITE;
2706 SetLastError(0xdeadbeef);
2707 hmap = CreateFileMappingW(hfile, NULL, alloc_prot, 0, si.dwPageSize, NULL);
2708 ok(hmap != 0, "%d: CreateFileMapping error %d\n", i, GetLastError());
2710 SetLastError(0xdeadbeef);
2711 base = MapViewOfFile(hmap, FILE_MAP_READ | FILE_MAP_WRITE | (page_exec_supported ? FILE_MAP_EXECUTE : 0), 0, 0, 0);
2712 ok(base != NULL, "MapViewOfFile failed %d\n", GetLastError());
2714 old_prot = 0xdeadbeef;
2715 SetLastError(0xdeadbeef);
2716 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
2717 ok(ret, "VirtualProtect error %d\n", GetLastError());
2718 ok(old_prot == alloc_prot, "got %#x != expected %#x\n", old_prot, alloc_prot);
2720 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2722 SetLastError(0xdeadbeef);
2723 ret = VirtualQuery(base, &info, sizeof(info));
2724 ok(ret, "VirtualQuery failed %d\n", GetLastError());
2725 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
2726 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
2727 ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect);
2728 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
2729 ok(info.AllocationProtect == alloc_prot, "%d: %#x != %#x\n", i, info.AllocationProtect, alloc_prot);
2730 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
2731 ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
2733 old_prot = 0xdeadbeef;
2734 SetLastError(0xdeadbeef);
2735 ret = VirtualProtect(base, si.dwPageSize, td[i].prot, &old_prot);
2736 if (td[i].success || td[i].prot == PAGE_NOACCESS || td[i].prot == PAGE_EXECUTE)
2738 if (!ret)
2740 /* win2k and XP don't support EXEC on file mappings */
2741 if (td[i].prot == PAGE_EXECUTE)
2743 ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i);
2744 continue;
2746 /* NT4 and win2k don't support EXEC on file mappings */
2747 if (td[i].prot == PAGE_EXECUTE_READ || td[i].prot == PAGE_EXECUTE_READWRITE)
2749 ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i);
2750 continue;
2752 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
2753 if (td[i].prot == PAGE_EXECUTE_WRITECOPY)
2755 ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
2756 continue;
2760 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
2761 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
2763 prot = td[i].prot;
2764 /* looks strange but Windows doesn't do this for PAGE_WRITECOPY */
2765 if (prot == PAGE_EXECUTE_WRITECOPY) prot = PAGE_EXECUTE_READWRITE;
2767 SetLastError(0xdeadbeef);
2768 ret = VirtualQuery(base, &info, sizeof(info));
2769 ok(ret, "VirtualQuery failed %d\n", GetLastError());
2770 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
2771 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
2772 /* FIXME: remove the condition below once Wine is fixed */
2773 if (td[i].prot == PAGE_EXECUTE_WRITECOPY)
2774 todo_wine ok(info.Protect == prot, "%d: got %#x != expected %#x\n", i, info.Protect, prot);
2775 else
2776 ok(info.Protect == prot, "%d: got %#x != expected %#x\n", i, info.Protect, prot);
2777 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
2778 ok(info.AllocationProtect == alloc_prot, "%d: %#x != %#x\n", i, info.AllocationProtect, alloc_prot);
2779 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
2780 ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
2782 if (is_mem_writable(info.Protect))
2784 base[0] = 0xfe;
2786 SetLastError(0xdeadbeef);
2787 ret = VirtualQuery(base, &info, sizeof(info));
2788 ok(ret, "VirtualQuery failed %d\n", GetLastError());
2789 /* FIXME: remove the condition below once Wine is fixed */
2790 if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
2791 todo_wine ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
2792 else
2793 ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
2796 else
2798 ok(!ret, "%d: VirtualProtect should fail\n", i);
2799 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
2800 continue;
2803 old_prot = 0xdeadbeef;
2804 SetLastError(0xdeadbeef);
2805 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
2806 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
2807 /* FIXME: remove the condition below once Wine is fixed */
2808 if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
2809 todo_wine ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
2810 else
2811 ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
2814 UnmapViewOfFile(base);
2815 CloseHandle(hmap);
2817 CloseHandle(hfile);
2818 DeleteFileA(file_name);
2821 #define ACCESS_READ 0x01
2822 #define ACCESS_WRITE 0x02
2823 #define ACCESS_EXECUTE 0x04
2824 #define ACCESS_WRITECOPY 0x08
2826 static DWORD page_prot_to_access(DWORD prot)
2828 switch (prot)
2830 case PAGE_READWRITE:
2831 return ACCESS_READ | ACCESS_WRITE;
2833 case PAGE_EXECUTE:
2834 case PAGE_EXECUTE_READ:
2835 return ACCESS_READ | ACCESS_EXECUTE;
2837 case PAGE_EXECUTE_READWRITE:
2838 return ACCESS_READ | ACCESS_WRITE | ACCESS_WRITECOPY | ACCESS_EXECUTE;
2840 case PAGE_EXECUTE_WRITECOPY:
2841 return ACCESS_READ | ACCESS_WRITECOPY | ACCESS_EXECUTE;
2843 case PAGE_READONLY:
2844 return ACCESS_READ;
2846 case PAGE_WRITECOPY:
2847 return ACCESS_READ;
2849 default:
2850 return 0;
2854 static BOOL is_compatible_protection(DWORD map_prot, DWORD view_prot, DWORD prot)
2856 DWORD map_access, view_access, prot_access;
2858 map_access = page_prot_to_access(map_prot);
2859 view_access = page_prot_to_access(view_prot);
2860 prot_access = page_prot_to_access(prot);
2862 if (view_access == prot_access) return TRUE;
2863 if (!view_access) return FALSE;
2865 if ((view_access & prot_access) != prot_access) return FALSE;
2866 if ((map_access & prot_access) == prot_access) return TRUE;
2868 return FALSE;
2871 static DWORD map_prot_to_access(DWORD prot)
2873 switch (prot)
2875 case PAGE_READWRITE:
2876 case PAGE_EXECUTE_READWRITE:
2877 return SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT | SECTION_QUERY;
2878 case PAGE_READONLY:
2879 case PAGE_WRITECOPY:
2880 case PAGE_EXECUTE:
2881 case PAGE_EXECUTE_READ:
2882 case PAGE_EXECUTE_WRITECOPY:
2883 return SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT | SECTION_QUERY;
2884 default:
2885 return 0;
2889 static BOOL is_compatible_access(DWORD map_prot, DWORD view_prot)
2891 DWORD access = map_prot_to_access(map_prot);
2892 if (!view_prot) view_prot = SECTION_MAP_READ;
2893 return (view_prot & access) == view_prot;
2896 static void *map_view_of_file(HANDLE handle, DWORD access)
2898 NTSTATUS status;
2899 LARGE_INTEGER offset;
2900 SIZE_T count;
2901 ULONG protect;
2902 BOOL exec;
2903 void *addr;
2905 if (!pNtMapViewOfSection) return NULL;
2907 count = 0;
2908 offset.u.LowPart = 0;
2909 offset.u.HighPart = 0;
2911 exec = access & FILE_MAP_EXECUTE;
2912 access &= ~FILE_MAP_EXECUTE;
2914 if (access == FILE_MAP_COPY)
2916 if (exec)
2917 protect = PAGE_EXECUTE_WRITECOPY;
2918 else
2919 protect = PAGE_WRITECOPY;
2921 else if (access & FILE_MAP_WRITE)
2923 if (exec)
2924 protect = PAGE_EXECUTE_READWRITE;
2925 else
2926 protect = PAGE_READWRITE;
2928 else if (access & FILE_MAP_READ)
2930 if (exec)
2931 protect = PAGE_EXECUTE_READ;
2932 else
2933 protect = PAGE_READONLY;
2935 else protect = PAGE_NOACCESS;
2937 addr = NULL;
2938 status = pNtMapViewOfSection(handle, GetCurrentProcess(), &addr, 0, 0, &offset,
2939 &count, 1 /* ViewShare */, 0, protect);
2940 if (status)
2942 /* for simplicity */
2943 SetLastError(ERROR_ACCESS_DENIED);
2944 addr = NULL;
2946 return addr;
2949 static void test_mapping(void)
2951 static const DWORD page_prot[] =
2953 PAGE_NOACCESS, PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY,
2954 PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY
2956 static const struct
2958 DWORD access, prot;
2959 } view[] =
2961 { 0, PAGE_NOACCESS }, /* 0x00 */
2962 { FILE_MAP_COPY, PAGE_WRITECOPY }, /* 0x01 */
2963 { FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x02 */
2964 { FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x03 */
2965 { FILE_MAP_READ, PAGE_READONLY }, /* 0x04 */
2966 { FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x05 */
2967 { FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x06 */
2968 { FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x07 */
2969 { SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x08 */
2970 { SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x09 */
2971 { SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0a */
2972 { SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0b */
2973 { SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_READONLY }, /* 0x0c */
2974 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x0d */
2975 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0e */
2976 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0f */
2977 { FILE_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x20 */
2978 { FILE_MAP_EXECUTE | FILE_MAP_COPY, PAGE_EXECUTE_WRITECOPY }, /* 0x21 */
2979 { FILE_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x22 */
2980 { FILE_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x23 */
2981 { FILE_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x24 */
2982 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x25 */
2983 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x26 */
2984 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x27 */
2985 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x28 */
2986 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x29 */
2987 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2a */
2988 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x2b */
2989 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x2c */
2990 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x2d */
2991 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2e */
2992 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE } /* 0x2f */
2994 void *base, *nt_base, *ptr;
2995 DWORD i, j, k, ret, old_prot, prev_prot;
2996 SYSTEM_INFO si;
2997 char temp_path[MAX_PATH];
2998 char file_name[MAX_PATH];
2999 HANDLE hfile, hmap;
3000 MEMORY_BASIC_INFORMATION info, nt_info;
3002 GetSystemInfo(&si);
3003 trace("system page size %#x\n", si.dwPageSize);
3005 GetTempPathA(MAX_PATH, temp_path);
3006 GetTempFileNameA(temp_path, "map", 0, file_name);
3008 SetLastError(0xdeadbeef);
3009 hfile = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
3010 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
3011 SetFilePointer(hfile, si.dwPageSize, NULL, FILE_BEGIN);
3012 SetEndOfFile(hfile);
3014 for (i = 0; i < sizeof(page_prot)/sizeof(page_prot[0]); i++)
3016 SetLastError(0xdeadbeef);
3017 hmap = CreateFileMappingW(hfile, NULL, page_prot[i] | SEC_COMMIT, 0, si.dwPageSize, NULL);
3019 if (page_prot[i] == PAGE_NOACCESS)
3021 HANDLE hmap2;
3023 ok(!hmap, "CreateFileMapping(PAGE_NOACCESS) should fail\n");
3024 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3026 /* A trick to create a not accessible mapping */
3027 SetLastError(0xdeadbeef);
3028 hmap = CreateFileMappingW(hfile, NULL, PAGE_READWRITE | SEC_COMMIT, 0, si.dwPageSize, NULL);
3029 ok(hmap != 0, "CreateFileMapping(PAGE_READWRITE) error %d\n", GetLastError());
3030 SetLastError(0xdeadbeef);
3031 ret = DuplicateHandle(GetCurrentProcess(), hmap, GetCurrentProcess(), &hmap2, 0, FALSE, 0);
3032 ok(ret, "DuplicateHandle error %d\n", GetLastError());
3033 CloseHandle(hmap);
3034 hmap = hmap2;
3037 if (!hmap)
3039 trace("%d: CreateFileMapping(%04x) failed: %d\n", i, page_prot[i], GetLastError());
3041 /* NT4 and win2k don't support EXEC on file mappings */
3042 if (page_prot[i] == PAGE_EXECUTE_READ || page_prot[i] == PAGE_EXECUTE_READWRITE)
3044 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i);
3045 continue;
3047 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3048 if (page_prot[i] == PAGE_EXECUTE_WRITECOPY)
3050 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
3051 continue;
3055 ok(hmap != 0, "%d: CreateFileMapping(%04x) error %d\n", i, page_prot[i], GetLastError());
3057 for (j = 0; j < sizeof(view)/sizeof(view[0]); j++)
3059 nt_base = map_view_of_file(hmap, view[j].access);
3060 if (nt_base)
3062 SetLastError(0xdeadbeef);
3063 ret = VirtualQuery(nt_base, &nt_info, sizeof(nt_info));
3064 ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
3065 UnmapViewOfFile(nt_base);
3068 SetLastError(0xdeadbeef);
3069 base = MapViewOfFile(hmap, view[j].access, 0, 0, 0);
3071 /* Vista+ supports FILE_MAP_EXECUTE properly, earlier versions don't */
3072 ok(!nt_base == !base ||
3073 broken((view[j].access & FILE_MAP_EXECUTE) && !nt_base != !base),
3074 "%d: (%04x/%04x) NT %p kernel %p\n", j, page_prot[i], view[j].access, nt_base, base);
3076 if (!is_compatible_access(page_prot[i], view[j].access))
3078 ok(!base, "%d: MapViewOfFile(%04x/%04x) should fail\n", j, page_prot[i], view[j].access);
3079 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
3080 continue;
3083 /* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */
3084 if (!base && (view[j].access & FILE_MAP_EXECUTE))
3086 ok(broken(!base), "%d: MapViewOfFile(%04x/%04x) failed %d\n", j, page_prot[i], view[j].access, GetLastError());
3087 continue;
3090 ok(base != NULL, "%d: MapViewOfFile(%04x/%04x) failed %d\n", j, page_prot[i], view[j].access, GetLastError());
3092 SetLastError(0xdeadbeef);
3093 ret = VirtualQuery(base, &info, sizeof(info));
3094 ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
3095 ok(info.BaseAddress == base, "%d: (%04x) got %p, expected %p\n", j, view[j].access, info.BaseAddress, base);
3096 ok(info.RegionSize == si.dwPageSize, "%d: (%04x) got %#lx != expected %#x\n", j, view[j].access, info.RegionSize, si.dwPageSize);
3097 ok(info.Protect == view[j].prot ||
3098 broken(view[j].prot == PAGE_EXECUTE_READ && info.Protect == PAGE_READONLY) || /* win2k */
3099 broken(view[j].prot == PAGE_EXECUTE_READWRITE && info.Protect == PAGE_READWRITE) || /* win2k */
3100 broken(view[j].prot == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
3101 "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.Protect, view[j].prot);
3102 ok(info.AllocationBase == base, "%d: (%04x) got %p, expected %p\n", j, view[j].access, info.AllocationBase, base);
3103 ok(info.AllocationProtect == info.Protect, "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.AllocationProtect, info.Protect);
3104 ok(info.State == MEM_COMMIT, "%d: (%04x) got %#x, expected MEM_COMMIT\n", j, view[j].access, info.State);
3105 ok(info.Type == MEM_MAPPED, "%d: (%04x) got %#x, expected MEM_MAPPED\n", j, view[j].access, info.Type);
3107 if (nt_base && base)
3109 ok(nt_info.RegionSize == info.RegionSize, "%d: (%04x) got %#lx != expected %#lx\n", j, view[j].access, nt_info.RegionSize, info.RegionSize);
3110 ok(nt_info.Protect == info.Protect /* Vista+ */ ||
3111 broken(nt_info.AllocationProtect == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
3112 "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.Protect, info.Protect);
3113 ok(nt_info.AllocationProtect == info.AllocationProtect /* Vista+ */ ||
3114 broken(nt_info.AllocationProtect == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
3115 "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.AllocationProtect, info.AllocationProtect);
3116 ok(nt_info.State == info.State, "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.State, info.State);
3117 ok(nt_info.Type == info.Type, "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.Type, info.Type);
3120 prev_prot = info.Protect;
3122 for (k = 0; k < sizeof(page_prot)/sizeof(page_prot[0]); k++)
3124 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3125 SetLastError(0xdeadbeef);
3126 old_prot = 0xdeadbeef;
3127 ret = VirtualProtect(base, si.dwPageSize, page_prot[k], &old_prot);
3128 if (is_compatible_protection(page_prot[i], view[j].prot, page_prot[k]))
3130 /* win2k and XP don't support EXEC on file mappings */
3131 if (!ret && page_prot[k] == PAGE_EXECUTE)
3133 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3134 continue;
3136 /* NT4 and win2k don't support EXEC on file mappings */
3137 if (!ret && (page_prot[k] == PAGE_EXECUTE_READ || page_prot[k] == PAGE_EXECUTE_READWRITE))
3139 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3140 continue;
3142 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3143 if (!ret && page_prot[k] == PAGE_EXECUTE_WRITECOPY)
3145 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n");
3146 continue;
3148 /* win2k and XP don't support PAGE_EXECUTE_WRITECOPY views properly */
3149 if (!ret && view[j].prot == PAGE_EXECUTE_WRITECOPY)
3151 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY view properly\n");
3152 continue;
3155 ok(ret, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot[i], view[j].prot, page_prot[k]);
3156 ok(old_prot == prev_prot, "got %#x, expected %#x\n", old_prot, prev_prot);
3157 prev_prot = page_prot[k];
3159 else
3161 /* NT4 doesn't fail on incompatible map and view */
3162 if (ret)
3164 ok(broken(ret), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
3165 skip("Incompatible map and view are not properly handled on this platform\n");
3166 break; /* NT4 won't pass remaining tests */
3169 ok(!ret, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
3170 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3174 for (k = 0; k < sizeof(page_prot)/sizeof(page_prot[0]); k++)
3176 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3177 SetLastError(0xdeadbeef);
3178 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, page_prot[k]);
3179 ok(!ptr, "VirtualAlloc(%02x) should fail\n", page_prot[k]);
3180 /* FIXME: remove once Wine is fixed */
3181 if (page_prot[k] == PAGE_WRITECOPY || page_prot[k] == PAGE_EXECUTE_WRITECOPY)
3182 todo_wine
3183 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3184 else
3185 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3188 UnmapViewOfFile(base);
3191 CloseHandle(hmap);
3194 CloseHandle(hfile);
3195 DeleteFileA(file_name);
3198 static void test_shared_memory(BOOL is_child)
3200 HANDLE mapping;
3201 LONG *p;
3203 SetLastError(0xdeadbef);
3204 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_virtual.c");
3205 ok(mapping != 0, "CreateFileMapping error %d\n", GetLastError());
3206 if (is_child)
3207 ok(GetLastError() == ERROR_ALREADY_EXISTS, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3209 SetLastError(0xdeadbef);
3210 p = MapViewOfFile(mapping, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 4096);
3211 ok(p != NULL, "MapViewOfFile error %d\n", GetLastError());
3213 if (is_child)
3215 ok(*p == 0x1a2b3c4d, "expected 0x1a2b3c4d in child, got %#x\n", *p);
3217 else
3219 char **argv;
3220 char cmdline[MAX_PATH];
3221 PROCESS_INFORMATION pi;
3222 STARTUPINFOA si = { sizeof(si) };
3223 DWORD ret;
3225 *p = 0x1a2b3c4d;
3227 winetest_get_mainargs(&argv);
3228 sprintf(cmdline, "\"%s\" virtual sharedmem", argv[0]);
3229 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
3230 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
3231 winetest_wait_child_process(pi.hProcess);
3232 CloseHandle(pi.hThread);
3233 CloseHandle(pi.hProcess);
3236 UnmapViewOfFile(p);
3237 CloseHandle(mapping);
3240 static void test_shared_memory_ro(BOOL is_child, DWORD child_access)
3242 HANDLE mapping;
3243 LONG *p;
3245 SetLastError(0xdeadbef);
3246 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_virtual.c_ro");
3247 ok(mapping != 0, "CreateFileMapping error %d\n", GetLastError());
3248 if (is_child)
3249 ok(GetLastError() == ERROR_ALREADY_EXISTS, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3251 SetLastError(0xdeadbef);
3252 p = MapViewOfFile(mapping, is_child ? child_access : FILE_MAP_READ, 0, 0, 4096);
3253 ok(p != NULL, "MapViewOfFile error %d\n", GetLastError());
3255 if (is_child)
3257 *p = 0xdeadbeef;
3259 else
3261 char **argv;
3262 char cmdline[MAX_PATH];
3263 PROCESS_INFORMATION pi;
3264 STARTUPINFOA si = { sizeof(si) };
3265 DWORD ret;
3267 winetest_get_mainargs(&argv);
3268 sprintf(cmdline, "\"%s\" virtual sharedmemro %x", argv[0], child_access);
3269 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
3270 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
3271 winetest_wait_child_process(pi.hProcess);
3272 CloseHandle(pi.hThread);
3273 CloseHandle(pi.hProcess);
3275 if(child_access & FILE_MAP_WRITE)
3276 ok(*p == 0xdeadbeef, "*p = %x, expected 0xdeadbeef\n", *p);
3277 else
3278 ok(!*p, "*p = %x, expected 0\n", *p);
3281 UnmapViewOfFile(p);
3282 CloseHandle(mapping);
3285 START_TEST(virtual)
3287 int argc;
3288 char **argv;
3289 argc = winetest_get_mainargs( &argv );
3291 if (argc >= 3)
3293 if (!strcmp(argv[2], "sleep"))
3295 Sleep(5000); /* spawned process runs for at most 5 seconds */
3296 return;
3298 if (!strcmp(argv[2], "sharedmem"))
3300 test_shared_memory(TRUE);
3301 return;
3303 if (!strcmp(argv[2], "sharedmemro"))
3305 test_shared_memory_ro(TRUE, strtol(argv[3], NULL, 16));
3306 return;
3308 while (1)
3310 void *mem;
3311 BOOL ret;
3312 mem = VirtualAlloc(NULL, 1<<20, MEM_COMMIT|MEM_RESERVE,
3313 PAGE_EXECUTE_READWRITE);
3314 ok(mem != NULL, "VirtualAlloc failed %u\n", GetLastError());
3315 if (mem == NULL) break;
3316 ret = VirtualFree(mem, 0, MEM_RELEASE);
3317 ok(ret, "VirtualFree failed %u\n", GetLastError());
3318 if (!ret) break;
3320 return;
3323 hkernel32 = GetModuleHandleA("kernel32.dll");
3324 hntdll = GetModuleHandleA("ntdll.dll");
3326 pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
3327 pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
3328 pGetWriteWatch = (void *) GetProcAddress(hkernel32, "GetWriteWatch");
3329 pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch");
3330 pNtAreMappedFilesTheSame = (void *)GetProcAddress( hntdll, "NtAreMappedFilesTheSame" );
3331 pNtMapViewOfSection = (void *)GetProcAddress( hntdll, "NtMapViewOfSection" );
3332 pNtUnmapViewOfSection = (void *)GetProcAddress( hntdll, "NtUnmapViewOfSection" );
3333 pNtCurrentTeb = (void *)GetProcAddress( hntdll, "NtCurrentTeb" );
3334 pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlAddVectoredExceptionHandler" );
3335 pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlRemoveVectoredExceptionHandler" );
3337 test_shared_memory(FALSE);
3338 test_shared_memory_ro(FALSE, FILE_MAP_READ|FILE_MAP_WRITE);
3339 test_shared_memory_ro(FALSE, FILE_MAP_COPY);
3340 test_shared_memory_ro(FALSE, FILE_MAP_COPY|FILE_MAP_WRITE);
3341 test_mapping();
3342 test_CreateFileMapping_protection();
3343 test_VirtualAlloc_protection();
3344 test_VirtualProtect();
3345 test_VirtualAllocEx();
3346 test_VirtualAlloc();
3347 test_MapViewOfFile();
3348 test_NtMapViewOfSection();
3349 test_NtAreMappedFilesTheSame();
3350 test_CreateFileMapping();
3351 test_IsBadReadPtr();
3352 test_IsBadWritePtr();
3353 test_IsBadCodePtr();
3354 test_write_watch();
3355 #ifdef __i386__
3356 test_guard_page();
3357 /* The following tests should be executed as a last step, and in exactly this
3358 * order, since ATL thunk emulation cannot be enabled anymore on Windows. */
3359 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE );
3360 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE );
3361 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION );
3362 #endif