winex11.drv: Map coordinates before calling send_mouse_input.
[wine/zf.git] / dlls / kernel32 / tests / virtual.c
blobe6d9e8621a96953c9bb73c5cece1f16dfe021727
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 SYSTEM_INFO si;
40 static UINT (WINAPI *pGetWriteWatch)(DWORD,LPVOID,SIZE_T,LPVOID*,ULONG_PTR*,ULONG*);
41 static UINT (WINAPI *pResetWriteWatch)(LPVOID,SIZE_T);
42 static NTSTATUS (WINAPI *pNtAreMappedFilesTheSame)(PVOID,PVOID);
43 static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *,
44 const LARGE_INTEGER *, ULONG, ULONG, HANDLE );
45 static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG_PTR, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG);
46 static DWORD (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID);
47 static NTSTATUS (WINAPI *pNtQuerySection)(HANDLE, SECTION_INFORMATION_CLASS, void *, SIZE_T, SIZE_T *);
48 static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG, PVECTORED_EXCEPTION_HANDLER);
49 static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
50 static BOOL (WINAPI *pGetProcessDEPPolicy)(HANDLE, LPDWORD, PBOOL);
51 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
52 static NTSTATUS (WINAPI *pNtProtectVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG *);
54 /* ############################### */
56 static HANDLE create_target_process(const char *arg)
58 char **argv;
59 char cmdline[MAX_PATH];
60 PROCESS_INFORMATION pi;
61 BOOL ret;
62 STARTUPINFOA si = { 0 };
63 si.cb = sizeof(si);
65 winetest_get_mainargs( &argv );
66 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
67 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
68 ok(ret, "error: %u\n", GetLastError());
69 ret = CloseHandle(pi.hThread);
70 ok(ret, "error %u\n", GetLastError());
71 return pi.hProcess;
74 static void test_VirtualAllocEx(void)
76 const unsigned int alloc_size = 1<<15;
77 char *src, *dst;
78 SIZE_T bytes_written = 0, bytes_read = 0, i;
79 void *addr1, *addr2;
80 BOOL b;
81 DWORD old_prot;
82 MEMORY_BASIC_INFORMATION info;
83 HANDLE hProcess;
85 hProcess = create_target_process("sleep");
86 ok(hProcess != NULL, "Can't start process\n");
88 SetLastError(0xdeadbeef);
89 addr1 = VirtualAllocEx(hProcess, NULL, alloc_size, MEM_COMMIT,
90 PAGE_EXECUTE_READWRITE);
91 ok(addr1 != NULL, "VirtualAllocEx error %u\n", GetLastError());
93 src = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE );
94 dst = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE );
95 for (i = 0; i < alloc_size; i++)
96 src[i] = i & 0xff;
98 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
99 ok(b && (bytes_written == alloc_size), "%lu bytes written\n",
100 bytes_written);
101 b = ReadProcessMemory(hProcess, addr1, dst, alloc_size, &bytes_read);
102 ok(b && (bytes_read == alloc_size), "%lu bytes read\n", bytes_read);
103 ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n");
105 /* test invalid source buffers */
107 b = VirtualProtect( src + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot );
108 ok( b, "VirtualProtect failed error %u\n", GetLastError() );
109 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
110 ok( !b, "WriteProcessMemory succeeded\n" );
111 ok( GetLastError() == ERROR_NOACCESS ||
112 GetLastError() == ERROR_PARTIAL_COPY, /* vista */
113 "wrong error %u\n", GetLastError() );
114 ok( bytes_written == 0, "%lu bytes written\n", bytes_written );
115 b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
116 ok( !b, "ReadProcessMemory succeeded\n" );
117 ok( GetLastError() == ERROR_NOACCESS ||
118 GetLastError() == ERROR_PARTIAL_COPY, /* win10 v1607+ */
119 "wrong error %u\n", GetLastError() );
120 if (GetLastError() == ERROR_NOACCESS)
121 ok( bytes_read == 0, "%lu bytes written\n", bytes_read );
123 b = VirtualProtect( src, 0x2000, PAGE_NOACCESS, &old_prot );
124 ok( b, "VirtualProtect failed error %u\n", GetLastError() );
125 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
126 ok( !b, "WriteProcessMemory succeeded\n" );
127 ok( GetLastError() == ERROR_NOACCESS ||
128 GetLastError() == ERROR_PARTIAL_COPY, /* vista */
129 "wrong error %u\n", GetLastError() );
130 ok( bytes_written == 0, "%lu bytes written\n", bytes_written );
131 b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
132 ok( !b, "ReadProcessMemory succeeded\n" );
133 ok( GetLastError() == ERROR_NOACCESS ||
134 GetLastError() == ERROR_PARTIAL_COPY, /* win10 v1607+ */
135 "wrong error %u\n", GetLastError() );
136 if (GetLastError() == ERROR_NOACCESS)
137 ok( bytes_read == 0, "%lu bytes written\n", bytes_read );
139 b = VirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE);
140 ok(b != 0, "VirtualFreeEx, error %u\n", GetLastError());
142 VirtualFree( src, 0, MEM_RELEASE );
143 VirtualFree( dst, 0, MEM_RELEASE );
146 * The following tests parallel those in test_VirtualAlloc()
149 SetLastError(0xdeadbeef);
150 addr1 = VirtualAllocEx(hProcess, 0, 0, MEM_RESERVE, PAGE_NOACCESS);
151 ok(addr1 == NULL, "VirtualAllocEx should fail on zero-sized allocation\n");
152 ok(GetLastError() == ERROR_INVALID_PARAMETER,
153 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
155 addr1 = VirtualAllocEx(hProcess, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
156 ok(addr1 != NULL, "VirtualAllocEx failed\n");
158 /* test a not committed memory */
159 memset(&info, 'q', sizeof(info));
160 ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info), "VirtualQueryEx failed\n");
161 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
162 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
163 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
164 ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
165 ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
166 ok(info.Protect == 0, "%x != PAGE_NOACCESS\n", info.Protect);
167 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
169 SetLastError(0xdeadbeef);
170 ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
171 "VirtualProtectEx should fail on a not committed memory\n");
172 ok(GetLastError() == ERROR_INVALID_ADDRESS,
173 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
175 addr2 = VirtualAllocEx(hProcess, addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS);
176 ok(addr1 == addr2, "VirtualAllocEx failed\n");
178 /* test a committed memory */
179 ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info),
180 "VirtualQueryEx failed\n");
181 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
182 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
183 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
184 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
185 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
186 /* this time NT reports PAGE_NOACCESS as well */
187 ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
188 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
190 /* this should fail, since not the whole range is committed yet */
191 SetLastError(0xdeadbeef);
192 ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
193 "VirtualProtectEx should fail on a not committed memory\n");
194 ok(GetLastError() == ERROR_INVALID_ADDRESS,
195 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
197 old_prot = 0;
198 ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtectEx failed\n");
199 ok(old_prot == PAGE_NOACCESS, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
201 old_prot = 0;
202 ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtectEx failed\n");
203 ok(old_prot == PAGE_READONLY, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
205 ok(!VirtualFreeEx(hProcess, addr1, 0x10000, 0),
206 "VirtualFreeEx should fail with type 0\n");
207 ok(GetLastError() == ERROR_INVALID_PARAMETER,
208 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
210 ok(VirtualFreeEx(hProcess, addr1, 0x10000, MEM_DECOMMIT), "VirtualFreeEx failed\n");
212 /* if the type is MEM_RELEASE, size must be 0 */
213 ok(!VirtualFreeEx(hProcess, addr1, 1, MEM_RELEASE),
214 "VirtualFreeEx should fail\n");
215 ok(GetLastError() == ERROR_INVALID_PARAMETER,
216 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
218 ok(VirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE), "VirtualFreeEx failed\n");
220 TerminateProcess(hProcess, 0);
221 CloseHandle(hProcess);
224 static void test_VirtualAlloc(void)
226 void *addr1, *addr2;
227 DWORD old_prot;
228 MEMORY_BASIC_INFORMATION info;
230 SetLastError(0xdeadbeef);
231 addr1 = VirtualAlloc(0, 0, MEM_RESERVE, PAGE_NOACCESS);
232 ok(addr1 == NULL, "VirtualAlloc should fail on zero-sized allocation\n");
233 ok(GetLastError() == ERROR_INVALID_PARAMETER,
234 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
236 addr1 = VirtualAlloc(0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
237 ok(addr1 != NULL, "VirtualAlloc failed\n");
239 /* test a not committed memory */
240 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
241 "VirtualQuery failed\n");
242 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
243 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
244 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
245 ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
246 ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
247 ok(info.Protect == 0, "%x != PAGE_NOACCESS\n", info.Protect);
248 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
250 SetLastError(0xdeadbeef);
251 ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
252 "VirtualProtect should fail on a not committed memory\n");
253 ok( GetLastError() == ERROR_INVALID_ADDRESS,
254 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
256 addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS);
257 ok(addr1 == addr2, "VirtualAlloc failed\n");
259 /* test a committed memory */
260 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
261 "VirtualQuery failed\n");
262 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
263 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
264 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
265 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
266 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
267 /* this time NT reports PAGE_NOACCESS as well */
268 ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
269 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
271 /* this should fail, since not the whole range is committed yet */
272 SetLastError(0xdeadbeef);
273 ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
274 "VirtualProtect should fail on a not committed memory\n");
275 ok( GetLastError() == ERROR_INVALID_ADDRESS,
276 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
278 ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtect failed\n");
279 ok(old_prot == PAGE_NOACCESS,
280 "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
282 ok(VirtualProtect(addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtect failed\n");
283 ok(old_prot == PAGE_READONLY,
284 "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
286 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
287 "VirtualQuery failed\n");
288 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
289 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
290 ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
291 memset( addr1, 0x55, 20 );
292 ok( *(DWORD *)addr1 == 0x55555555, "wrong data %x\n", *(DWORD *)addr1 );
294 addr2 = VirtualAlloc( addr1, 0x1000, MEM_RESET, PAGE_NOACCESS );
295 ok( addr2 == addr1, "VirtualAlloc failed err %u\n", GetLastError() );
296 ok( *(DWORD *)addr1 == 0x55555555 || *(DWORD *)addr1 == 0, "wrong data %x\n", *(DWORD *)addr1 );
297 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
298 "VirtualQuery failed\n");
299 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
300 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
301 ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
303 addr2 = VirtualAlloc( (char *)addr1 + 0x1000, 0x1000, MEM_RESET, PAGE_NOACCESS );
304 ok( (char *)addr2 == (char *)addr1 + 0x1000, "VirtualAlloc failed\n" );
306 ok(VirtualQuery(addr2, &info, sizeof(info)) == sizeof(info),
307 "VirtualQuery failed\n");
308 ok(info.RegionSize == 0xf000, "%lx != 0xf000\n", info.RegionSize);
309 ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
310 ok(info.Protect == 0, "%x != 0\n", info.Protect);
312 addr2 = VirtualAlloc( (char *)addr1 + 0xf000, 0x2000, MEM_RESET, PAGE_NOACCESS );
313 ok( !addr2, "VirtualAlloc failed\n" );
314 ok( GetLastError() == ERROR_INVALID_ADDRESS, "wrong error %u\n", GetLastError() );
316 /* invalid protection values */
317 SetLastError(0xdeadbeef);
318 addr2 = VirtualAlloc(NULL, 0x1000, MEM_RESERVE, 0);
319 ok(!addr2, "VirtualAlloc succeeded\n");
320 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
322 SetLastError(0xdeadbeef);
323 addr2 = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, 0);
324 ok(!addr2, "VirtualAlloc succeeded\n");
325 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
327 SetLastError(0xdeadbeef);
328 addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_READONLY | PAGE_EXECUTE);
329 ok(!addr2, "VirtualAlloc succeeded\n");
330 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
332 SetLastError(0xdeadbeef);
333 ok(!VirtualProtect(addr1, 0x1000, PAGE_READWRITE | PAGE_EXECUTE_WRITECOPY, &old_prot),
334 "VirtualProtect succeeded\n");
335 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
337 SetLastError(0xdeadbeef);
338 ok(!VirtualProtect(addr1, 0x1000, 0, &old_prot), "VirtualProtect succeeded\n");
339 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
341 SetLastError(0xdeadbeef);
342 ok(!VirtualFree(addr1, 0x10000, 0), "VirtualFree should fail with type 0\n");
343 ok(GetLastError() == ERROR_INVALID_PARAMETER,
344 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
346 SetLastError(0xdeadbeef);
347 ok(!VirtualFree(addr1, 0, MEM_FREE), "VirtualFree should fail with type MEM_FREE\n");
348 ok(GetLastError() == ERROR_INVALID_PARAMETER,
349 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
351 ok(VirtualFree(addr1, 0x10000, MEM_DECOMMIT), "VirtualFree failed\n");
353 /* if the type is MEM_RELEASE, size must be 0 */
354 ok(!VirtualFree(addr1, 1, MEM_RELEASE), "VirtualFree should fail\n");
355 ok(GetLastError() == ERROR_INVALID_PARAMETER,
356 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
358 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
360 /* PAGE_NOCACHE cannot be set per page in recent Windows */
361 addr1 = VirtualAlloc( NULL, 0x2000, MEM_COMMIT, PAGE_READWRITE | PAGE_NOCACHE );
362 ok( addr1 != NULL, "VirtualAlloc failed\n");
363 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n");
364 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
365 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
366 ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE),
367 "wrong protect %x\n", info.AllocationProtect);
368 ok(info.RegionSize == 0x2000, "wrong size %lx\n", info.RegionSize);
369 ok(info.State == MEM_COMMIT, "wrong state %x\n", info.State);
370 ok(info.Protect == (PAGE_READWRITE | PAGE_NOCACHE), "wrong protect %x\n", info.Protect);
371 ok(info.Type == MEM_PRIVATE, "wrong type %x\n", info.Type);
373 ok(VirtualProtect(addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtect failed\n");
374 ok( old_prot == (PAGE_READWRITE | PAGE_NOCACHE), "wrong protect %x\n", old_prot );
375 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n");
376 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
377 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
378 ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE),
379 "wrong protect %x\n", info.AllocationProtect);
380 ok(info.RegionSize == 0x2000 || broken(info.RegionSize == 0x1000),
381 "wrong size %lx\n", info.RegionSize);
382 ok(info.State == MEM_COMMIT, "wrong state %x\n", info.State);
383 ok(info.Protect == (PAGE_READWRITE | PAGE_NOCACHE) || broken(info.Protect == PAGE_READWRITE),
384 "wrong protect %x\n", info.Protect);
385 ok(info.Type == MEM_PRIVATE, "wrong type %x\n", info.Type);
387 ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtect failed\n");
388 ok( old_prot == (PAGE_READWRITE | PAGE_NOCACHE) || broken(old_prot == PAGE_READWRITE),
389 "wrong protect %x\n", old_prot );
390 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n");
391 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
392 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
393 ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE),
394 "wrong protect %x\n", info.AllocationProtect);
395 ok(info.RegionSize == 0x1000, "wrong size %lx\n", info.RegionSize);
396 ok(info.State == MEM_COMMIT, "wrong state %x\n", info.State);
397 ok(info.Protect == (PAGE_READONLY | PAGE_NOCACHE) || broken(info.Protect == PAGE_READONLY),
398 "wrong protect %x\n", info.Protect);
399 ok(info.Type == MEM_PRIVATE, "wrong type %x\n", info.Type);
401 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
403 addr1 = VirtualAlloc( NULL, 0x2000, MEM_COMMIT, PAGE_READWRITE );
404 ok( addr1 != NULL, "VirtualAlloc failed\n");
405 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n");
406 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
407 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
408 ok(info.AllocationProtect == PAGE_READWRITE,
409 "wrong protect %x\n", info.AllocationProtect);
410 ok(info.RegionSize == 0x2000, "wrong size %lx\n", info.RegionSize);
411 ok(info.State == MEM_COMMIT, "wrong state %x\n", info.State);
412 ok(info.Protect == PAGE_READWRITE, "wrong protect %x\n", info.Protect);
413 ok(info.Type == MEM_PRIVATE, "wrong type %x\n", info.Type);
415 ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY | PAGE_NOCACHE, &old_prot), "VirtualProtect failed\n");
416 ok( old_prot == PAGE_READWRITE, "wrong protect %x\n", old_prot );
417 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n");
418 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
419 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
420 ok(info.AllocationProtect == PAGE_READWRITE, "wrong protect %x\n", info.AllocationProtect);
421 ok(info.RegionSize == 0x1000, "wrong size %lx\n", info.RegionSize);
422 ok(info.State == MEM_COMMIT, "wrong state %x\n", info.State);
423 ok(info.Protect == PAGE_READONLY || broken(info.Protect == (PAGE_READONLY | PAGE_NOCACHE)),
424 "wrong protect %x\n", info.Protect);
425 ok(info.Type == MEM_PRIVATE, "wrong type %x\n", info.Type);
427 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
429 /* memory returned by VirtualAlloc should be aligned to 64k */
430 addr1 = VirtualAlloc(0, 0x2000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
431 ok(addr1 != NULL, "VirtualAlloc failed\n");
432 ok(!((ULONG_PTR)addr1 & 0xffff), "returned memory %p is not aligned to 64k\n", addr1);
433 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
434 addr2 = VirtualAlloc(addr1, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
435 ok(addr2 == addr1, "VirtualAlloc returned %p, expected %p\n", addr2, addr1);
437 /* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
438 SetLastError(0xdeadbeef);
439 addr2 = VirtualAlloc(addr1, 0x1000, MEM_RESERVE | MEM_COMMIT | AT_ROUND_TO_PAGE, PAGE_EXECUTE_READWRITE);
440 ok(!addr2, "VirtualAlloc unexpectedly succeeded\n");
441 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
443 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
446 static void test_MapViewOfFile(void)
448 static const char testfile[] = "testfile.xxx";
449 const char *name;
450 HANDLE file, mapping, map2;
451 void *ptr, *ptr2, *addr;
452 SECTION_BASIC_INFORMATION section_info;
453 SECTION_IMAGE_INFORMATION image_info;
454 MEMORY_BASIC_INFORMATION info;
455 BOOL ret;
456 SIZE_T size;
457 NTSTATUS status;
458 SIZE_T info_size;
459 LARGE_INTEGER map_size;
461 SetLastError(0xdeadbeef);
462 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
463 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
464 SetFilePointer( file, 12288, NULL, FILE_BEGIN );
465 SetEndOfFile( file );
467 /* read/write mapping */
469 SetLastError(0xdeadbeef);
470 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
471 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
473 SetLastError(0xdeadbeef);
474 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
475 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
476 UnmapViewOfFile( ptr );
478 SetLastError(0xdeadbeef);
479 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
480 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
481 UnmapViewOfFile( ptr );
483 SetLastError(0xdeadbeef);
484 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
485 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
486 UnmapViewOfFile( ptr );
488 SetLastError(0xdeadbeef);
489 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
490 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
491 UnmapViewOfFile( ptr );
493 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
494 FILE_MAP_READ|FILE_MAP_WRITE, FALSE, 0 );
495 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
496 ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
497 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
498 UnmapViewOfFile( ptr );
499 CloseHandle( map2 );
501 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
502 FILE_MAP_READ, FALSE, 0 );
503 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
504 SetLastError(0xdeadbeef);
505 ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
506 ok( !ptr, "MapViewOfFile succeeded\n" );
507 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
508 CloseHandle( map2 );
509 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2, 0, FALSE, 0 );
510 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
511 SetLastError(0xdeadbeef);
512 ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
513 ok( !ptr, "MapViewOfFile succeeded\n" );
514 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
515 CloseHandle( map2 );
516 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
517 FILE_MAP_READ, FALSE, 0 );
518 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
519 ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
520 ok( ptr != NULL, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
522 UnmapViewOfFile( ptr );
523 CloseHandle( map2 );
524 CloseHandle( mapping );
526 /* read-only mapping */
528 SetLastError(0xdeadbeef);
529 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
530 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
532 SetLastError(0xdeadbeef);
533 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
534 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
535 UnmapViewOfFile( ptr );
537 SetLastError(0xdeadbeef);
538 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
539 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
540 UnmapViewOfFile( ptr );
542 SetLastError(0xdeadbeef);
543 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
544 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
545 UnmapViewOfFile( ptr );
547 SetLastError(0xdeadbeef);
548 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
549 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
550 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
551 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
552 CloseHandle( mapping );
554 /* copy-on-write mapping */
556 SetLastError(0xdeadbeef);
557 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
558 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
560 SetLastError(0xdeadbeef);
561 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
562 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
563 UnmapViewOfFile( ptr );
565 SetLastError(0xdeadbeef);
566 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
567 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
568 UnmapViewOfFile( ptr );
570 SetLastError(0xdeadbeef);
571 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
572 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
573 UnmapViewOfFile( ptr );
575 SetLastError(0xdeadbeef);
576 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
577 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
578 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
579 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
580 CloseHandle( mapping );
582 /* no access mapping */
584 SetLastError(0xdeadbeef);
585 mapping = CreateFileMappingA( file, NULL, PAGE_NOACCESS, 0, 4096, NULL );
586 ok( !mapping, "CreateFileMappingA succeeded\n" );
587 ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
588 CloseHandle( file );
590 /* now try read-only file */
592 SetLastError(0xdeadbeef);
593 file = CreateFileA( testfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
594 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
596 SetLastError(0xdeadbeef);
597 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
598 ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
599 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
600 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
602 SetLastError(0xdeadbeef);
603 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
604 ok( mapping != 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
605 CloseHandle( mapping );
607 SetLastError(0xdeadbeef);
608 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
609 ok( mapping != 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
610 CloseHandle( mapping );
611 CloseHandle( file );
613 /* now try no access file */
615 SetLastError(0xdeadbeef);
616 file = CreateFileA( testfile, 0, 0, NULL, OPEN_EXISTING, 0, 0 );
617 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
619 SetLastError(0xdeadbeef);
620 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
621 ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
622 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
623 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
625 SetLastError(0xdeadbeef);
626 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
627 ok( !mapping, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
628 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
629 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
631 SetLastError(0xdeadbeef);
632 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
633 ok( !mapping, "CreateFileMapping PAGE_READONLY succeeded\n" );
634 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
635 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
637 CloseHandle( file );
638 DeleteFileA( testfile );
640 SetLastError(0xdeadbeef);
641 name = "Local\\Foo";
642 file = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4090, name );
643 /* nt4 doesn't have Local\\ */
644 if (!file && GetLastError() == ERROR_PATH_NOT_FOUND)
646 name = "Foo";
647 file = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4090, name );
649 ok( file != 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
651 SetLastError(0xdeadbeef);
652 mapping = OpenFileMappingA( FILE_MAP_READ, FALSE, name );
653 ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
654 SetLastError(0xdeadbeef);
655 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
656 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
657 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
658 SetLastError(0xdeadbeef);
659 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
660 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
661 SetLastError(0xdeadbeef);
662 size = VirtualQuery( ptr, &info, sizeof(info) );
663 ok( size == sizeof(info),
664 "VirtualQuery error %u\n", GetLastError() );
665 ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
666 ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
667 ok( info.AllocationProtect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.AllocationProtect );
668 ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
669 ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
670 ok( info.Protect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.Protect );
671 UnmapViewOfFile( ptr );
672 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
673 sizeof(section_info), &info_size );
674 ok( status == STATUS_ACCESS_DENIED, "NtQuerySection failed err %x\n", status );
675 CloseHandle( mapping );
676 mapping = OpenFileMappingA( FILE_MAP_READ | SECTION_QUERY, FALSE, name );
677 ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
678 info_size = (SIZE_T)0xdeadbeef << 16;
679 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
680 sizeof(section_info), &info_size );
681 ok( !status, "NtQuerySection failed err %x\n", status );
682 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %lu\n", info_size );
683 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
684 section_info.Attributes );
685 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
686 ok( section_info.Size.QuadPart == info.RegionSize, "NtQuerySection wrong size %x%08x / %08lx\n",
687 section_info.Size.u.HighPart, section_info.Size.u.LowPart, info.RegionSize );
688 CloseHandle( mapping );
690 SetLastError(0xdeadbeef);
691 mapping = OpenFileMappingA( FILE_MAP_WRITE, FALSE, name );
692 ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
693 SetLastError(0xdeadbeef);
694 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
695 ok( !ptr, "MapViewOfFile succeeded\n" );
696 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
697 SetLastError(0xdeadbeef);
698 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
699 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
700 SetLastError(0xdeadbeef);
701 size = VirtualQuery( ptr, &info, sizeof(info) );
702 ok( size == sizeof(info),
703 "VirtualQuery error %u\n", GetLastError() );
704 ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
705 ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
706 ok( info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect );
707 ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
708 ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
709 ok( info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect );
710 UnmapViewOfFile( ptr );
711 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
712 sizeof(section_info), &info_size );
713 ok( status == STATUS_ACCESS_DENIED, "NtQuerySection failed err %x\n", status );
714 CloseHandle( mapping );
716 mapping = OpenFileMappingA( FILE_MAP_WRITE | SECTION_QUERY, FALSE, name );
717 ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
718 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
719 sizeof(section_info), &info_size );
720 ok( !status, "NtQuerySection failed err %x\n", status );
721 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %lu\n", info_size );
722 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
723 section_info.Attributes );
724 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
725 ok( section_info.Size.QuadPart == info.RegionSize, "NtQuerySection wrong size %x%08x / %08lx\n",
726 section_info.Size.u.HighPart, section_info.Size.u.LowPart, info.RegionSize );
727 CloseHandle( mapping );
729 CloseHandle( file );
731 /* read/write mapping with SEC_RESERVE */
732 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_RESERVE, 0, MAPPING_SIZE, NULL);
733 ok(mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError());
734 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
735 sizeof(section_info), NULL );
736 ok( !status, "NtQuerySection failed err %x\n", status );
737 ok( section_info.Attributes == SEC_RESERVE, "NtQuerySection wrong attr %08x\n",
738 section_info.Attributes );
739 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
740 ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %x%08x / %08x\n",
741 section_info.Size.u.HighPart, section_info.Size.u.LowPart, MAPPING_SIZE );
743 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
744 ok(ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
746 ptr2 = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
747 ok( ptr2 != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
748 ok( ptr != ptr2, "MapViewOfFile returned same pointer\n" );
750 ret = VirtualQuery(ptr, &info, sizeof(info));
751 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
752 ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
753 ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
754 ok(info.RegionSize == MAPPING_SIZE, "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE, info.RegionSize);
755 ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
756 ok(info.AllocationProtect == PAGE_READWRITE,
757 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
758 ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
759 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
761 ret = VirtualQuery(ptr2, &info, sizeof(info));
762 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
763 ok(info.BaseAddress == ptr2,
764 "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
765 ok(info.AllocationBase == ptr2,
766 "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
767 ok(info.AllocationProtect == PAGE_READWRITE,
768 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
769 ok(info.RegionSize == MAPPING_SIZE,
770 "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE, info.RegionSize);
771 ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
772 ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
773 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
775 ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY);
776 ok(ptr != NULL, "VirtualAlloc failed with error %d\n", GetLastError());
778 ret = VirtualQuery(ptr, &info, sizeof(info));
779 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
780 ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
781 ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
782 ok(info.RegionSize == 0x10000, "RegionSize should have been 0x10000 but was 0x%lx\n", info.RegionSize);
783 ok(info.State == MEM_COMMIT, "State should have been MEM_COMMIT instead of 0x%x\n", info.State);
784 ok(info.Protect == PAGE_READONLY, "Protect should have been PAGE_READONLY instead of 0x%x\n", info.Protect);
785 ok(info.AllocationProtect == PAGE_READWRITE,
786 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
787 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
789 /* shows that the VirtualAlloc above affects the mapping, not just the
790 * virtual memory in this process - it also affects all other processes
791 * with a view of the mapping, but that isn't tested here */
792 ret = VirtualQuery(ptr2, &info, sizeof(info));
793 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
794 ok(info.BaseAddress == ptr2,
795 "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
796 ok(info.AllocationBase == ptr2,
797 "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
798 ok(info.AllocationProtect == PAGE_READWRITE,
799 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
800 ok(info.RegionSize == 0x10000,
801 "RegionSize should have been 0x10000 but was 0x%lx\n", info.RegionSize);
802 ok(info.State == MEM_COMMIT,
803 "State should have been MEM_COMMIT instead of 0x%x\n", info.State);
804 ok(info.Protect == PAGE_READWRITE,
805 "Protect should have been PAGE_READWRITE instead of 0x%x\n", info.Protect);
806 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
808 addr = VirtualAlloc( ptr, MAPPING_SIZE, MEM_RESET, PAGE_READONLY );
809 ok( addr == ptr, "VirtualAlloc failed with error %u\n", GetLastError() );
811 ret = VirtualFree( ptr, 0x10000, MEM_DECOMMIT );
812 ok( !ret, "VirtualFree succeeded\n" );
813 ok( GetLastError() == ERROR_INVALID_PARAMETER, "VirtualFree failed with %u\n", GetLastError() );
815 ret = UnmapViewOfFile(ptr2);
816 ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
817 ret = UnmapViewOfFile(ptr);
818 ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
819 CloseHandle(mapping);
821 /* same thing with SEC_COMMIT */
822 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, MAPPING_SIZE, NULL);
823 ok(mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError());
824 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
825 sizeof(section_info), NULL );
826 ok( !status, "NtQuerySection failed err %x\n", status );
827 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
828 section_info.Attributes );
829 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
830 ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %x%08x / %08x\n",
831 section_info.Size.u.HighPart, section_info.Size.u.LowPart, MAPPING_SIZE );
833 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
834 ok(ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
836 ret = VirtualQuery(ptr, &info, sizeof(info));
837 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
838 ok(info.BaseAddress == ptr, "wrong BaseAddress %p/%p\n", ptr, info.BaseAddress);
839 ok(info.AllocationBase == ptr, "wrong AllocationBase %p/%p\n", ptr, info.AllocationBase);
840 ok(info.RegionSize == MAPPING_SIZE, "wrong RegionSize 0x%lx\n", info.RegionSize);
841 ok(info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State);
842 ok(info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect 0x%x\n", info.AllocationProtect);
843 ok(info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect);
844 ok(info.Type == MEM_MAPPED, "wrong Type 0x%x\n", info.Type);
846 ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY);
847 ok(ptr != NULL, "VirtualAlloc failed with error %d\n", GetLastError());
849 ret = VirtualQuery(ptr, &info, sizeof(info));
850 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
851 ok(info.BaseAddress == ptr, "wrong BaseAddress %p/%p\n", ptr, info.BaseAddress);
852 ok(info.AllocationBase == ptr, "wrong AllocationBase %p/%p\n", ptr, info.AllocationBase);
853 ok(info.RegionSize == 0x10000, "wrong RegionSize 0x%lx\n", info.RegionSize);
854 ok(info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State);
855 ok(info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect 0x%x\n", info.AllocationProtect);
856 ok(info.Protect == PAGE_READONLY, "wrong Protect 0x%x\n", info.Protect);
857 ok(info.Type == MEM_MAPPED, "wrong Type 0x%x\n", info.Type);
859 addr = VirtualAlloc( ptr, MAPPING_SIZE, MEM_RESET, PAGE_READONLY );
860 ok( addr == ptr, "VirtualAlloc failed with error %u\n", GetLastError() );
862 ret = VirtualFree( ptr, 0x10000, MEM_DECOMMIT );
863 ok( !ret, "VirtualFree succeeded\n" );
864 ok( GetLastError() == ERROR_INVALID_PARAMETER, "VirtualFree failed with %u\n", GetLastError() );
866 ret = UnmapViewOfFile(ptr);
867 ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
868 CloseHandle(mapping);
870 /* same thing with SEC_NOCACHE (only supported on recent Windows versions) */
871 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT | SEC_NOCACHE,
872 0, MAPPING_SIZE, NULL);
873 ok(mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError());
874 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
875 sizeof(section_info), NULL );
876 ok( !status, "NtQuerySection failed err %x\n", status );
877 ok( section_info.Attributes == (SEC_COMMIT | SEC_NOCACHE) ||
878 broken(section_info.Attributes == SEC_COMMIT),
879 "NtQuerySection wrong attr %08x\n", section_info.Attributes );
880 if (section_info.Attributes & SEC_NOCACHE)
882 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
883 ok(ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
885 ret = VirtualQuery(ptr, &info, sizeof(info));
886 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
887 ok(info.BaseAddress == ptr, "wrong BaseAddress %p/%p\n", ptr, info.BaseAddress);
888 ok(info.AllocationBase == ptr, "wrong AllocationBase %p/%p\n", ptr, info.AllocationBase);
889 ok(info.RegionSize == MAPPING_SIZE, "wrong RegionSize 0x%lx\n", info.RegionSize);
890 ok(info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State);
891 ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE),
892 "wrong AllocationProtect 0x%x\n", info.AllocationProtect);
893 ok(info.Protect == (PAGE_READWRITE | PAGE_NOCACHE), "wrong Protect 0x%x\n", info.Protect);
894 ok(info.Type == MEM_MAPPED, "wrong Type 0x%x\n", info.Type);
896 ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY);
897 ok(ptr != NULL, "VirtualAlloc failed with error %d\n", GetLastError());
899 ret = VirtualQuery(ptr, &info, sizeof(info));
900 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
901 ok(info.BaseAddress == ptr, "wrong BaseAddress %p/%p\n", ptr, info.BaseAddress);
902 ok(info.AllocationBase == ptr, "wrong AllocationBase %p/%p\n", ptr, info.AllocationBase);
903 ok(info.RegionSize == 0x10000, "wrong RegionSize 0x%lx\n", info.RegionSize);
904 ok(info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State);
905 ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE),
906 "wrong AllocationProtect 0x%x\n", info.AllocationProtect);
907 ok(info.Protect == (PAGE_READONLY | PAGE_NOCACHE), "wrong Protect 0x%x\n", info.Protect);
908 ok(info.Type == MEM_MAPPED, "wrong Type 0x%x\n", info.Type);
910 ret = UnmapViewOfFile(ptr);
911 ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
913 CloseHandle(mapping);
915 addr = VirtualAlloc(NULL, 0x10000, MEM_COMMIT, PAGE_READONLY );
916 ok( addr != NULL, "VirtualAlloc failed with error %u\n", GetLastError() );
918 SetLastError(0xdeadbeef);
919 ok( !UnmapViewOfFile(addr), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
920 ok( GetLastError() == ERROR_INVALID_ADDRESS,
921 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
922 SetLastError(0xdeadbeef);
923 ok( !UnmapViewOfFile((char *)addr + 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
924 ok( GetLastError() == ERROR_INVALID_ADDRESS,
925 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
926 SetLastError(0xdeadbeef);
927 ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
928 ok( GetLastError() == ERROR_INVALID_ADDRESS,
929 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
931 ok( VirtualFree(addr, 0, MEM_RELEASE), "VirtualFree failed\n" );
933 /* close named mapping handle without unmapping */
934 name = "Foo";
935 SetLastError(0xdeadbeef);
936 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
937 ok( mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
938 SetLastError(0xdeadbeef);
939 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
940 ok( ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError() );
941 SetLastError(0xdeadbeef);
942 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
943 ok( map2 != 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
944 SetLastError(0xdeadbeef);
945 ret = CloseHandle(map2);
946 ok(ret, "CloseHandle error %d\n", GetLastError());
947 SetLastError(0xdeadbeef);
948 ret = CloseHandle(mapping);
949 ok(ret, "CloseHandle error %d\n", GetLastError());
951 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
952 ok( !ret, "memory is not accessible\n" );
954 ret = VirtualQuery(ptr, &info, sizeof(info));
955 ok(ret, "VirtualQuery error %d\n", GetLastError());
956 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
957 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
958 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
959 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
960 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
961 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
962 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
964 SetLastError(0xdeadbeef);
965 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
966 ok( map2 == 0, "OpenFileMappingA succeeded\n" );
967 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %d\n", GetLastError() );
968 if (map2) CloseHandle(map2); /* FIXME: remove once Wine is fixed */
969 SetLastError(0xdeadbeef);
970 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
971 ok( mapping != 0, "CreateFileMappingA failed\n" );
972 ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %d\n", GetLastError() );
973 SetLastError(0xdeadbeef);
974 ret = CloseHandle(mapping);
975 ok(ret, "CloseHandle error %d\n", GetLastError());
977 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
978 ok( !ret, "memory is not accessible\n" );
980 ret = VirtualQuery(ptr, &info, sizeof(info));
981 ok(ret, "VirtualQuery error %d\n", GetLastError());
982 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
983 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
984 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
985 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
986 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
987 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
988 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
990 SetLastError(0xdeadbeef);
991 ret = UnmapViewOfFile(ptr);
992 ok( ret, "UnmapViewOfFile failed with error %d\n", GetLastError() );
994 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
995 ok( ret, "memory is accessible\n" );
997 ret = VirtualQuery(ptr, &info, sizeof(info));
998 ok(ret, "VirtualQuery error %d\n", GetLastError());
999 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
1000 ok(info.Protect == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", info.Protect);
1001 ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase);
1002 ok(info.AllocationProtect == 0, "%#x != 0\n", info.AllocationProtect);
1003 ok(info.State == MEM_FREE, "%#x != MEM_FREE\n", info.State);
1004 ok(info.Type == 0, "%#x != 0\n", info.Type);
1006 SetLastError(0xdeadbeef);
1007 file = CreateFileA(testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1008 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1009 SetFilePointer(file, 4096, NULL, FILE_BEGIN);
1010 SetEndOfFile(file);
1012 SetLastError(0xdeadbeef);
1013 mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
1014 ok( mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
1015 SetLastError(0xdeadbeef);
1016 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
1017 ok( ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError() );
1018 SetLastError(0xdeadbeef);
1019 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
1020 ok( map2 != 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
1021 SetLastError(0xdeadbeef);
1022 ret = CloseHandle(map2);
1023 ok(ret, "CloseHandle error %d\n", GetLastError());
1024 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
1025 sizeof(section_info), &info_size );
1026 ok( !status, "NtQuerySection failed err %x\n", status );
1027 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %lu\n", info_size );
1028 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1029 section_info.Attributes );
1030 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1031 ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %x%08x\n",
1032 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1033 SetLastError(0xdeadbeef);
1034 ret = CloseHandle(mapping);
1035 ok(ret, "CloseHandle error %d\n", GetLastError());
1037 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
1038 ok( !ret, "memory is not accessible\n" );
1040 ret = VirtualQuery(ptr, &info, sizeof(info));
1041 ok(ret, "VirtualQuery error %d\n", GetLastError());
1042 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
1043 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
1044 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
1045 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
1046 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
1047 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
1048 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
1050 SetLastError(0xdeadbeef);
1051 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
1052 ok( map2 == 0, "OpenFileMappingA succeeded\n" );
1053 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %d\n", GetLastError() );
1054 CloseHandle(map2);
1055 SetLastError(0xdeadbeef);
1056 mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
1057 ok( mapping != 0, "CreateFileMappingA failed\n" );
1058 ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %d\n", GetLastError() );
1059 SetLastError(0xdeadbeef);
1060 ret = CloseHandle(mapping);
1061 ok(ret, "CloseHandle error %d\n", GetLastError());
1063 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
1064 ok( !ret, "memory is not accessible\n" );
1066 ret = VirtualQuery(ptr, &info, sizeof(info));
1067 ok(ret, "VirtualQuery error %d\n", GetLastError());
1068 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
1069 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
1070 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
1071 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
1072 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
1073 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
1074 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
1076 SetLastError(0xdeadbeef);
1077 ret = UnmapViewOfFile(ptr);
1078 ok( ret, "UnmapViewOfFile failed with error %d\n", GetLastError() );
1080 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
1081 ok( ret, "memory is accessible\n" );
1083 ret = VirtualQuery(ptr, &info, sizeof(info));
1084 ok(ret, "VirtualQuery error %d\n", GetLastError());
1085 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
1086 ok(info.Protect == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", info.Protect);
1087 ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase);
1088 ok(info.AllocationProtect == 0, "%#x != 0\n", info.AllocationProtect);
1089 ok(info.State == MEM_FREE, "%#x != MEM_FREE\n", info.State);
1090 ok(info.Type == 0, "%#x != 0\n", info.Type);
1092 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 12288, NULL );
1093 ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
1095 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
1096 ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
1098 ret = UnmapViewOfFile( (char *)ptr + 100 );
1099 ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
1101 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
1102 ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
1104 ret = UnmapViewOfFile( (char *)ptr + 4096 );
1105 ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
1107 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
1108 ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
1110 ret = UnmapViewOfFile( (char *)ptr + 4096 + 100 );
1111 ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
1113 CloseHandle(mapping);
1115 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 36, NULL );
1116 ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
1117 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
1118 sizeof(section_info), &info_size );
1119 ok( !status, "NtQuerySection failed err %x\n", status );
1120 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %lu\n", info_size );
1121 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1122 section_info.Attributes );
1123 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1124 ok( section_info.Size.QuadPart == 36, "NtQuerySection wrong size %x%08x\n",
1125 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1126 CloseHandle(mapping);
1128 SetFilePointer(file, 0x3456, NULL, FILE_BEGIN);
1129 SetEndOfFile(file);
1130 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 0, NULL );
1131 ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
1132 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
1133 sizeof(section_info), &info_size );
1134 ok( !status, "NtQuerySection failed err %x\n", status );
1135 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %lu\n", info_size );
1136 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1137 section_info.Attributes );
1138 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1139 ok( section_info.Size.QuadPart == 0x3456, "NtQuerySection wrong size %x%08x\n",
1140 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1141 CloseHandle(mapping);
1143 map_size.QuadPart = 0x3457;
1144 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1145 &map_size, PAGE_READONLY, SEC_COMMIT, file );
1146 ok( status == STATUS_SECTION_TOO_BIG, "NtCreateSection failed %x\n", status );
1147 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1148 &map_size, PAGE_READONLY, SEC_IMAGE, file );
1149 ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection failed %x\n", status );
1150 if (!status) CloseHandle( mapping );
1151 map_size.QuadPart = 0x3452;
1152 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1153 &map_size, PAGE_READONLY, SEC_COMMIT, file );
1154 ok( !status, "NtCreateSection failed %x\n", status );
1155 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info), NULL );
1156 ok( !status, "NtQuerySection failed err %x\n", status );
1157 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1158 section_info.Attributes );
1159 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1160 ok( section_info.Size.QuadPart == 0x3452, "NtQuerySection wrong size %x%08x\n",
1161 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1162 size = map_size.QuadPart;
1163 status = pNtMapViewOfSection( mapping, GetCurrentProcess(), &ptr, 0, 0, NULL,
1164 &size, ViewShare, 0, PAGE_READONLY );
1165 ok( !status, "NtMapViewOfSection failed err %x\n", status );
1166 pNtUnmapViewOfSection( GetCurrentProcess(), ptr );
1167 size = map_size.QuadPart + 1;
1168 status = pNtMapViewOfSection( mapping, GetCurrentProcess(), &ptr, 0, 0, NULL,
1169 &size, ViewShare, 0, PAGE_READONLY );
1170 ok( status == STATUS_INVALID_VIEW_SIZE, "NtMapViewOfSection failed err %x\n", status );
1171 CloseHandle(mapping);
1173 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1174 &map_size, PAGE_READONLY, SEC_COMMIT, 0 );
1175 ok( !status, "NtCreateSection failed %x\n", status );
1176 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info), NULL );
1177 ok( !status, "NtQuerySection failed err %x\n", status );
1178 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
1179 section_info.Attributes );
1180 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1181 ok( section_info.Size.QuadPart == 0x4000, "NtQuerySection wrong size %x%08x\n",
1182 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1183 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info)-1, NULL );
1184 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQuerySection failed err %x\n", status );
1185 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info)+1, NULL );
1186 ok( !status, "NtQuerySection failed err %x\n", status );
1187 status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info)-1, NULL );
1188 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQuerySection failed err %x\n", status );
1189 status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info), NULL );
1190 ok( status == STATUS_SECTION_NOT_IMAGE, "NtQuerySection failed err %x\n", status );
1191 status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info)+1, NULL );
1192 ok( status == STATUS_SECTION_NOT_IMAGE, "NtQuerySection failed err %x\n", status );
1193 if (sizeof(SIZE_T) > sizeof(int))
1195 status = pNtQuerySection( mapping, SectionImageInformation, &image_info,
1196 sizeof(image_info) + ((SIZE_T)0x10000000 << 8), NULL );
1197 todo_wine
1198 ok( status == STATUS_ACCESS_VIOLATION, "NtQuerySection wrong err %x\n", status );
1200 CloseHandle(mapping);
1202 SetFilePointer(file, 0, NULL, FILE_BEGIN);
1203 SetEndOfFile(file);
1204 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1205 NULL, PAGE_READONLY, SEC_COMMIT, file );
1206 ok( status == STATUS_MAPPED_FILE_SIZE_ZERO, "NtCreateSection failed %x\n", status );
1207 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1208 NULL, PAGE_READONLY, SEC_IMAGE, file );
1209 ok( status == STATUS_INVALID_FILE_FOR_SECTION, "NtCreateSection failed %x\n", status );
1211 CloseHandle(file);
1212 DeleteFileA(testfile);
1216 static void test_NtAreMappedFilesTheSame(void)
1218 static const char testfile[] = "testfile.xxx";
1219 HANDLE file, file2, mapping, map2;
1220 void *ptr, *ptr2;
1221 NTSTATUS status;
1222 char path[MAX_PATH];
1224 if (!pNtAreMappedFilesTheSame)
1226 win_skip( "NtAreMappedFilesTheSame not available\n" );
1227 return;
1230 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
1231 NULL, CREATE_ALWAYS, 0, 0 );
1232 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1233 SetFilePointer( file, 4096, NULL, FILE_BEGIN );
1234 SetEndOfFile( file );
1236 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
1237 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1239 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1240 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1242 file2 = CreateFileA( testfile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1243 NULL, OPEN_EXISTING, 0, 0 );
1244 ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1246 map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY, 0, 4096, NULL );
1247 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1248 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
1249 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1250 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1251 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1252 UnmapViewOfFile( ptr2 );
1254 ptr2 = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1255 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1256 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1257 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1258 UnmapViewOfFile( ptr2 );
1259 CloseHandle( map2 );
1261 map2 = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
1262 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1263 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
1264 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1265 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1266 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1267 UnmapViewOfFile( ptr2 );
1268 CloseHandle( map2 );
1269 CloseHandle( file2 );
1271 status = pNtAreMappedFilesTheSame( ptr, ptr );
1272 ok( status == STATUS_SUCCESS || broken(status == STATUS_NOT_SAME_DEVICE),
1273 "NtAreMappedFilesTheSame returned %x\n", status );
1275 status = pNtAreMappedFilesTheSame( ptr, (char *)ptr + 30 );
1276 ok( status == STATUS_SUCCESS || broken(status == STATUS_NOT_SAME_DEVICE),
1277 "NtAreMappedFilesTheSame returned %x\n", status );
1279 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1280 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1282 status = pNtAreMappedFilesTheSame( ptr, (void *)0xdeadbeef );
1283 ok( status == STATUS_CONFLICTING_ADDRESSES || status == STATUS_INVALID_ADDRESS,
1284 "NtAreMappedFilesTheSame returned %x\n", status );
1286 status = pNtAreMappedFilesTheSame( ptr, NULL );
1287 ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
1289 status = pNtAreMappedFilesTheSame( ptr, (void *)GetProcessHeap() );
1290 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
1292 status = pNtAreMappedFilesTheSame( NULL, NULL );
1293 ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
1295 ptr2 = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE );
1296 ok( ptr2 != NULL, "VirtualAlloc error %u\n", GetLastError() );
1297 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1298 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
1299 VirtualFree( ptr2, 0, MEM_RELEASE );
1301 UnmapViewOfFile( ptr );
1302 CloseHandle( mapping );
1303 CloseHandle( file );
1305 status = pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
1306 GetModuleHandleA("kernel32.dll") );
1307 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1308 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1309 GetModuleHandleA("kernel32.dll") );
1310 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1311 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1312 (char *)GetModuleHandleA("kernel32.dll") + 4096 );
1313 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1315 GetSystemDirectoryA( path, MAX_PATH );
1316 strcat( path, "\\kernel32.dll" );
1317 file = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
1318 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1320 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
1321 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1322 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1323 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1324 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1325 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1326 UnmapViewOfFile( ptr );
1327 CloseHandle( mapping );
1329 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
1330 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1331 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
1332 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1333 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1334 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1336 file2 = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
1337 ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1338 map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
1339 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1340 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 0 );
1341 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1342 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1343 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1344 UnmapViewOfFile( ptr2 );
1345 CloseHandle( map2 );
1346 CloseHandle( file2 );
1348 UnmapViewOfFile( ptr );
1349 CloseHandle( mapping );
1351 CloseHandle( file );
1352 DeleteFileA( testfile );
1355 static void test_CreateFileMapping(void)
1357 HANDLE handle, handle2, file[3];
1358 char path[MAX_PATH], filename[MAX_PATH];
1359 unsigned int i;
1360 NTSTATUS status;
1362 static const struct { DWORD file, flags, error, attrs; } sec_flag_tests[] =
1364 /* anonymous mapping */
1365 { 0, SEC_RESERVE, 0 }, /* 0 */
1366 { 0, SEC_RESERVE | SEC_NOCACHE, 0 },
1367 { 0, SEC_RESERVE | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER },
1368 { 0, SEC_RESERVE | SEC_WRITECOMBINE, 0 },
1369 { 0, SEC_COMMIT, 0 },
1370 { 0, SEC_COMMIT | SEC_NOCACHE, 0 }, /* 5 */
1371 { 0, SEC_COMMIT | SEC_WRITECOMBINE, 0 },
1372 { 0, SEC_RESERVE | SEC_COMMIT, ERROR_INVALID_PARAMETER },
1373 { 0, SEC_IMAGE, ERROR_BAD_EXE_FORMAT },
1374 { 0, SEC_IMAGE | SEC_RESERVE, ERROR_INVALID_PARAMETER },
1375 { 0, SEC_IMAGE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, /* 10 */
1376 { 0, SEC_NOCACHE, ERROR_INVALID_PARAMETER },
1377 { 0, SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER },
1378 { 0, SEC_WRITECOMBINE, ERROR_INVALID_PARAMETER },
1379 { 0, SEC_FILE, ERROR_INVALID_PARAMETER },
1380 { 0, SEC_FILE | SEC_RESERVE, ERROR_INVALID_PARAMETER }, /* 15 */
1381 { 0, SEC_FILE | SEC_COMMIT, ERROR_INVALID_PARAMETER },
1382 { 0, 0, 0, SEC_COMMIT },
1383 /* normal file */
1384 { 1, SEC_RESERVE, 0, SEC_FILE },
1385 { 1, SEC_RESERVE | SEC_NOCACHE, 0, SEC_FILE | SEC_NOCACHE },
1386 { 1, SEC_RESERVE | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER }, /* 20 */
1387 { 1, SEC_RESERVE | SEC_WRITECOMBINE, 0, SEC_FILE | SEC_WRITECOMBINE },
1388 { 1, SEC_COMMIT, 0, SEC_FILE },
1389 { 1, SEC_COMMIT | SEC_NOCACHE, 0, SEC_FILE | SEC_NOCACHE },
1390 { 1, SEC_COMMIT | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER },
1391 { 1, SEC_COMMIT | SEC_WRITECOMBINE, 0, SEC_FILE | SEC_WRITECOMBINE }, /* 25 */
1392 { 1, SEC_RESERVE | SEC_COMMIT, ERROR_INVALID_PARAMETER },
1393 { 1, SEC_IMAGE, ERROR_BAD_EXE_FORMAT },
1394 { 1, SEC_IMAGE | SEC_RESERVE, ERROR_INVALID_PARAMETER },
1395 { 1, SEC_IMAGE | SEC_COMMIT, ERROR_INVALID_PARAMETER },
1396 { 1, SEC_NOCACHE, ERROR_INVALID_PARAMETER }, /* 30 */
1397 { 1, SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER },
1398 { 1, SEC_WRITECOMBINE, ERROR_INVALID_PARAMETER },
1399 { 1, SEC_FILE, ERROR_INVALID_PARAMETER },
1400 { 1, SEC_FILE | SEC_RESERVE, ERROR_INVALID_PARAMETER },
1401 { 1, SEC_FILE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, /* 35 */
1402 { 1, 0, 0, SEC_FILE },
1403 /* PE image file */
1404 { 2, SEC_IMAGE, 0, SEC_FILE | SEC_IMAGE },
1405 { 2, SEC_IMAGE | SEC_FILE, ERROR_INVALID_PARAMETER },
1406 { 2, SEC_IMAGE | SEC_NOCACHE, 0, SEC_FILE | SEC_IMAGE },
1407 { 2, SEC_IMAGE | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER }, /* 40 */
1408 { 2, SEC_IMAGE | SEC_WRITECOMBINE, ERROR_INVALID_PARAMETER },
1409 { 2, SEC_IMAGE | SEC_RESERVE, ERROR_INVALID_PARAMETER },
1410 { 2, SEC_IMAGE | SEC_COMMIT, ERROR_INVALID_PARAMETER },
1413 /* test case sensitivity */
1415 SetLastError(0xdeadbeef);
1416 handle = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1417 "Wine Test Mapping");
1418 ok( handle != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
1419 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1421 SetLastError(0xdeadbeef);
1422 handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1423 "Wine Test Mapping");
1424 ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
1425 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
1426 CloseHandle( handle2 );
1428 SetLastError(0xdeadbeef);
1429 handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1430 "WINE TEST MAPPING");
1431 ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
1432 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1433 CloseHandle( handle2 );
1435 SetLastError(0xdeadbeef);
1436 handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "Wine Test Mapping");
1437 ok( handle2 != NULL, "OpenFileMapping failed with error %d\n", GetLastError());
1438 CloseHandle( handle2 );
1440 SetLastError(0xdeadbeef);
1441 handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "WINE TEST MAPPING");
1442 ok( !handle2, "OpenFileMapping succeeded\n");
1443 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
1445 CloseHandle( handle );
1447 /* test SEC_* flags */
1449 file[0] = INVALID_HANDLE_VALUE;
1450 GetTempPathA( MAX_PATH, path );
1451 GetTempFileNameA( path, "map", 0, filename );
1453 file[1] = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1454 ok( file[1] != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1455 SetFilePointer( file[1], 0x2000, NULL, FILE_BEGIN );
1456 SetEndOfFile( file[1] );
1458 GetSystemDirectoryA( path, MAX_PATH );
1459 strcat( path, "\\kernel32.dll" );
1460 file[2] = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
1461 ok( file[2] != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1463 for (i = 0; i < ARRAY_SIZE(sec_flag_tests); i++)
1465 DWORD flags = sec_flag_tests[i].flags;
1466 DWORD perm = sec_flag_tests[i].file == 2 ? PAGE_READONLY : PAGE_READWRITE;
1467 SetLastError( 0xdeadbeef );
1468 handle = CreateFileMappingA( file[sec_flag_tests[i].file], NULL,
1469 flags | perm, 0, 0x1000, "Wine Test Mapping" );
1470 if (sec_flag_tests[i].error)
1472 ok( !handle, "%u: CreateFileMapping succeeded\n", i );
1473 ok( GetLastError() == sec_flag_tests[i].error, "%u: wrong error %u\n", i, GetLastError());
1475 else
1477 /* SEC_WRITECOMBINE and SEC_IMAGE_NO_EXECUTE not supported on older Windows */
1478 BOOL new_flags = ((flags & SEC_WRITECOMBINE) ||
1479 ((flags & SEC_IMAGE_NO_EXECUTE) == SEC_IMAGE_NO_EXECUTE));
1480 ok( handle != NULL || broken(new_flags),
1481 "%u: CreateFileMapping failed with error %u\n", i, GetLastError());
1482 ok( GetLastError() == 0 || broken(new_flags && GetLastError() == ERROR_INVALID_PARAMETER),
1483 "%u: wrong error %u\n", i, GetLastError());
1486 if (handle)
1488 SECTION_BASIC_INFORMATION info;
1489 DWORD expect = sec_flag_tests[i].attrs ? sec_flag_tests[i].attrs : sec_flag_tests[i].flags;
1491 status = pNtQuerySection( handle, SectionBasicInformation, &info, sizeof(info), NULL );
1492 ok( !status, "%u: NtQuerySection failed err %x\n", i, status );
1493 /* SEC_NOCACHE not supported on older Windows */
1494 ok( info.Attributes == expect || broken( info.Attributes == (expect & ~SEC_NOCACHE) ),
1495 "%u: NtQuerySection wrong attr %08x\n", i, info.Attributes );
1496 CloseHandle( handle );
1499 CloseHandle( file[1] );
1500 CloseHandle( file[2] );
1501 DeleteFileA( filename );
1504 static void test_IsBadReadPtr(void)
1506 BOOL ret;
1507 void *ptr = (void *)0xdeadbeef;
1508 char stackvar;
1510 ret = IsBadReadPtr(NULL, 0);
1511 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1513 ret = IsBadReadPtr(NULL, 1);
1514 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1516 ret = IsBadReadPtr(ptr, 0);
1517 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1519 ret = IsBadReadPtr(ptr, 1);
1520 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1522 ret = IsBadReadPtr(&stackvar, 0);
1523 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1525 ret = IsBadReadPtr(&stackvar, sizeof(char));
1526 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1528 ret = IsBadReadPtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD));
1529 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1531 ret = IsBadReadPtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD));
1532 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1535 static void test_IsBadWritePtr(void)
1537 BOOL ret;
1538 void *ptr = (void *)0xdeadbeef;
1539 char stackval;
1541 ret = IsBadWritePtr(NULL, 0);
1542 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1544 ret = IsBadWritePtr(NULL, 1);
1545 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1547 ret = IsBadWritePtr(ptr, 0);
1548 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1550 ret = IsBadWritePtr(ptr, 1);
1551 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1553 ret = IsBadWritePtr(&stackval, 0);
1554 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1556 ret = IsBadWritePtr(&stackval, sizeof(char));
1557 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1559 ret = IsBadWritePtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD));
1560 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1562 ret = IsBadWritePtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD));
1563 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1566 static void test_IsBadCodePtr(void)
1568 BOOL ret;
1569 void *ptr = (void *)0xdeadbeef;
1570 char stackval;
1572 ret = IsBadCodePtr(NULL);
1573 ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1575 ret = IsBadCodePtr(ptr);
1576 ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1578 ret = IsBadCodePtr((void *)&stackval);
1579 ok(ret == FALSE, "Expected IsBadCodePtr to return FALSE, got %d\n", ret);
1582 struct read_pipe_args
1584 HANDLE pipe;
1585 int index;
1586 void *base;
1587 DWORD size;
1590 static const char testdata[] = "Hello World";
1592 static DWORD CALLBACK read_pipe( void *arg )
1594 struct read_pipe_args *args = arg;
1595 DWORD num_bytes;
1596 BOOL success = ConnectNamedPipe( args->pipe, NULL );
1597 ok( success || GetLastError() == ERROR_PIPE_CONNECTED,
1598 "%u: ConnectNamedPipe failed %u\n", args->index, GetLastError() );
1600 success = ReadFile( args->pipe, args->base, args->size, &num_bytes, NULL );
1601 ok( success, "%u: ReadFile failed %u\n", args->index, GetLastError() );
1602 ok( num_bytes == sizeof(testdata), "%u: wrong number of bytes read %u\n", args->index, num_bytes );
1603 ok( !memcmp( args->base, testdata, sizeof(testdata)),
1604 "%u: didn't receive expected data\n", args->index );
1605 return 0;
1608 static void test_write_watch(void)
1610 static const char pipename[] = "\\\\.\\pipe\\test_write_watch_pipe";
1611 DWORD ret, size, old_prot, num_bytes;
1612 MEMORY_BASIC_INFORMATION info;
1613 HANDLE readpipe, writepipe, file;
1614 OVERLAPPED overlapped, *overlapped2;
1615 void *results[64];
1616 ULONG_PTR count;
1617 ULONG i, pagesize;
1618 BOOL success;
1619 char path[MAX_PATH], filename[MAX_PATH], *base;
1621 if (!pGetWriteWatch || !pResetWriteWatch)
1623 win_skip( "GetWriteWatch not supported\n" );
1624 return;
1627 size = 0x10000;
1628 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE );
1629 if (!base &&
1630 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
1632 win_skip( "MEM_WRITE_WATCH not supported\n" );
1633 return;
1635 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1636 ret = VirtualQuery( base, &info, sizeof(info) );
1637 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1638 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1639 ok( info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect %x\n", info.AllocationProtect );
1640 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1641 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
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 count = 64;
1646 SetLastError( 0xdeadbeef );
1647 ret = pGetWriteWatch( 0, NULL, size, results, &count, &pagesize );
1648 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1649 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
1650 broken( GetLastError() == 0xdeadbeef ), /* win98 */
1651 "wrong error %u\n", GetLastError() );
1653 SetLastError( 0xdeadbeef );
1654 ret = pGetWriteWatch( 0, GetModuleHandleW(NULL), size, results, &count, &pagesize );
1655 if (ret)
1657 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1658 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1660 else /* win98 */
1662 ok( count == 0, "wrong count %lu\n", count );
1665 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1666 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1667 ok( count == 0, "wrong count %lu\n", count );
1669 base[pagesize + 1] = 0x44;
1671 count = 64;
1672 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1673 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1674 ok( count == 1, "wrong count %lu\n", count );
1675 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1677 count = 64;
1678 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1679 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1680 ok( count == 1, "wrong count %lu\n", count );
1681 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1683 count = 64;
1684 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1685 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1686 ok( count == 0, "wrong count %lu\n", count );
1688 base[2*pagesize + 3] = 0x11;
1689 base[4*pagesize + 8] = 0x11;
1691 count = 64;
1692 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1693 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1694 ok( count == 2, "wrong count %lu\n", count );
1695 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1696 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1698 count = 64;
1699 ret = pGetWriteWatch( 0, base + 3*pagesize, 2*pagesize, results, &count, &pagesize );
1700 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1701 ok( count == 1, "wrong count %lu\n", count );
1702 ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1704 ret = pResetWriteWatch( base, 3*pagesize );
1705 ok( !ret, "pResetWriteWatch failed %u\n", GetLastError() );
1707 count = 64;
1708 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1709 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1710 ok( count == 1, "wrong count %lu\n", count );
1711 ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1713 *(DWORD *)(base + 2*pagesize - 2) = 0xdeadbeef;
1715 count = 64;
1716 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1717 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1718 ok( count == 3, "wrong count %lu\n", count );
1719 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1720 ok( results[1] == base + 2*pagesize, "wrong result %p\n", results[1] );
1721 ok( results[2] == base + 4*pagesize, "wrong result %p\n", results[2] );
1723 count = 1;
1724 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1725 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1726 ok( count == 1, "wrong count %lu\n", count );
1727 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1729 count = 64;
1730 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1731 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1732 ok( count == 2, "wrong count %lu\n", count );
1733 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1734 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1736 /* changing protections doesn't affect watches */
1738 ret = VirtualProtect( base, 3*pagesize, PAGE_READONLY, &old_prot );
1739 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1740 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1742 ret = VirtualQuery( base, &info, sizeof(info) );
1743 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1744 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1745 ok( info.RegionSize == 3*pagesize, "wrong RegionSize 0x%lx\n", info.RegionSize );
1746 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1747 ok( info.Protect == PAGE_READONLY, "wrong Protect 0x%x\n", info.Protect );
1749 ret = VirtualProtect( base, 3*pagesize, PAGE_READWRITE, &old_prot );
1750 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1751 ok( old_prot == PAGE_READONLY, "wrong old prot %x\n", old_prot );
1753 count = 64;
1754 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1755 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1756 ok( count == 2, "wrong count %lu\n", count );
1757 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1758 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1760 ret = VirtualQuery( base, &info, sizeof(info) );
1761 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1762 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1763 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1764 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1765 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1767 /* ReadFile should trigger write watches */
1769 for (i = 0; i < 2; i++)
1771 memset( &overlapped, 0, sizeof(overlapped) );
1772 overlapped.hEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
1774 readpipe = CreateNamedPipeA( pipename, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_INBOUND,
1775 (i ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE) | PIPE_WAIT, 1, 1024, 1024,
1776 NMPWAIT_USE_DEFAULT_WAIT, NULL );
1777 ok( readpipe != INVALID_HANDLE_VALUE, "CreateNamedPipeA failed %u\n", GetLastError() );
1779 success = ConnectNamedPipe( readpipe, &overlapped );
1780 ok( !success, "%u: ConnectNamedPipe unexpectedly succeeded\n", i );
1781 ok( GetLastError() == ERROR_IO_PENDING, "%u: expected ERROR_IO_PENDING, got %u\n",
1782 i, GetLastError() );
1784 writepipe = CreateFileA( pipename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
1785 ok( writepipe != INVALID_HANDLE_VALUE, "%u: CreateFileA failed %u\n", i, GetLastError() );
1787 ret = WaitForSingleObject( overlapped.hEvent, 1000 );
1788 ok( ret == WAIT_OBJECT_0, "%u: expected WAIT_OBJECT_0, got %u\n", i, ret );
1790 memset( base, 0, size );
1792 count = 64;
1793 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1794 ok( !ret, "%u: GetWriteWatch failed %u\n", i, GetLastError() );
1795 ok( count == 16, "%u: wrong count %lu\n", i, count );
1797 success = ReadFile( readpipe, base, size, NULL, &overlapped );
1798 ok( !success, "%u: ReadFile unexpectedly succeeded\n", i );
1799 ok( GetLastError() == ERROR_IO_PENDING, "%u: expected ERROR_IO_PENDING, got %u\n",
1800 i, GetLastError() );
1802 count = 64;
1803 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1804 ok( !ret, "%u: GetWriteWatch failed %u\n", i, GetLastError() );
1805 ok( count == 16, "%u: wrong count %lu\n", i, count );
1807 num_bytes = 0;
1808 success = WriteFile( writepipe, testdata, sizeof(testdata), &num_bytes, NULL );
1809 ok( success, "%u: WriteFile failed %u\n", i, GetLastError() );
1810 ok( num_bytes == sizeof(testdata), "%u: wrong number of bytes written %u\n", i, num_bytes );
1812 num_bytes = 0;
1813 success = GetOverlappedResult( readpipe, &overlapped, &num_bytes, TRUE );
1814 ok( success, "%u: GetOverlappedResult failed %u\n", i, GetLastError() );
1815 ok( num_bytes == sizeof(testdata), "%u: wrong number of bytes read %u\n", i, num_bytes );
1816 ok( !memcmp( base, testdata, sizeof(testdata)), "%u: didn't receive expected data\n", i );
1818 count = 64;
1819 memset( results, 0, sizeof(results) );
1820 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1821 ok( !ret, "%u: GetWriteWatch failed %u\n", i, GetLastError() );
1822 ok( count == 1, "%u: wrong count %lu\n", i, count );
1823 ok( results[0] == base, "%u: wrong result %p\n", i, results[0] );
1825 CloseHandle( readpipe );
1826 CloseHandle( writepipe );
1827 CloseHandle( overlapped.hEvent );
1830 for (i = 0; i < 2; i++)
1832 struct read_pipe_args args;
1833 HANDLE thread;
1835 readpipe = CreateNamedPipeA( pipename, PIPE_ACCESS_INBOUND,
1836 (i ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE) | PIPE_WAIT, 1, 1024, 1024,
1837 NMPWAIT_USE_DEFAULT_WAIT, NULL );
1838 ok( readpipe != INVALID_HANDLE_VALUE, "CreateNamedPipeA failed %u\n", GetLastError() );
1840 memset( base, 0, size );
1842 count = 64;
1843 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1844 ok( !ret, "%u: GetWriteWatch failed %u\n", i, GetLastError() );
1845 ok( count == 16, "%u: wrong count %lu\n", i, count );
1847 args.pipe = readpipe;
1848 args.index = i;
1849 args.base = base;
1850 args.size = size;
1851 thread = CreateThread( NULL, 0, read_pipe, &args, 0, NULL );
1853 writepipe = CreateFileA( pipename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
1854 ok( writepipe != INVALID_HANDLE_VALUE, "%u: CreateFileA failed %u\n", i, GetLastError() );
1855 Sleep( 200 );
1857 count = 64;
1858 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1859 ok( !ret, "%u: GetWriteWatch failed %u\n", i, GetLastError() );
1860 ok( count == 16, "%u: wrong count %lu\n", i, count );
1862 num_bytes = 0;
1863 success = WriteFile( writepipe, testdata, sizeof(testdata), &num_bytes, NULL );
1864 ok( success, "%u: WriteFile failed %u\n", i, GetLastError() );
1865 ok( num_bytes == sizeof(testdata), "%u: wrong number of bytes written %u\n", i, num_bytes );
1866 WaitForSingleObject( thread, 10000 );
1868 count = 64;
1869 memset( results, 0, sizeof(results) );
1870 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1871 ok( !ret, "%u: GetWriteWatch failed %u\n", i, GetLastError() );
1872 ok( count == 1, "%u: wrong count %lu\n", i, count );
1873 ok( results[0] == base, "%u: wrong result %p\n", i, results[0] );
1875 CloseHandle( readpipe );
1876 CloseHandle( writepipe );
1877 CloseHandle( thread );
1880 GetTempPathA( MAX_PATH, path );
1881 GetTempFileNameA( path, "map", 0, filename );
1882 file = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1883 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1884 SetFilePointer( file, 2 * pagesize + 3, NULL, FILE_BEGIN );
1885 SetEndOfFile( file );
1886 SetFilePointer( file, 0, NULL, FILE_BEGIN );
1888 success = ReadFile( file, base, size, &num_bytes, NULL );
1889 ok( success, "ReadFile failed %u\n", GetLastError() );
1890 ok( num_bytes == 2 * pagesize + 3, "wrong bytes %u\n", num_bytes );
1892 count = 64;
1893 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1894 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1895 ok( count == 16, "wrong count %lu\n", count );
1897 success = ReadFile( file, base, size, &num_bytes, NULL );
1898 ok( success, "ReadFile failed %u\n", GetLastError() );
1899 ok( num_bytes == 0, "wrong bytes %u\n", num_bytes );
1901 count = 64;
1902 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1903 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1904 ok( count == 16, "wrong count %lu\n", count );
1906 CloseHandle( file );
1907 DeleteFileA( filename );
1909 success = ReadFile( (HANDLE)0xdead, base, size, &num_bytes, NULL );
1910 ok( !success, "ReadFile succeeded\n" );
1911 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
1913 count = 64;
1914 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1915 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1916 ok( count == 0, "wrong count %lu\n", count );
1918 /* OVERLAPPED structure write watch */
1919 memset( &overlapped, 0, sizeof(overlapped) );
1920 overlapped.hEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
1922 readpipe = CreateNamedPipeA( pipename, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_INBOUND,
1923 PIPE_TYPE_MESSAGE | PIPE_WAIT, 1, 1024, 1024,
1924 NMPWAIT_USE_DEFAULT_WAIT, NULL );
1925 ok( readpipe != INVALID_HANDLE_VALUE, "CreateNamedPipeA failed %u\n", GetLastError() );
1927 success = ConnectNamedPipe( readpipe, &overlapped );
1928 ok( !success, "ConnectNamedPipe unexpectedly succeeded\n" );
1929 ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1931 writepipe = CreateFileA( pipename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
1932 ok( writepipe != INVALID_HANDLE_VALUE, "CreateFileA failed %u\n", GetLastError() );
1934 ret = WaitForSingleObject( overlapped.hEvent, 1000 );
1935 ok( ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret );
1937 memset( base, 0, size );
1938 overlapped2 = (OVERLAPPED*)(base + size - sizeof(*overlapped2));
1939 overlapped2->hEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
1941 count = 64;
1942 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1943 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1944 ok( count == 16, "wrong count %lu\n", count );
1946 success = ReadFile( readpipe, base, sizeof(testdata), NULL, overlapped2 );
1947 ok( !success, "ReadFile unexpectedly succeeded\n" );
1948 ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1949 overlapped2->Internal = 0xdeadbeef;
1951 count = 64;
1952 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1953 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1954 ok( count == 2, "wrong count %lu\n", count );
1956 num_bytes = 0;
1957 success = WriteFile( writepipe, testdata, sizeof(testdata), &num_bytes, NULL );
1958 ok( success, "WriteFile failed %u\n", GetLastError() );
1959 ok( num_bytes == sizeof(testdata), "wrong number of bytes written %u\n", num_bytes );
1961 num_bytes = 0;
1962 success = GetOverlappedResult( readpipe, overlapped2, &num_bytes, TRUE );
1963 ok( success, "GetOverlappedResult failed %u\n", GetLastError() );
1964 ok( num_bytes == sizeof(testdata), "wrong number of bytes read %u\n", num_bytes );
1965 ok( !memcmp( base, testdata, sizeof(testdata)), "didn't receive expected data\n" );
1967 count = 64;
1968 memset( results, 0, sizeof(results) );
1969 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1970 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1971 ok( count == 2, "wrong count %lu\n", count );
1972 ok( results[0] == base, "wrong result %p\n", results[0] );
1974 CloseHandle( readpipe );
1975 CloseHandle( writepipe );
1976 CloseHandle( overlapped.hEvent );
1977 CloseHandle( overlapped2->hEvent );
1979 /* some invalid parameter tests */
1981 SetLastError( 0xdeadbeef );
1982 count = 0;
1983 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1984 if (ret)
1986 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1987 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1989 SetLastError( 0xdeadbeef );
1990 ret = pGetWriteWatch( 0, base, size, results, NULL, &pagesize );
1991 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1992 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1994 SetLastError( 0xdeadbeef );
1995 count = 64;
1996 ret = pGetWriteWatch( 0, base, size, results, &count, NULL );
1997 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1998 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
2000 SetLastError( 0xdeadbeef );
2001 count = 64;
2002 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
2003 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
2004 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
2006 SetLastError( 0xdeadbeef );
2007 count = 0;
2008 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
2009 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
2010 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2012 SetLastError( 0xdeadbeef );
2013 count = 64;
2014 ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
2015 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
2016 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2018 SetLastError( 0xdeadbeef );
2019 count = 64;
2020 ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
2021 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
2022 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2024 SetLastError( 0xdeadbeef );
2025 count = 64;
2026 ret = pGetWriteWatch( 0, base, size * 2, results, &count, &pagesize );
2027 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
2028 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2030 SetLastError( 0xdeadbeef );
2031 count = 64;
2032 ret = pGetWriteWatch( 0, base + size - pagesize, pagesize + 1, results, &count, &pagesize );
2033 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
2034 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2036 SetLastError( 0xdeadbeef );
2037 ret = pResetWriteWatch( base, 0 );
2038 ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
2039 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2041 SetLastError( 0xdeadbeef );
2042 ret = pResetWriteWatch( GetModuleHandleW(NULL), size );
2043 ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
2044 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2046 else /* win98 is completely different */
2048 SetLastError( 0xdeadbeef );
2049 count = 64;
2050 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
2051 ok( ret == ERROR_INVALID_PARAMETER, "GetWriteWatch succeeded %u\n", ret );
2052 ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
2054 count = 0;
2055 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
2056 ok( !ret, "GetWriteWatch failed %u\n", ret );
2058 count = 64;
2059 ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
2060 ok( !ret, "GetWriteWatch failed %u\n", ret );
2062 count = 64;
2063 ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
2064 ok( !ret, "GetWriteWatch failed %u\n", ret );
2066 ret = pResetWriteWatch( base, 0 );
2067 ok( !ret, "ResetWriteWatch failed %u\n", ret );
2069 ret = pResetWriteWatch( GetModuleHandleW(NULL), size );
2070 ok( !ret, "ResetWriteWatch failed %u\n", ret );
2073 VirtualFree( base, 0, MEM_RELEASE );
2075 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_READWRITE );
2076 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2077 VirtualFree( base, 0, MEM_RELEASE );
2079 base = VirtualAlloc( 0, size, MEM_WRITE_WATCH, PAGE_READWRITE );
2080 ok( !base, "VirtualAlloc succeeded\n" );
2081 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2083 /* initial protect doesn't matter */
2085 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_NOACCESS );
2086 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2087 base = VirtualAlloc( base, size, MEM_COMMIT, PAGE_NOACCESS );
2088 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2090 count = 64;
2091 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
2092 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2093 ok( count == 0, "wrong count %lu\n", count );
2095 ret = VirtualProtect( base, 6*pagesize, PAGE_READWRITE, &old_prot );
2096 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
2097 ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
2099 base[5*pagesize + 200] = 3;
2101 ret = VirtualProtect( base, 6*pagesize, PAGE_NOACCESS, &old_prot );
2102 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
2103 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2105 count = 64;
2106 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
2107 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2108 ok( count == 1, "wrong count %lu\n", count );
2109 ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
2111 ret = VirtualFree( base, size, MEM_DECOMMIT );
2112 ok( ret, "VirtualFree failed %u\n", GetLastError() );
2114 count = 64;
2115 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
2116 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2117 ok( count == 1 || broken(count == 0), /* win98 */
2118 "wrong count %lu\n", count );
2119 if (count) ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
2121 VirtualFree( base, 0, MEM_RELEASE );
2124 #if defined(__i386__) || defined(__x86_64__)
2126 static DWORD WINAPI stack_commit_func( void *arg )
2128 volatile char *p = (char *)&p;
2130 /* trigger all guard pages, to ensure that the pages are committed */
2131 while (p >= (char *)NtCurrentTeb()->DeallocationStack + 4 * 0x1000)
2133 p[0] |= 0;
2134 p -= 0x1000;
2137 ok( arg == (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg );
2138 return 42;
2141 static void test_stack_commit(void)
2143 #ifdef __i386__
2144 static const char code_call_on_stack[] = {
2145 0x55, /* pushl %ebp */
2146 0x56, /* pushl %esi */
2147 0x89, 0xe6, /* movl %esp,%esi */
2148 0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */
2149 0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */
2150 0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */
2151 0x83, 0xe0, 0xf0, /* andl $~15,%eax */
2152 0x83, 0xe8, 0x0c, /* subl $12,%eax */
2153 0x89, 0xc4, /* movl %eax,%esp */
2154 0x52, /* pushl %edx */
2155 0x31, 0xed, /* xorl %ebp,%ebp */
2156 0xff, 0xd1, /* call *%ecx */
2157 0x89, 0xf4, /* movl %esi,%esp */
2158 0x5e, /* popl %esi */
2159 0x5d, /* popl %ebp */
2160 0xc2, 0x0c, 0x00 }; /* ret $12 */
2161 #else
2162 static const char code_call_on_stack[] = {
2163 0x55, /* pushq %rbp */
2164 0x48, 0x89, 0xe5, /* movq %rsp,%rbp */
2165 /* %rcx - func, %rdx - arg, %r8 - stack */
2166 0x48, 0x87, 0xca, /* xchgq %rcx,%rdx */
2167 0x49, 0x83, 0xe0, 0xf0, /* andq $~15,%r8 */
2168 0x49, 0x83, 0xe8, 0x20, /* subq $0x20,%r8 */
2169 0x4c, 0x89, 0xc4, /* movq %r8,%rsp */
2170 0xff, 0xd2, /* callq *%rdx */
2171 0x48, 0x89, 0xec, /* movq %rbp,%rsp */
2172 0x5d, /* popq %rbp */
2173 0xc3 }; /* ret */
2174 #endif
2175 DWORD (WINAPI *call_on_stack)( DWORD (WINAPI *func)(void *), void *arg, void *stack );
2176 void *old_stack, *old_stack_base, *old_stack_limit;
2177 void *new_stack, *new_stack_base;
2178 DWORD result;
2180 call_on_stack = VirtualAlloc( 0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE );
2181 ok( call_on_stack != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2182 memcpy( call_on_stack, code_call_on_stack, sizeof(code_call_on_stack) );
2184 /* allocate a new stack, only the first guard page is committed */
2185 new_stack = VirtualAlloc( 0, 0x400000, MEM_RESERVE, PAGE_READWRITE );
2186 ok( new_stack != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2187 new_stack_base = (char *)new_stack + 0x400000;
2188 VirtualAlloc( (char *)new_stack_base - 0x1000, 0x1000, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
2190 old_stack = NtCurrentTeb()->DeallocationStack;
2191 old_stack_base = NtCurrentTeb()->Tib.StackBase;
2192 old_stack_limit = NtCurrentTeb()->Tib.StackLimit;
2194 NtCurrentTeb()->DeallocationStack = new_stack;
2195 NtCurrentTeb()->Tib.StackBase = new_stack_base;
2196 NtCurrentTeb()->Tib.StackLimit = new_stack_base;
2198 result = call_on_stack( stack_commit_func, (void *)0xdeadbeef, new_stack_base );
2200 NtCurrentTeb()->DeallocationStack = old_stack;
2201 NtCurrentTeb()->Tib.StackBase = old_stack_base;
2202 NtCurrentTeb()->Tib.StackLimit = old_stack_limit;
2204 ok( result == 42, "expected 42, got %u\n", result );
2206 VirtualFree( new_stack, 0, MEM_RELEASE );
2207 VirtualFree( call_on_stack, 0, MEM_RELEASE );
2210 #endif /* defined(__i386__) || defined(__x86_64__) */
2211 #ifdef __i386__
2213 static LONG num_guard_page_calls;
2215 static DWORD guard_page_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
2216 CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
2218 trace( "exception: %08x flags:%x addr:%p\n",
2219 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
2221 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
2222 ok( rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION, "ExceptionCode is %08x instead of %08x\n",
2223 rec->ExceptionCode, STATUS_GUARD_PAGE_VIOLATION );
2225 InterlockedIncrement( &num_guard_page_calls );
2226 *(int *)rec->ExceptionInformation[1] += 0x100;
2228 return ExceptionContinueExecution;
2231 static void test_guard_page(void)
2233 EXCEPTION_REGISTRATION_RECORD frame;
2234 MEMORY_BASIC_INFORMATION info;
2235 DWORD ret, size, old_prot;
2236 int *value, old_value;
2237 void *results[64];
2238 ULONG_PTR count;
2239 ULONG pagesize;
2240 BOOL success;
2241 char *base;
2243 size = 0x1000;
2244 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
2245 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2246 value = (int *)base;
2248 /* verify info structure */
2249 ret = VirtualQuery( base, &info, sizeof(info) );
2250 ok( ret, "VirtualQuery failed %u\n", GetLastError());
2251 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
2252 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
2253 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
2254 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
2255 ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%x\n", info.Protect );
2256 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
2258 /* put some initial value into the memory */
2259 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2260 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2261 ok( old_prot == (PAGE_READWRITE | PAGE_GUARD), "wrong old prot %x\n", old_prot );
2263 *value = 1;
2264 *(value + 1) = 2;
2266 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2267 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2268 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2270 /* test behaviour of VirtualLock - first attempt should fail */
2271 SetLastError( 0xdeadbeef );
2272 success = VirtualLock( base, size );
2273 ok( !success, "VirtualLock unexpectedly succeeded\n" );
2274 todo_wine
2275 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %u\n", GetLastError() );
2277 success = VirtualLock( base, size );
2278 todo_wine
2279 ok( success, "VirtualLock failed %u\n", GetLastError() );
2280 if (success)
2282 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2283 success = VirtualUnlock( base, size );
2284 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2287 /* check info structure again, PAGE_GUARD should be removed now */
2288 ret = VirtualQuery( base, &info, sizeof(info) );
2289 ok( ret, "VirtualQuery failed %u\n", GetLastError());
2290 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
2291 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
2292 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
2293 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
2294 todo_wine
2295 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
2296 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
2298 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2299 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2300 todo_wine
2301 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2303 /* test directly accessing the memory - we need to setup an exception handler first */
2304 frame.Handler = guard_page_handler;
2305 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2306 NtCurrentTeb()->Tib.ExceptionList = &frame;
2308 InterlockedExchange( &num_guard_page_calls, 0 );
2309 InterlockedExchange( &old_value, *value ); /* exception handler increments value by 0x100 */
2310 *value = 2;
2311 ok( old_value == 0x101, "memory block contains wrong value, expected 0x101, got 0x%x\n", old_value );
2312 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2314 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2316 /* check info structure again, PAGE_GUARD should be removed now */
2317 ret = VirtualQuery( base, &info, sizeof(info) );
2318 ok( ret, "VirtualQuery failed %u\n", GetLastError());
2319 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
2321 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2322 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2323 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2325 /* test accessing second integer in memory */
2326 frame.Handler = guard_page_handler;
2327 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2328 NtCurrentTeb()->Tib.ExceptionList = &frame;
2330 InterlockedExchange( &num_guard_page_calls, 0 );
2331 old_value = *(value + 1);
2332 ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value );
2333 ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value );
2334 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2336 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2338 success = VirtualLock( base, size );
2339 ok( success, "VirtualLock failed %u\n", GetLastError() );
2340 if (success)
2342 ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value );
2343 success = VirtualUnlock( base, size );
2344 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2347 VirtualFree( base, 0, MEM_RELEASE );
2349 /* combined guard page / write watch tests */
2350 if (!pGetWriteWatch || !pResetWriteWatch)
2352 win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" );
2353 return;
2356 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE | PAGE_GUARD );
2357 if (!base && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
2359 win_skip( "MEM_WRITE_WATCH not supported\n" );
2360 return;
2362 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2363 value = (int *)base;
2365 ret = VirtualQuery( base, &info, sizeof(info) );
2366 ok( ret, "VirtualQuery failed %u\n", GetLastError() );
2367 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
2368 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
2369 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
2370 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
2371 ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%x\n", info.Protect );
2372 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
2374 count = 64;
2375 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
2376 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2377 ok( count == 0, "wrong count %lu\n", count );
2379 /* writing to a page should trigger should trigger guard page, even if write watch is set */
2380 frame.Handler = guard_page_handler;
2381 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2382 NtCurrentTeb()->Tib.ExceptionList = &frame;
2384 InterlockedExchange( &num_guard_page_calls, 0 );
2385 *value = 1;
2386 *(value + 1) = 2;
2387 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2389 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2391 count = 64;
2392 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2393 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2394 ok( count == 1, "wrong count %lu\n", count );
2395 ok( results[0] == base, "wrong result %p\n", results[0] );
2397 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2398 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2400 /* write watch is triggered from inside of the guard page handler */
2401 frame.Handler = guard_page_handler;
2402 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2403 NtCurrentTeb()->Tib.ExceptionList = &frame;
2405 InterlockedExchange( &num_guard_page_calls, 0 );
2406 old_value = *(value + 1); /* doesn't trigger write watch */
2407 ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value );
2408 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2409 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2411 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2413 count = 64;
2414 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2415 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2416 ok( count == 1, "wrong count %lu\n", count );
2417 ok( results[0] == base, "wrong result %p\n", results[0] );
2419 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2420 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2422 /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */
2423 SetLastError( 0xdeadbeef );
2424 success = VirtualLock( base, size );
2425 ok( !success, "VirtualLock unexpectedly succeeded\n" );
2426 todo_wine
2427 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %u\n", GetLastError() );
2429 count = 64;
2430 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
2431 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2432 ok( count == 0, "wrong count %lu\n", count );
2434 success = VirtualLock( base, size );
2435 todo_wine
2436 ok( success, "VirtualLock failed %u\n", GetLastError() );
2437 if (success)
2439 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2440 success = VirtualUnlock( base, size );
2441 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2444 count = 64;
2445 results[0] = (void *)0xdeadbeef;
2446 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2447 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2448 todo_wine
2449 ok( count == 1 || broken(count == 0) /* Windows 8 */, "wrong count %lu\n", count );
2450 todo_wine
2451 ok( results[0] == base || broken(results[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results[0] );
2453 VirtualFree( base, 0, MEM_RELEASE );
2456 static LONG num_execute_fault_calls;
2458 static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
2459 CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
2461 ULONG flags = MEM_EXECUTE_OPTION_ENABLE;
2462 DWORD err;
2464 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2465 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
2466 rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] );
2468 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
2469 ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION || rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION,
2470 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec->ExceptionCode );
2472 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags), NULL );
2474 if (rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
2477 err = IsProcessorFeaturePresent( PF_NX_ENABLED ) ? EXCEPTION_EXECUTE_FAULT : EXCEPTION_READ_FAULT;
2478 ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %d instead of %d\n",
2479 (DWORD)rec->ExceptionInformation[0], err );
2481 InterlockedIncrement( &num_guard_page_calls );
2483 else if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION)
2485 DWORD old_prot;
2486 BOOL success;
2488 err = (flags & MEM_EXECUTE_OPTION_DISABLE) ? EXCEPTION_EXECUTE_FAULT : EXCEPTION_READ_FAULT;
2489 ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %d instead of %d\n",
2490 (DWORD)rec->ExceptionInformation[0], err );
2492 success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
2493 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2494 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2496 InterlockedIncrement( &num_execute_fault_calls );
2499 return ExceptionContinueExecution;
2502 static LONG CALLBACK execute_fault_vec_handler( EXCEPTION_POINTERS *ExceptionInfo )
2504 PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
2505 DWORD old_prot;
2506 BOOL success;
2508 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2509 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
2510 rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] );
2512 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
2513 ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION,
2514 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec->ExceptionCode );
2516 if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION)
2517 InterlockedIncrement( &num_execute_fault_calls );
2519 if (rec->ExceptionInformation[0] == EXCEPTION_READ_FAULT)
2520 return EXCEPTION_CONTINUE_SEARCH;
2522 success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
2523 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2524 ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
2526 return EXCEPTION_CONTINUE_EXECUTION;
2529 static inline DWORD send_message_excpt( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2531 EXCEPTION_REGISTRATION_RECORD frame;
2532 DWORD ret;
2534 frame.Handler = execute_fault_seh_handler;
2535 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2536 NtCurrentTeb()->Tib.ExceptionList = &frame;
2538 InterlockedExchange( &num_guard_page_calls, 0 );
2539 InterlockedExchange( &num_execute_fault_calls, 0 );
2540 ret = SendMessageA( hWnd, uMsg, wParam, lParam );
2542 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2544 return ret;
2547 static inline DWORD call_proc_excpt( DWORD (CALLBACK *code)(void *), void *arg )
2549 EXCEPTION_REGISTRATION_RECORD frame;
2550 DWORD ret;
2552 frame.Handler = execute_fault_seh_handler;
2553 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2554 NtCurrentTeb()->Tib.ExceptionList = &frame;
2556 InterlockedExchange( &num_guard_page_calls, 0 );
2557 InterlockedExchange( &num_execute_fault_calls, 0 );
2558 ret = code( arg );
2560 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2562 return ret;
2565 static LRESULT CALLBACK jmp_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2567 if (uMsg == WM_USER)
2568 return 42;
2570 return DefWindowProcA( hWnd, uMsg, wParam, lParam );
2573 static LRESULT CALLBACK atl_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2575 DWORD arg = (DWORD)hWnd;
2576 if (uMsg == WM_USER)
2577 ok( arg == 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg );
2578 else
2579 ok( arg != 0x11223344, "arg is unexpectedly 0x11223344\n" );
2580 return 43;
2583 static DWORD CALLBACK atl5_test_func( void )
2585 return 44;
2588 static void test_atl_thunk_emulation( ULONG dep_flags )
2590 static const char code_jmp[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
2591 static const char code_atl1[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2592 static const char code_atl2[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2593 static const char code_atl3[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1};
2594 static const char code_atl4[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
2595 static const char code_atl5[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04};
2596 static const char cls_name[] = "atl_thunk_class";
2597 DWORD ret, size, old_prot;
2598 ULONG old_flags = MEM_EXECUTE_OPTION_ENABLE;
2599 BOOL success, restore_flags = FALSE;
2600 void *results[64];
2601 ULONG_PTR count;
2602 ULONG pagesize;
2603 WNDCLASSEXA wc;
2604 char *base;
2605 HWND hWnd;
2607 trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
2609 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags), NULL );
2610 if (old_flags != dep_flags)
2612 ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &dep_flags, sizeof(dep_flags) );
2613 if (ret == STATUS_INVALID_INFO_CLASS /* Windows 2000 */ ||
2614 ret == STATUS_ACCESS_DENIED)
2616 win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
2617 return;
2619 ok( !ret, "NtSetInformationProcess failed with status %08x\n", ret );
2620 restore_flags = TRUE;
2623 size = 0x1000;
2624 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
2625 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2627 /* Check result of GetProcessDEPPolicy */
2628 if (!pGetProcessDEPPolicy)
2629 win_skip( "GetProcessDEPPolicy not supported\n" );
2630 else
2632 BOOL (WINAPI *get_dep_policy)(HANDLE, LPDWORD, PBOOL) = (void *)base;
2633 BOOL policy_permanent = 0xdeadbeef;
2634 DWORD policy_flags = 0xdeadbeef;
2636 /* GetProcessDEPPolicy crashes on Windows when a NULL pointer is passed.
2637 * Moreover this function has a bug on Windows 8, which has the effect that
2638 * policy_permanent is set to the content of the CL register instead of 0,
2639 * when the policy is not permanent. To detect that we use an assembler
2640 * wrapper to call the function. */
2642 memcpy( base, code_atl2, sizeof(code_atl2) );
2643 *(DWORD *)(base + 6) = (DWORD_PTR)pGetProcessDEPPolicy - (DWORD_PTR)(base + 10);
2645 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2646 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2648 success = get_dep_policy( GetCurrentProcess(), &policy_flags, &policy_permanent );
2649 ok( success, "GetProcessDEPPolicy failed %u\n", GetLastError() );
2651 ret = 0;
2652 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2653 ret |= PROCESS_DEP_ENABLE;
2654 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)
2655 ret |= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION;
2657 ok( policy_flags == ret, "expected policy flags %d, got %d\n", ret, policy_flags );
2658 ok( !policy_permanent || broken(policy_permanent == 0x44),
2659 "expected policy permanent FALSE, got %d\n", policy_permanent );
2662 memcpy( base, code_jmp, sizeof(code_jmp) );
2663 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2665 /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
2666 * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
2667 * where it is active, so that application which depend on that still work properly.
2668 * We have no exception handler enabled yet, so give proper EXECUTE permissions to
2669 * prevent crashes while creating the window. */
2671 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2672 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2674 memset( &wc, 0, sizeof(wc) );
2675 wc.cbSize = sizeof(wc);
2676 wc.style = CS_VREDRAW | CS_HREDRAW;
2677 wc.hInstance = GetModuleHandleA( 0 );
2678 wc.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW );
2679 wc.hbrBackground = NULL;
2680 wc.lpszClassName = cls_name;
2681 wc.lpfnWndProc = (WNDPROC)base;
2682 success = RegisterClassExA(&wc) != 0;
2683 ok( success, "RegisterClassExA failed %u\n", GetLastError() );
2685 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2686 ok( hWnd != 0, "CreateWindowExA failed %u\n", GetLastError() );
2688 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2689 ok( ret == 42, "SendMessage returned unexpected result %d\n", ret );
2691 /* At first try with an instruction which is not recognized as proper ATL thunk
2692 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2693 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2695 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2696 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2698 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2699 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2700 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2701 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && !IsProcessorFeaturePresent( PF_NX_ENABLED ))
2703 trace( "DEP hardware support is not available\n" );
2704 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2705 dep_flags = MEM_EXECUTE_OPTION_ENABLE;
2707 else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2709 trace( "DEP hardware support is available\n" );
2710 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2712 else
2713 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2715 /* Now a bit more complicated, the page containing the code is protected with
2716 * PAGE_GUARD memory protection. */
2718 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2719 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2721 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2722 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2723 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2724 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2725 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2726 else
2727 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2729 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2730 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2731 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2732 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2734 /* Now test with a proper ATL thunk instruction. */
2736 memcpy( base, code_atl1, sizeof(code_atl1) );
2737 *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
2739 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2740 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2742 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2743 ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
2745 /* Try executing with PAGE_READWRITE protection. */
2747 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2748 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2750 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2751 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2752 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2753 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2754 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2755 else
2756 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2758 /* Now a bit more complicated, the page containing the code is protected with
2759 * PAGE_GUARD memory protection. */
2761 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2762 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2764 /* the same, but with PAGE_GUARD set */
2765 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2766 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2767 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2768 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2769 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2770 else
2771 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2773 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2774 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2775 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2776 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2778 /* The following test shows that on Windows, even a vectored exception handler
2779 * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */
2781 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && !(dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2783 if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
2785 PVOID vectored_handler;
2787 success = VirtualProtect( base, size, PAGE_NOACCESS, &old_prot );
2788 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2790 vectored_handler = pRtlAddVectoredExceptionHandler( TRUE, &execute_fault_vec_handler );
2791 ok( vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n" );
2793 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2795 pRtlRemoveVectoredExceptionHandler( vectored_handler );
2797 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2798 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2800 else
2801 win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" );
2804 /* Test alternative ATL thunk instructions. */
2806 memcpy( base, code_atl2, sizeof(code_atl2) );
2807 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 10);
2809 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2810 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2812 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2813 /* FIXME: we don't check the content of the register ECX yet */
2814 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2815 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2816 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2817 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2818 else
2819 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2821 memcpy( base, code_atl3, sizeof(code_atl3) );
2822 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func;
2824 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2825 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2827 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2828 /* FIXME: we don't check the content of the registers ECX/EDX yet */
2829 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2830 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2831 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2832 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2833 else
2834 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2836 memcpy( base, code_atl4, sizeof(code_atl4) );
2837 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func;
2839 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2840 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2842 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2843 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2844 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2845 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2846 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2847 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2848 else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2849 ok( num_execute_fault_calls == 0 || broken(num_execute_fault_calls == 1) /* Windows XP */,
2850 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2851 else
2852 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2854 memcpy( base, code_atl5, sizeof(code_atl5) );
2856 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2857 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2859 results[1] = atl5_test_func;
2860 ret = call_proc_excpt( (void *)base, results );
2861 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2862 ok( ret == 44, "call returned wrong result, expected 44, got %d\n", ret );
2863 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2864 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2865 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2866 else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2867 ok( num_execute_fault_calls == 0 || broken(num_execute_fault_calls == 1) /* Windows XP */,
2868 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2869 else
2870 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2872 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2874 memcpy( base, code_jmp, sizeof(code_jmp) );
2875 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2877 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2878 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2880 DestroyWindow( hWnd );
2882 success = UnregisterClassA( cls_name, GetModuleHandleA(0) );
2883 ok( success, "UnregisterClass failed %u\n", GetLastError() );
2885 VirtualFree( base, 0, MEM_RELEASE );
2887 /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */
2889 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE );
2890 if (!base && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
2892 win_skip( "MEM_WRITE_WATCH not supported\n" );
2893 goto out;
2895 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2897 count = 64;
2898 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2899 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2900 ok( count == 0, "wrong count %lu\n", count );
2902 memcpy( base, code_jmp, sizeof(code_jmp) );
2903 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2905 count = 64;
2906 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2907 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2908 ok( count == 1, "wrong count %lu\n", count );
2909 ok( results[0] == base, "wrong result %p\n", results[0] );
2911 /* Create a new window class and associated Window (see above) */
2913 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2914 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2916 memset( &wc, 0, sizeof(wc) );
2917 wc.cbSize = sizeof(wc);
2918 wc.style = CS_VREDRAW | CS_HREDRAW;
2919 wc.hInstance = GetModuleHandleA( 0 );
2920 wc.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW );
2921 wc.hbrBackground = NULL;
2922 wc.lpszClassName = cls_name;
2923 wc.lpfnWndProc = (WNDPROC)base;
2924 success = RegisterClassExA(&wc) != 0;
2925 ok( success, "RegisterClassExA failed %u\n", GetLastError() );
2927 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2928 ok( hWnd != 0, "CreateWindowExA failed %u\n", GetLastError() );
2930 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2931 ok( ret == 42, "SendMessage returned unexpected result %d\n", ret );
2933 count = 64;
2934 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2935 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2936 ok( count == 0, "wrong count %lu\n", count );
2938 /* At first try with an instruction which is not recognized as proper ATL thunk
2939 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2940 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2942 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2943 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2945 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2946 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2947 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2948 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2949 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2950 else
2951 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2953 count = 64;
2954 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2955 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2956 ok( count == 0, "wrong count %lu\n", count );
2958 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2959 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2960 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2961 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2963 /* Now a bit more complicated, the page containing the code is protected with
2964 * PAGE_GUARD memory protection. */
2966 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2967 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2969 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2970 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2971 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2972 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2973 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2974 else
2975 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2977 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2978 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2979 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2980 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2982 count = 64;
2983 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2984 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2985 ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
2987 /* Now test with a proper ATL thunk instruction. */
2989 memcpy( base, code_atl1, sizeof(code_atl1) );
2990 *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
2992 count = 64;
2993 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2994 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2995 ok( count == 1, "wrong count %lu\n", count );
2996 ok( results[0] == base, "wrong result %p\n", results[0] );
2998 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2999 ok( success, "VirtualProtect failed %u\n", GetLastError() );
3001 ret = SendMessageA(hWnd, WM_USER, 0, 0);
3002 ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
3004 /* Try executing with PAGE_READWRITE protection. */
3006 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
3007 ok( success, "VirtualProtect failed %u\n", GetLastError() );
3009 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
3010 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
3011 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
3012 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
3013 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
3014 else
3015 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
3017 count = 64;
3018 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
3019 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
3020 ok( count == 0, "wrong count %lu\n", count );
3022 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
3023 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
3024 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
3025 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
3027 /* Now a bit more complicated, the page containing the code is protected with
3028 * PAGE_GUARD memory protection. */
3030 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
3031 ok( success, "VirtualProtect failed %u\n", GetLastError() );
3033 /* the same, but with PAGE_GUARD set */
3034 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
3035 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
3036 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
3037 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
3038 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
3039 else
3040 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
3042 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
3043 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
3044 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
3045 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
3047 count = 64;
3048 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
3049 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
3050 ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
3052 /* Restore the JMP instruction, set to executable, and then destroy the Window */
3054 memcpy( base, code_jmp, sizeof(code_jmp) );
3055 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
3057 count = 64;
3058 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
3059 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
3060 ok( count == 1, "wrong count %lu\n", count );
3061 ok( results[0] == base, "wrong result %p\n", results[0] );
3063 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
3064 ok( success, "VirtualProtect failed %u\n", GetLastError() );
3066 DestroyWindow( hWnd );
3068 success = UnregisterClassA( cls_name, GetModuleHandleA(0) );
3069 ok( success, "UnregisterClass failed %u\n", GetLastError() );
3071 VirtualFree( base, 0, MEM_RELEASE );
3073 out:
3074 if (restore_flags)
3076 ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags) );
3077 ok( !ret, "NtSetInformationProcess failed with status %08x\n", ret );
3081 #endif /* __i386__ */
3083 static void test_VirtualProtect(void)
3085 static const struct test_data
3087 DWORD prot_set, prot_get;
3088 } td[] =
3090 { 0, 0 }, /* 0x00 */
3091 { PAGE_NOACCESS, PAGE_NOACCESS }, /* 0x01 */
3092 { PAGE_READONLY, PAGE_READONLY }, /* 0x02 */
3093 { PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x03 */
3094 { PAGE_READWRITE, PAGE_READWRITE }, /* 0x04 */
3095 { PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x05 */
3096 { PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x06 */
3097 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x07 */
3098 { PAGE_WRITECOPY, 0 }, /* 0x08 */
3099 { PAGE_WRITECOPY | PAGE_NOACCESS, 0 }, /* 0x09 */
3100 { PAGE_WRITECOPY | PAGE_READONLY, 0 }, /* 0x0a */
3101 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, 0 }, /* 0x0b */
3102 { PAGE_WRITECOPY | PAGE_READWRITE, 0 }, /* 0x0c */
3103 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x0d */
3104 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x0e */
3105 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x0f */
3107 { PAGE_EXECUTE, PAGE_EXECUTE }, /* 0x10 */
3108 { PAGE_EXECUTE_READ, PAGE_EXECUTE_READ }, /* 0x20 */
3109 { PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x30 */
3110 { PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_READWRITE }, /* 0x40 */
3111 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0x50 */
3112 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0x60 */
3113 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x70 */
3114 { PAGE_EXECUTE_WRITECOPY, 0 }, /* 0x80 */
3115 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, 0 }, /* 0x90 */
3116 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, 0 }, /* 0xa0 */
3117 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0xb0 */
3118 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, 0 }, /* 0xc0 */
3119 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0xd0 */
3120 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0xe0 */
3121 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 } /* 0xf0 */
3123 char *base, *ptr;
3124 DWORD ret, old_prot, rw_prot, exec_prot, i, j;
3125 MEMORY_BASIC_INFORMATION info;
3126 void *addr;
3127 SIZE_T size;
3128 NTSTATUS status;
3130 SetLastError(0xdeadbeef);
3131 base = VirtualAlloc(0, si.dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
3132 ok(base != NULL, "VirtualAlloc failed %d\n", GetLastError());
3134 SetLastError(0xdeadbeef);
3135 ret = VirtualProtect(base, si.dwPageSize, PAGE_READONLY, NULL);
3136 ok(!ret, "VirtualProtect should fail\n");
3137 ok(GetLastError() == ERROR_NOACCESS, "expected ERROR_NOACCESS, got %d\n", GetLastError());
3138 old_prot = 0xdeadbeef;
3139 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
3140 ok(ret, "VirtualProtect failed %d\n", GetLastError());
3141 ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
3143 addr = base;
3144 size = si.dwPageSize;
3145 status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_READONLY, NULL);
3146 ok(status == STATUS_ACCESS_VIOLATION, "NtProtectVirtualMemory should fail, got %08x\n", status);
3147 addr = base;
3148 size = si.dwPageSize;
3149 old_prot = 0xdeadbeef;
3150 status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_NOACCESS, &old_prot);
3151 ok(status == STATUS_SUCCESS, "NtProtectVirtualMemory should succeed, got %08x\n", status);
3152 ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
3154 for (i = 0; i < ARRAY_SIZE(td); i++)
3156 SetLastError(0xdeadbeef);
3157 ret = VirtualQuery(base, &info, sizeof(info));
3158 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3159 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
3160 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
3161 ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect);
3162 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
3163 ok(info.AllocationProtect == PAGE_NOACCESS, "%d: %#x != PAGE_NOACCESS\n", i, info.AllocationProtect);
3164 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
3165 ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
3167 old_prot = 0xdeadbeef;
3168 SetLastError(0xdeadbeef);
3169 ret = VirtualProtect(base, si.dwPageSize, td[i].prot_set, &old_prot);
3170 if (td[i].prot_get)
3172 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
3173 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
3175 SetLastError(0xdeadbeef);
3176 ret = VirtualQuery(base, &info, sizeof(info));
3177 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3178 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
3179 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
3180 ok(info.Protect == td[i].prot_get, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_get);
3181 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
3182 ok(info.AllocationProtect == PAGE_NOACCESS, "%d: %#x != PAGE_NOACCESS\n", i, info.AllocationProtect);
3183 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
3184 ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
3186 else
3188 ok(!ret, "%d: VirtualProtect should fail\n", i);
3189 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3192 old_prot = 0xdeadbeef;
3193 SetLastError(0xdeadbeef);
3194 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
3195 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
3196 if (td[i].prot_get)
3197 ok(old_prot == td[i].prot_get, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_get);
3198 else
3199 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
3202 exec_prot = 0;
3204 for (i = 0; i <= 4; i++)
3206 rw_prot = 0;
3208 for (j = 0; j <= 4; j++)
3210 DWORD prot = exec_prot | rw_prot;
3212 SetLastError(0xdeadbeef);
3213 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, prot);
3214 if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
3216 ok(!ptr, "VirtualAlloc(%02x) should fail\n", prot);
3217 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3219 else
3221 if (prot & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))
3223 ok(!ptr, "VirtualAlloc(%02x) should fail\n", prot);
3224 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3226 else
3228 ok(ptr != NULL, "VirtualAlloc(%02x) error %d\n", prot, GetLastError());
3229 ok(ptr == base, "expected %p, got %p\n", base, ptr);
3233 SetLastError(0xdeadbeef);
3234 ret = VirtualProtect(base, si.dwPageSize, prot, &old_prot);
3235 if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
3237 ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
3238 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3240 else
3242 if (prot & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))
3244 ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
3245 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3247 else
3248 ok(ret, "VirtualProtect(%02x) error %d\n", prot, GetLastError());
3251 rw_prot = 1 << j;
3254 exec_prot = 1 << (i + 4);
3257 VirtualFree(base, 0, MEM_RELEASE);
3260 static BOOL is_mem_writable(DWORD prot)
3262 switch (prot & 0xff)
3264 case PAGE_READWRITE:
3265 case PAGE_WRITECOPY:
3266 case PAGE_EXECUTE_READWRITE:
3267 case PAGE_EXECUTE_WRITECOPY:
3268 return TRUE;
3270 default:
3271 return FALSE;
3275 static void test_VirtualAlloc_protection(void)
3277 static const struct test_data
3279 DWORD prot;
3280 BOOL success;
3281 } td[] =
3283 { 0, FALSE }, /* 0x00 */
3284 { PAGE_NOACCESS, TRUE }, /* 0x01 */
3285 { PAGE_READONLY, TRUE }, /* 0x02 */
3286 { PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x03 */
3287 { PAGE_READWRITE, TRUE }, /* 0x04 */
3288 { PAGE_READWRITE | PAGE_NOACCESS, FALSE }, /* 0x05 */
3289 { PAGE_READWRITE | PAGE_READONLY, FALSE }, /* 0x06 */
3290 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x07 */
3291 { PAGE_WRITECOPY, FALSE }, /* 0x08 */
3292 { PAGE_WRITECOPY | PAGE_NOACCESS, FALSE }, /* 0x09 */
3293 { PAGE_WRITECOPY | PAGE_READONLY, FALSE }, /* 0x0a */
3294 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, FALSE }, /* 0x0b */
3295 { PAGE_WRITECOPY | PAGE_READWRITE, FALSE }, /* 0x0c */
3296 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, FALSE }, /* 0x0d */
3297 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, FALSE }, /* 0x0e */
3298 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x0f */
3300 { PAGE_EXECUTE, TRUE }, /* 0x10 */
3301 { PAGE_EXECUTE_READ, TRUE }, /* 0x20 */
3302 { PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0x30 */
3303 { PAGE_EXECUTE_READWRITE, TRUE }, /* 0x40 */
3304 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE }, /* 0x50 */
3305 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE }, /* 0x60 */
3306 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0x70 */
3307 { PAGE_EXECUTE_WRITECOPY, FALSE }, /* 0x80 */
3308 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, FALSE }, /* 0x90 */
3309 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, FALSE }, /* 0xa0 */
3310 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0xb0 */
3311 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, FALSE }, /* 0xc0 */
3312 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE }, /* 0xd0 */
3313 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE }, /* 0xe0 */
3314 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE } /* 0xf0 */
3316 char *base, *ptr;
3317 DWORD ret, i;
3318 MEMORY_BASIC_INFORMATION info;
3320 for (i = 0; i < ARRAY_SIZE(td); i++)
3322 SetLastError(0xdeadbeef);
3323 base = VirtualAlloc(0, si.dwPageSize, MEM_COMMIT, td[i].prot);
3325 if (td[i].success)
3327 ok(base != NULL, "%d: VirtualAlloc failed %d\n", i, GetLastError());
3329 SetLastError(0xdeadbeef);
3330 ret = VirtualQuery(base, &info, sizeof(info));
3331 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3332 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
3333 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
3334 ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
3335 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
3336 ok(info.AllocationProtect == td[i].prot, "%d: %#x != %#x\n", i, info.AllocationProtect, td[i].prot);
3337 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
3338 ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
3340 if (is_mem_writable(info.Protect))
3342 base[0] = 0xfe;
3344 SetLastError(0xdeadbeef);
3345 ret = VirtualQuery(base, &info, sizeof(info));
3346 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3347 ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
3350 SetLastError(0xdeadbeef);
3351 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, td[i].prot);
3352 ok(ptr == base, "%d: VirtualAlloc failed %d\n", i, GetLastError());
3354 VirtualFree(base, 0, MEM_RELEASE);
3356 else
3358 ok(!base, "%d: VirtualAlloc should fail\n", i);
3359 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3364 static void test_CreateFileMapping_protection(void)
3366 static const struct test_data
3368 DWORD prot;
3369 BOOL success;
3370 DWORD prot_after_write;
3371 } td[] =
3373 { 0, FALSE, 0 }, /* 0x00 */
3374 { PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x01 */
3375 { PAGE_READONLY, TRUE, PAGE_READONLY }, /* 0x02 */
3376 { PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x03 */
3377 { PAGE_READWRITE, TRUE, PAGE_READWRITE }, /* 0x04 */
3378 { PAGE_READWRITE | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x05 */
3379 { PAGE_READWRITE | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x06 */
3380 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x07 */
3381 { PAGE_WRITECOPY, TRUE, PAGE_READWRITE }, /* 0x08 */
3382 { PAGE_WRITECOPY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x09 */
3383 { PAGE_WRITECOPY | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0a */
3384 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0b */
3385 { PAGE_WRITECOPY | PAGE_READWRITE, FALSE, PAGE_NOACCESS }, /* 0x0c */
3386 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x0d */
3387 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0e */
3388 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x0f */
3390 { PAGE_EXECUTE, FALSE, PAGE_EXECUTE }, /* 0x10 */
3391 { PAGE_EXECUTE_READ, TRUE, PAGE_EXECUTE_READ }, /* 0x20 */
3392 { PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_EXECUTE_READ }, /* 0x30 */
3393 { PAGE_EXECUTE_READWRITE, TRUE, PAGE_EXECUTE_READWRITE }, /* 0x40 */
3394 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x50 */
3395 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0x60 */
3396 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x70 */
3397 { PAGE_EXECUTE_WRITECOPY, TRUE, PAGE_EXECUTE_READWRITE }, /* 0x80 */
3398 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x90 */
3399 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0xa0 */
3400 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0xb0 */
3401 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, FALSE, PAGE_NOACCESS }, /* 0xc0 */
3402 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0xd0 */
3403 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0xe0 */
3404 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS } /* 0xf0 */
3406 char *base, *ptr;
3407 DWORD ret, i, alloc_prot, old_prot;
3408 MEMORY_BASIC_INFORMATION info;
3409 char temp_path[MAX_PATH];
3410 char file_name[MAX_PATH];
3411 HANDLE hfile, hmap;
3412 BOOL page_exec_supported = TRUE;
3414 GetTempPathA(MAX_PATH, temp_path);
3415 GetTempFileNameA(temp_path, "map", 0, file_name);
3417 SetLastError(0xdeadbeef);
3418 hfile = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
3419 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
3420 SetFilePointer(hfile, si.dwPageSize, NULL, FILE_BEGIN);
3421 SetEndOfFile(hfile);
3423 for (i = 0; i < ARRAY_SIZE(td); i++)
3425 SetLastError(0xdeadbeef);
3426 hmap = CreateFileMappingW(hfile, NULL, td[i].prot | SEC_COMMIT, 0, si.dwPageSize, NULL);
3428 if (td[i].success)
3430 if (!hmap)
3432 trace("%d: CreateFileMapping(%04x) failed: %d\n", i, td[i].prot, GetLastError());
3433 /* NT4 and win2k don't support EXEC on file mappings */
3434 if (td[i].prot == PAGE_EXECUTE_READ || td[i].prot == PAGE_EXECUTE_READWRITE)
3436 page_exec_supported = FALSE;
3437 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i);
3438 continue;
3440 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3441 if (td[i].prot == PAGE_EXECUTE_WRITECOPY)
3443 page_exec_supported = FALSE;
3444 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
3445 continue;
3448 ok(hmap != 0, "%d: CreateFileMapping(%04x) error %d\n", i, td[i].prot, GetLastError());
3450 base = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0);
3451 ok(base != NULL, "%d: MapViewOfFile failed %d\n", i, GetLastError());
3453 SetLastError(0xdeadbeef);
3454 ret = VirtualQuery(base, &info, sizeof(info));
3455 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3456 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
3457 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
3458 ok(info.Protect == PAGE_READONLY, "%d: got %#x != expected PAGE_READONLY\n", i, info.Protect);
3459 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
3460 ok(info.AllocationProtect == PAGE_READONLY, "%d: %#x != PAGE_READONLY\n", i, info.AllocationProtect);
3461 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
3462 ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
3464 SetLastError(0xdeadbeef);
3465 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, td[i].prot);
3466 ok(!ptr, "%d: VirtualAlloc(%02x) should fail\n", i, td[i].prot);
3467 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
3469 SetLastError(0xdeadbeef);
3470 ret = VirtualProtect(base, si.dwPageSize, td[i].prot, &old_prot);
3471 if (td[i].prot == PAGE_READONLY || td[i].prot == PAGE_WRITECOPY)
3472 ok(ret, "%d: VirtualProtect(%02x) error %d\n", i, td[i].prot, GetLastError());
3473 else
3475 ok(!ret, "%d: VirtualProtect(%02x) should fail\n", i, td[i].prot);
3476 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3479 UnmapViewOfFile(base);
3480 CloseHandle(hmap);
3482 else
3484 ok(!hmap, "%d: CreateFileMapping should fail\n", i);
3485 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3489 if (page_exec_supported) alloc_prot = PAGE_EXECUTE_READWRITE;
3490 else alloc_prot = PAGE_READWRITE;
3491 SetLastError(0xdeadbeef);
3492 hmap = CreateFileMappingW(hfile, NULL, alloc_prot, 0, si.dwPageSize, NULL);
3493 ok(hmap != 0, "%d: CreateFileMapping error %d\n", i, GetLastError());
3495 for (i = 0; i < ARRAY_SIZE(td); i++)
3497 SetLastError(0xdeadbeef);
3498 base = MapViewOfFile(hmap, FILE_MAP_READ | FILE_MAP_WRITE | (page_exec_supported ? FILE_MAP_EXECUTE : 0), 0, 0, 0);
3499 ok(base != NULL, "MapViewOfFile failed %d\n", GetLastError());
3501 old_prot = 0xdeadbeef;
3502 SetLastError(0xdeadbeef);
3503 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
3504 ok(ret, "VirtualProtect error %d\n", GetLastError());
3505 ok(old_prot == alloc_prot, "got %#x != expected %#x\n", old_prot, alloc_prot);
3507 SetLastError(0xdeadbeef);
3508 ret = VirtualQuery(base, &info, sizeof(info));
3509 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3510 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
3511 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
3512 ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect);
3513 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
3514 ok(info.AllocationProtect == alloc_prot, "%d: %#x != %#x\n", i, info.AllocationProtect, alloc_prot);
3515 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
3516 ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
3518 old_prot = 0xdeadbeef;
3519 SetLastError(0xdeadbeef);
3520 ret = VirtualProtect(base, si.dwPageSize, td[i].prot, &old_prot);
3521 if (td[i].success || td[i].prot == PAGE_NOACCESS || td[i].prot == PAGE_EXECUTE)
3523 if (!ret)
3525 /* win2k and XP don't support EXEC on file mappings */
3526 if (td[i].prot == PAGE_EXECUTE)
3528 ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i);
3529 continue;
3531 /* NT4 and win2k don't support EXEC on file mappings */
3532 if (td[i].prot == PAGE_EXECUTE_READ || td[i].prot == PAGE_EXECUTE_READWRITE)
3534 ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i);
3535 continue;
3537 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3538 if (td[i].prot == PAGE_EXECUTE_WRITECOPY)
3540 ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
3541 continue;
3545 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
3546 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
3548 SetLastError(0xdeadbeef);
3549 ret = VirtualQuery(base, &info, sizeof(info));
3550 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3551 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
3552 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
3553 ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
3554 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
3555 ok(info.AllocationProtect == alloc_prot, "%d: %#x != %#x\n", i, info.AllocationProtect, alloc_prot);
3556 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
3557 ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
3559 if (is_mem_writable(info.Protect))
3561 base[0] = 0xfe;
3563 SetLastError(0xdeadbeef);
3564 ret = VirtualQuery(base, &info, sizeof(info));
3565 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3566 /* FIXME: remove the condition below once Wine is fixed */
3567 todo_wine_if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
3568 ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
3571 else
3573 ok(!ret, "%d: VirtualProtect should fail\n", i);
3574 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3575 continue;
3578 old_prot = 0xdeadbeef;
3579 SetLastError(0xdeadbeef);
3580 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
3581 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
3582 /* FIXME: remove the condition below once Wine is fixed */
3583 todo_wine_if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
3584 ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
3586 UnmapViewOfFile(base);
3589 CloseHandle(hmap);
3591 CloseHandle(hfile);
3592 DeleteFileA(file_name);
3595 #define ACCESS_READ 0x01
3596 #define ACCESS_WRITE 0x02
3597 #define ACCESS_EXECUTE 0x04
3599 static DWORD page_prot_to_access(DWORD prot)
3601 switch (prot)
3603 case PAGE_READONLY:
3604 case PAGE_WRITECOPY:
3605 return ACCESS_READ;
3606 case PAGE_READWRITE:
3607 return ACCESS_READ | ACCESS_WRITE;
3608 case PAGE_EXECUTE:
3609 case PAGE_EXECUTE_READ:
3610 case PAGE_EXECUTE_WRITECOPY:
3611 return ACCESS_READ | ACCESS_EXECUTE;
3612 case PAGE_EXECUTE_READWRITE:
3613 return ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE;
3614 default:
3615 return 0;
3619 static BOOL is_compatible_protection(DWORD view_prot, DWORD prot)
3621 DWORD view_access, prot_access;
3623 view_access = page_prot_to_access(view_prot);
3624 prot_access = page_prot_to_access(prot);
3626 return ((view_access & prot_access) == prot_access);
3629 static DWORD map_prot_to_access(DWORD prot)
3631 switch (prot)
3633 case PAGE_READWRITE:
3634 return SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY;
3635 case PAGE_EXECUTE_READWRITE:
3636 return SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE | SECTION_QUERY;
3637 case PAGE_READONLY:
3638 case PAGE_WRITECOPY:
3639 return SECTION_MAP_READ | SECTION_QUERY;
3640 case PAGE_EXECUTE:
3641 case PAGE_EXECUTE_READ:
3642 case PAGE_EXECUTE_WRITECOPY:
3643 return SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_QUERY;
3644 default:
3645 return 0;
3649 static DWORD map_prot_no_write(DWORD prot)
3651 switch (prot)
3653 case PAGE_READWRITE: return PAGE_WRITECOPY;
3654 case PAGE_EXECUTE_READWRITE: return PAGE_EXECUTE_WRITECOPY;
3655 default: return prot;
3659 static DWORD map_prot_written(DWORD prot)
3661 switch (prot)
3663 case PAGE_WRITECOPY: return PAGE_READWRITE;
3664 case PAGE_EXECUTE_WRITECOPY: return PAGE_EXECUTE_READWRITE;
3665 default: return prot;
3669 static DWORD file_access_to_prot( DWORD access )
3671 BOOL exec = access & FILE_MAP_EXECUTE;
3672 access &= ~FILE_MAP_EXECUTE;
3674 if (access == FILE_MAP_COPY) return exec ? PAGE_EXECUTE_WRITECOPY : PAGE_WRITECOPY;
3675 if (access & FILE_MAP_WRITE) return exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
3676 if (access & FILE_MAP_READ) return exec ? PAGE_EXECUTE_READ : PAGE_READONLY;
3677 return PAGE_NOACCESS;
3680 static BOOL is_compatible_access(DWORD map_prot, DWORD view_prot)
3682 DWORD access = map_prot_to_access(map_prot);
3683 DWORD view_access = map_prot_to_access( file_access_to_prot( view_prot ));
3684 if (!view_access) view_access = SECTION_MAP_READ;
3685 return (view_access & access) == view_access;
3688 static void *map_view_of_file(HANDLE handle, DWORD access)
3690 NTSTATUS status;
3691 LARGE_INTEGER offset;
3692 SIZE_T count;
3693 ULONG protect;
3694 void *addr;
3696 if (!pNtMapViewOfSection) return NULL;
3698 count = 0;
3699 offset.u.LowPart = 0;
3700 offset.u.HighPart = 0;
3702 protect = file_access_to_prot( access );
3703 addr = NULL;
3704 status = pNtMapViewOfSection(handle, GetCurrentProcess(), &addr, 0, 0, &offset,
3705 &count, 1 /* ViewShare */, 0, protect);
3706 if ((int)status < 0) addr = NULL;
3707 return addr;
3710 static void test_mapping( HANDLE hfile, DWORD sec_flags, BOOL readonly )
3712 static const DWORD page_prot[] =
3714 PAGE_NOACCESS, PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY,
3715 PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY
3717 static const struct
3719 DWORD access, prot;
3720 } view[] =
3722 { 0, PAGE_NOACCESS }, /* 0x00 */
3723 { FILE_MAP_COPY, PAGE_WRITECOPY }, /* 0x01 */
3724 { FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x02 */
3725 { FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x03 */
3726 { FILE_MAP_READ, PAGE_READONLY }, /* 0x04 */
3727 { FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x05 */
3728 { FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x06 */
3729 { FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x07 */
3730 { SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x08 */
3731 { SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x09 */
3732 { SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0a */
3733 { SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0b */
3734 { SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_READONLY }, /* 0x0c */
3735 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x0d */
3736 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0e */
3737 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0f */
3738 { FILE_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x20 */
3739 { FILE_MAP_EXECUTE | FILE_MAP_COPY, PAGE_EXECUTE_WRITECOPY }, /* 0x21 */
3740 { FILE_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x22 */
3741 { FILE_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x23 */
3742 { FILE_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x24 */
3743 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x25 */
3744 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x26 */
3745 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x27 */
3746 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x28 */
3747 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x29 */
3748 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2a */
3749 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x2b */
3750 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x2c */
3751 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x2d */
3752 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2e */
3753 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE } /* 0x2f */
3755 void *base, *nt_base, *ptr;
3756 DWORD i, j, k, ret, old_prot, prev_prot, alloc_prot;
3757 HANDLE hmap;
3758 MEMORY_BASIC_INFORMATION info, nt_info;
3759 BOOL anon_mapping = (hfile == INVALID_HANDLE_VALUE);
3761 trace( "testing %s mapping flags %08x %s\n", anon_mapping ? "anonymous" : "file",
3762 sec_flags, readonly ? "readonly file" : "" );
3763 for (i = 0; i < ARRAY_SIZE(page_prot); i++)
3765 SetLastError(0xdeadbeef);
3766 hmap = CreateFileMappingW(hfile, NULL, page_prot[i] | sec_flags, 0, 2*si.dwPageSize, NULL);
3768 if (readonly && (page_prot[i] == PAGE_READWRITE || page_prot[i] == PAGE_EXECUTE_READ
3769 || page_prot[i] == PAGE_EXECUTE_READWRITE || page_prot[i] == PAGE_EXECUTE_WRITECOPY))
3771 todo_wine_if(page_prot[i] == PAGE_EXECUTE_READ || page_prot[i] == PAGE_EXECUTE_WRITECOPY)
3773 ok(!hmap, "%d: CreateFileMapping(%04x) should fail\n", i, page_prot[i]);
3774 ok(GetLastError() == ERROR_ACCESS_DENIED || broken(GetLastError() == ERROR_INVALID_PARAMETER),
3775 "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3777 if (hmap) CloseHandle(hmap);
3778 continue;
3781 if (page_prot[i] == PAGE_NOACCESS)
3783 HANDLE hmap2;
3785 ok(!hmap, "CreateFileMapping(PAGE_NOACCESS) should fail\n");
3786 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3788 /* A trick to create a not accessible mapping */
3789 SetLastError(0xdeadbeef);
3790 if (sec_flags & SEC_IMAGE)
3791 hmap = CreateFileMappingW(hfile, NULL, PAGE_WRITECOPY | sec_flags, 0, si.dwPageSize, NULL);
3792 else
3793 hmap = CreateFileMappingW(hfile, NULL, PAGE_READONLY | sec_flags, 0, si.dwPageSize, NULL);
3794 ok(hmap != 0, "CreateFileMapping(PAGE_READWRITE) error %d\n", GetLastError());
3795 SetLastError(0xdeadbeef);
3796 ret = DuplicateHandle(GetCurrentProcess(), hmap, GetCurrentProcess(), &hmap2, 0, FALSE, 0);
3797 ok(ret, "DuplicateHandle error %d\n", GetLastError());
3798 CloseHandle(hmap);
3799 hmap = hmap2;
3801 if (page_prot[i] == PAGE_EXECUTE)
3803 ok(!hmap, "CreateFileMapping(PAGE_EXECUTE) should fail\n");
3804 ok(GetLastError() == ERROR_INVALID_PARAMETER,
3805 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3806 continue;
3809 if (!hmap)
3811 trace("%d: CreateFileMapping(%04x) failed: %d\n", i, page_prot[i], GetLastError());
3813 if ((sec_flags & SEC_IMAGE) &&
3814 (page_prot[i] == PAGE_READWRITE || page_prot[i] == PAGE_EXECUTE_READWRITE))
3815 continue; /* SEC_IMAGE doesn't support write access */
3817 /* NT4 and win2k don't support EXEC on file mappings */
3818 if (page_prot[i] == PAGE_EXECUTE_READ || page_prot[i] == PAGE_EXECUTE_READWRITE)
3820 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i);
3821 continue;
3823 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3824 if (page_prot[i] == PAGE_EXECUTE_WRITECOPY)
3826 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
3827 continue;
3831 ok(hmap != 0, "%d: CreateFileMapping(%04x) error %d\n", i, page_prot[i], GetLastError());
3833 for (j = 0; j < ARRAY_SIZE(view); j++)
3835 nt_base = map_view_of_file(hmap, view[j].access);
3836 if (nt_base)
3838 SetLastError(0xdeadbeef);
3839 ret = VirtualQuery(nt_base, &nt_info, sizeof(nt_info));
3840 ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
3841 UnmapViewOfFile(nt_base);
3844 SetLastError(0xdeadbeef);
3845 base = MapViewOfFile(hmap, view[j].access, 0, 0, 0);
3847 /* Vista+ supports FILE_MAP_EXECUTE properly, earlier versions don't */
3848 ok(!nt_base == !base ||
3849 broken((view[j].access & FILE_MAP_EXECUTE) && !nt_base != !base),
3850 "%d: (%04x/%04x) NT %p kernel %p\n", j, page_prot[i], view[j].access, nt_base, base);
3852 if (!is_compatible_access(page_prot[i], view[j].access))
3854 /* FILE_MAP_EXECUTE | FILE_MAP_COPY broken on XP */
3855 if (base != NULL && view[j].access == (FILE_MAP_EXECUTE | FILE_MAP_COPY))
3857 ok( broken(base != NULL), "%d: MapViewOfFile(%04x/%04x) should fail\n",
3858 j, page_prot[i], view[j].access);
3859 UnmapViewOfFile( base );
3861 else
3863 ok(!base, "%d: MapViewOfFile(%04x/%04x) should fail\n",
3864 j, page_prot[i], view[j].access);
3865 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
3867 continue;
3870 /* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */
3871 if (!base && (view[j].access & FILE_MAP_EXECUTE))
3873 ok(broken(!base), "%d: MapViewOfFile(%04x/%04x) failed %d\n", j, page_prot[i], view[j].access, GetLastError());
3874 continue;
3877 ok(base != NULL, "%d: MapViewOfFile(%04x/%04x) failed %d\n", j, page_prot[i], view[j].access, GetLastError());
3879 SetLastError(0xdeadbeef);
3880 ret = VirtualQuery(base, &info, sizeof(info));
3881 ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
3882 ok(info.BaseAddress == base, "%d: (%04x) got %p, expected %p\n", j, view[j].access, info.BaseAddress, base);
3883 ok(info.RegionSize == 2*si.dwPageSize || (info.RegionSize == si.dwPageSize && (sec_flags & SEC_IMAGE)),
3884 "%d: (%04x) got %#lx != expected %#x\n", j, view[j].access, info.RegionSize, 2*si.dwPageSize);
3885 if (sec_flags & SEC_IMAGE)
3886 ok(info.Protect == PAGE_READONLY,
3887 "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.Protect, view[j].prot);
3888 else
3889 ok(info.Protect == view[j].prot ||
3890 broken(view[j].prot == PAGE_EXECUTE_READ && info.Protect == PAGE_READONLY) || /* win2k */
3891 broken(view[j].prot == PAGE_EXECUTE_READWRITE && info.Protect == PAGE_READWRITE) || /* win2k */
3892 broken(view[j].prot == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
3893 "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.Protect, view[j].prot);
3894 ok(info.AllocationBase == base, "%d: (%04x) got %p, expected %p\n", j, view[j].access, info.AllocationBase, base);
3895 if (sec_flags & SEC_IMAGE)
3896 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: (%04x) got %#x, expected %#x\n",
3897 j, view[j].access, info.AllocationProtect, info.Protect);
3898 else
3899 ok(info.AllocationProtect == info.Protect, "%d: (%04x) got %#x, expected %#x\n",
3900 j, view[j].access, info.AllocationProtect, info.Protect);
3901 ok(info.State == MEM_COMMIT, "%d: (%04x) got %#x, expected MEM_COMMIT\n", j, view[j].access, info.State);
3902 ok(info.Type == (sec_flags & SEC_IMAGE) ? SEC_IMAGE : MEM_MAPPED,
3903 "%d: (%04x) got %#x, expected MEM_MAPPED\n", j, view[j].access, info.Type);
3905 if (nt_base && base)
3907 ok(nt_info.RegionSize == info.RegionSize, "%d: (%04x) got %#lx != expected %#lx\n", j, view[j].access, nt_info.RegionSize, info.RegionSize);
3908 ok(nt_info.Protect == info.Protect /* Vista+ */ ||
3909 broken(nt_info.AllocationProtect == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
3910 "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.Protect, info.Protect);
3911 ok(nt_info.AllocationProtect == info.AllocationProtect /* Vista+ */ ||
3912 broken(nt_info.AllocationProtect == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
3913 "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.AllocationProtect, info.AllocationProtect);
3914 ok(nt_info.State == info.State, "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.State, info.State);
3915 ok(nt_info.Type == info.Type, "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.Type, info.Type);
3918 prev_prot = info.Protect;
3919 alloc_prot = info.AllocationProtect;
3921 for (k = 0; k < ARRAY_SIZE(page_prot); k++)
3923 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3924 DWORD actual_prot = (sec_flags & SEC_IMAGE) ? map_prot_no_write(page_prot[k]) : page_prot[k];
3925 SetLastError(0xdeadbeef);
3926 old_prot = 0xdeadbeef;
3927 ret = VirtualProtect(base, si.dwPageSize, page_prot[k], &old_prot);
3928 if (is_compatible_protection(alloc_prot, actual_prot))
3930 /* win2k and XP don't support EXEC on file mappings */
3931 if (!ret && (page_prot[k] == PAGE_EXECUTE || page_prot[k] == PAGE_EXECUTE_WRITECOPY || view[j].prot == PAGE_EXECUTE_WRITECOPY))
3933 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3934 continue;
3937 todo_wine_if(readonly && page_prot[k] == PAGE_WRITECOPY && view[j].prot != PAGE_WRITECOPY)
3938 ok(ret, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot[i], view[j].prot, page_prot[k]);
3939 todo_wine_if(readonly && page_prot[k] == PAGE_WRITECOPY && view[j].prot != PAGE_WRITECOPY)
3940 ok(old_prot == prev_prot, "got %#x, expected %#x\n", old_prot, prev_prot);
3941 prev_prot = actual_prot;
3943 ret = VirtualQuery(base, &info, sizeof(info));
3944 ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
3945 todo_wine_if(readonly && page_prot[k] == PAGE_WRITECOPY && view[j].prot != PAGE_WRITECOPY)
3946 ok(info.Protect == actual_prot,
3947 "VirtualProtect wrong prot, map %#x, view %#x, requested prot %#x got %#x\n",
3948 page_prot[i], view[j].prot, page_prot[k], info.Protect );
3950 else
3952 ok(!ret, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
3953 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3957 for (k = 0; k < ARRAY_SIZE(page_prot); k++)
3959 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3960 SetLastError(0xdeadbeef);
3961 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, page_prot[k]);
3962 if (anon_mapping)
3964 if (is_compatible_protection(view[j].prot, page_prot[k]))
3966 ok(ptr != NULL, "VirtualAlloc error %u, map %#x, view %#x, requested prot %#x\n",
3967 GetLastError(), page_prot[i], view[j].prot, page_prot[k]);
3969 else
3971 /* versions <= Vista accept all protections without checking */
3972 ok(!ptr || broken(ptr != NULL),
3973 "VirtualAlloc should fail, map %#x, view %#x, requested prot %#x\n",
3974 page_prot[i], view[j].prot, page_prot[k]);
3975 if (!ptr) ok( GetLastError() == ERROR_INVALID_PARAMETER,
3976 "wrong error %u\n", GetLastError());
3978 if (ptr)
3980 ret = VirtualQuery(base, &info, sizeof(info));
3981 ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
3982 ok(info.Protect == page_prot[k] ||
3983 /* if the mapping doesn't have write access,
3984 * broken versions silently switch to WRITECOPY */
3985 broken( info.Protect == map_prot_no_write(page_prot[k]) ),
3986 "VirtualAlloc wrong prot, map %#x, view %#x, requested prot %#x got %#x\n",
3987 page_prot[i], view[j].prot, page_prot[k], info.Protect );
3990 else
3992 ok(!ptr, "VirtualAlloc(%02x) should fail\n", page_prot[k]);
3993 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3997 if (!anon_mapping && is_compatible_protection(alloc_prot, PAGE_WRITECOPY))
3999 ret = VirtualProtect(base, sec_flags & SEC_IMAGE ? si.dwPageSize : 2*si.dwPageSize, PAGE_WRITECOPY, &old_prot);
4000 todo_wine_if(readonly && view[j].prot != PAGE_WRITECOPY)
4001 ok(ret, "VirtualProtect error %d, map %#x, view %#x\n", GetLastError(), page_prot[i], view[j].prot);
4002 if (ret) *(DWORD*)base = 0xdeadbeef;
4003 ret = VirtualQuery(base, &info, sizeof(info));
4004 ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
4005 todo_wine
4006 ok(info.Protect == PAGE_READWRITE, "VirtualProtect wrong prot, map %#x, view %#x got %#x\n",
4007 page_prot[i], view[j].prot, info.Protect );
4008 todo_wine_if (!(sec_flags & SEC_IMAGE))
4009 ok(info.RegionSize == si.dwPageSize, "wrong region size %#lx after write, map %#x, view %#x got %#x\n",
4010 info.RegionSize, page_prot[i], view[j].prot, info.Protect );
4012 prev_prot = info.Protect;
4013 alloc_prot = info.AllocationProtect;
4015 if (!(sec_flags & SEC_IMAGE))
4017 ret = VirtualQuery((char*)base + si.dwPageSize, &info, sizeof(info));
4018 ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
4019 todo_wine_if(readonly && view[j].prot != PAGE_WRITECOPY)
4020 ok(info.Protect == PAGE_WRITECOPY, "wrong prot, map %#x, view %#x got %#x\n",
4021 page_prot[i], view[j].prot, info.Protect);
4024 for (k = 0; k < ARRAY_SIZE(page_prot); k++)
4026 DWORD actual_prot = (sec_flags & SEC_IMAGE) ? map_prot_no_write(page_prot[k]) : page_prot[k];
4027 SetLastError(0xdeadbeef);
4028 old_prot = 0xdeadbeef;
4029 ret = VirtualProtect(base, si.dwPageSize, page_prot[k], &old_prot);
4030 if (is_compatible_protection(alloc_prot, actual_prot))
4032 /* win2k and XP don't support EXEC on file mappings */
4033 if (!ret && (page_prot[k] == PAGE_EXECUTE || page_prot[k] == PAGE_EXECUTE_WRITECOPY || view[j].prot == PAGE_EXECUTE_WRITECOPY))
4035 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n");
4036 continue;
4039 todo_wine_if(readonly && page_prot[k] == PAGE_WRITECOPY && view[j].prot != PAGE_WRITECOPY)
4040 ok(ret, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot[i], view[j].prot, page_prot[k]);
4041 todo_wine_if(readonly && page_prot[k] == PAGE_WRITECOPY && view[j].prot != PAGE_WRITECOPY)
4042 ok(old_prot == prev_prot, "got %#x, expected %#x\n", old_prot, prev_prot);
4044 ret = VirtualQuery(base, &info, sizeof(info));
4045 ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
4046 todo_wine_if( map_prot_written( page_prot[k] ) != actual_prot )
4047 ok(info.Protect == map_prot_written( page_prot[k] ),
4048 "VirtualProtect wrong prot, map %#x, view %#x, requested prot %#x got %#x\n",
4049 page_prot[i], view[j].prot, page_prot[k], info.Protect );
4050 prev_prot = info.Protect;
4052 else
4054 ok(!ret, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
4055 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
4059 UnmapViewOfFile(base);
4062 CloseHandle(hmap);
4066 static void test_mappings(void)
4068 char temp_path[MAX_PATH];
4069 char file_name[MAX_PATH];
4070 DWORD data, num_bytes;
4071 HANDLE hfile;
4073 GetTempPathA(MAX_PATH, temp_path);
4074 GetTempFileNameA(temp_path, "map", 0, file_name);
4076 hfile = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
4077 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
4078 SetFilePointer(hfile, 2*si.dwPageSize, NULL, FILE_BEGIN);
4079 SetEndOfFile(hfile);
4081 test_mapping( hfile, SEC_COMMIT, FALSE );
4083 /* test that file was not modified */
4084 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4085 ok(ReadFile(hfile, &data, sizeof(data), &num_bytes, NULL), "ReadFile failed\n");
4086 ok(num_bytes == sizeof(data), "num_bytes = %d\n", num_bytes);
4087 todo_wine
4088 ok(!data, "data = %x\n", data);
4090 CloseHandle( hfile );
4092 hfile = CreateFileA(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
4093 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
4095 test_mapping( hfile, SEC_COMMIT, TRUE );
4097 CloseHandle( hfile );
4098 DeleteFileA( file_name );
4100 /* SEC_IMAGE mapping */
4101 GetSystemDirectoryA( file_name, MAX_PATH );
4102 strcat( file_name, "\\kernel32.dll" );
4104 hfile = CreateFileA( file_name, GENERIC_READ|GENERIC_EXECUTE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
4105 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
4107 test_mapping( hfile, SEC_IMAGE, FALSE );
4109 CloseHandle( hfile );
4111 /* now anonymous mappings */
4112 test_mapping( INVALID_HANDLE_VALUE, SEC_COMMIT, FALSE );
4115 static void test_shared_memory(BOOL is_child)
4117 HANDLE mapping;
4118 LONG *p;
4120 SetLastError(0xdeadbef);
4121 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_virtual.c");
4122 ok(mapping != 0, "CreateFileMapping error %d\n", GetLastError());
4123 if (is_child)
4124 ok(GetLastError() == ERROR_ALREADY_EXISTS, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
4126 SetLastError(0xdeadbef);
4127 p = MapViewOfFile(mapping, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 4096);
4128 ok(p != NULL, "MapViewOfFile error %d\n", GetLastError());
4130 if (is_child)
4132 ok(*p == 0x1a2b3c4d, "expected 0x1a2b3c4d in child, got %#x\n", *p);
4134 else
4136 char **argv;
4137 char cmdline[MAX_PATH];
4138 PROCESS_INFORMATION pi;
4139 STARTUPINFOA si = { sizeof(si) };
4140 DWORD ret;
4142 *p = 0x1a2b3c4d;
4144 winetest_get_mainargs(&argv);
4145 sprintf(cmdline, "\"%s\" virtual sharedmem", argv[0]);
4146 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
4147 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
4148 wait_child_process(pi.hProcess);
4149 CloseHandle(pi.hThread);
4150 CloseHandle(pi.hProcess);
4153 UnmapViewOfFile(p);
4154 CloseHandle(mapping);
4157 static void test_shared_memory_ro(BOOL is_child, DWORD child_access)
4159 HANDLE mapping;
4160 LONG *p;
4162 SetLastError(0xdeadbef);
4163 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_virtual.c_ro");
4164 ok(mapping != 0, "CreateFileMapping error %d\n", GetLastError());
4165 if (is_child)
4166 ok(GetLastError() == ERROR_ALREADY_EXISTS, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
4168 SetLastError(0xdeadbef);
4169 p = MapViewOfFile(mapping, is_child ? child_access : FILE_MAP_READ, 0, 0, 4096);
4170 ok(p != NULL, "MapViewOfFile error %d\n", GetLastError());
4172 if (is_child)
4174 *p = 0xdeadbeef;
4176 else
4178 char **argv;
4179 char cmdline[MAX_PATH];
4180 PROCESS_INFORMATION pi;
4181 STARTUPINFOA si = { sizeof(si) };
4182 DWORD ret;
4184 winetest_get_mainargs(&argv);
4185 sprintf(cmdline, "\"%s\" virtual sharedmemro %x", argv[0], child_access);
4186 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
4187 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
4188 wait_child_process(pi.hProcess);
4189 CloseHandle(pi.hThread);
4190 CloseHandle(pi.hProcess);
4192 if(child_access & FILE_MAP_WRITE)
4193 ok(*p == 0xdeadbeef, "*p = %x, expected 0xdeadbeef\n", *p);
4194 else
4195 ok(!*p, "*p = %x, expected 0\n", *p);
4198 UnmapViewOfFile(p);
4199 CloseHandle(mapping);
4202 START_TEST(virtual)
4204 int argc;
4205 char **argv;
4206 argc = winetest_get_mainargs( &argv );
4208 if (argc >= 3)
4210 if (!strcmp(argv[2], "sleep"))
4212 Sleep(5000); /* spawned process runs for at most 5 seconds */
4213 return;
4215 if (!strcmp(argv[2], "sharedmem"))
4217 test_shared_memory(TRUE);
4218 return;
4220 if (!strcmp(argv[2], "sharedmemro"))
4222 test_shared_memory_ro(TRUE, strtol(argv[3], NULL, 16));
4223 return;
4225 while (1)
4227 void *mem;
4228 BOOL ret;
4229 mem = VirtualAlloc(NULL, 1<<20, MEM_COMMIT|MEM_RESERVE,
4230 PAGE_EXECUTE_READWRITE);
4231 ok(mem != NULL, "VirtualAlloc failed %u\n", GetLastError());
4232 if (mem == NULL) break;
4233 ret = VirtualFree(mem, 0, MEM_RELEASE);
4234 ok(ret, "VirtualFree failed %u\n", GetLastError());
4235 if (!ret) break;
4237 return;
4240 hkernel32 = GetModuleHandleA("kernel32.dll");
4241 hntdll = GetModuleHandleA("ntdll.dll");
4243 pGetWriteWatch = (void *) GetProcAddress(hkernel32, "GetWriteWatch");
4244 pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch");
4245 pGetProcessDEPPolicy = (void *)GetProcAddress( hkernel32, "GetProcessDEPPolicy" );
4246 pIsWow64Process = (void *)GetProcAddress( hkernel32, "IsWow64Process" );
4247 pNtAreMappedFilesTheSame = (void *)GetProcAddress( hntdll, "NtAreMappedFilesTheSame" );
4248 pNtCreateSection = (void *)GetProcAddress( hntdll, "NtCreateSection" );
4249 pNtMapViewOfSection = (void *)GetProcAddress( hntdll, "NtMapViewOfSection" );
4250 pNtUnmapViewOfSection = (void *)GetProcAddress( hntdll, "NtUnmapViewOfSection" );
4251 pNtQuerySection = (void *)GetProcAddress( hntdll, "NtQuerySection" );
4252 pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlAddVectoredExceptionHandler" );
4253 pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlRemoveVectoredExceptionHandler" );
4254 pNtProtectVirtualMemory = (void *)GetProcAddress( hntdll, "NtProtectVirtualMemory" );
4256 GetSystemInfo(&si);
4257 trace("system page size %#x\n", si.dwPageSize);
4259 test_shared_memory(FALSE);
4260 test_shared_memory_ro(FALSE, FILE_MAP_READ|FILE_MAP_WRITE);
4261 test_shared_memory_ro(FALSE, FILE_MAP_COPY);
4262 test_shared_memory_ro(FALSE, FILE_MAP_COPY|FILE_MAP_WRITE);
4263 test_mappings();
4264 test_CreateFileMapping_protection();
4265 test_VirtualAlloc_protection();
4266 test_VirtualProtect();
4267 test_VirtualAllocEx();
4268 test_VirtualAlloc();
4269 test_MapViewOfFile();
4270 test_NtAreMappedFilesTheSame();
4271 test_CreateFileMapping();
4272 test_IsBadReadPtr();
4273 test_IsBadWritePtr();
4274 test_IsBadCodePtr();
4275 test_write_watch();
4276 #if defined(__i386__) || defined(__x86_64__)
4277 test_stack_commit();
4278 #endif
4279 #ifdef __i386__
4280 test_guard_page();
4281 /* The following tests should be executed as a last step, and in exactly this
4282 * order, since ATL thunk emulation cannot be enabled anymore on Windows. */
4283 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE );
4284 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE );
4285 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION );
4286 #endif