ntdll: Implement the SectionBasicInformation class of NtQuerySection.
[wine.git] / dlls / kernel32 / tests / virtual.c
blob37d3c6282e780b191c7d8cd6d176759318d4c850
1 /*
2 * Unit test suite for Virtual* family of APIs.
4 * Copyright 2004 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnt.h"
29 #include "winternl.h"
30 #include "winerror.h"
31 #include "winuser.h"
32 #include "excpt.h"
33 #include "wine/test.h"
35 #define NUM_THREADS 4
36 #define MAPPING_SIZE 0x100000
38 static HINSTANCE hkernel32, hntdll;
39 static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
40 static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
41 static UINT (WINAPI *pGetWriteWatch)(DWORD,LPVOID,SIZE_T,LPVOID*,ULONG_PTR*,ULONG*);
42 static UINT (WINAPI *pResetWriteWatch)(LPVOID,SIZE_T);
43 static NTSTATUS (WINAPI *pNtAreMappedFilesTheSame)(PVOID,PVOID);
44 static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *,
45 const LARGE_INTEGER *, ULONG, ULONG, HANDLE );
46 static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG);
47 static DWORD (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID);
48 static NTSTATUS (WINAPI *pNtQuerySection)(HANDLE, SECTION_INFORMATION_CLASS, void *, ULONG, ULONG *);
49 static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG, PVECTORED_EXCEPTION_HANDLER);
50 static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
51 static BOOL (WINAPI *pGetProcessDEPPolicy)(HANDLE, LPDWORD, PBOOL);
52 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
53 static NTSTATUS (WINAPI *pNtProtectVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG *);
54 static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG);
55 static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
57 /* ############################### */
59 static HANDLE create_target_process(const char *arg)
61 char **argv;
62 char cmdline[MAX_PATH];
63 PROCESS_INFORMATION pi;
64 BOOL ret;
65 STARTUPINFOA si = { 0 };
66 si.cb = sizeof(si);
68 winetest_get_mainargs( &argv );
69 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
70 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
71 ok(ret, "error: %u\n", GetLastError());
72 ret = CloseHandle(pi.hThread);
73 ok(ret, "error %u\n", GetLastError());
74 return pi.hProcess;
77 static void test_VirtualAllocEx(void)
79 const unsigned int alloc_size = 1<<15;
80 char *src, *dst;
81 SIZE_T bytes_written = 0, bytes_read = 0, i;
82 void *addr1, *addr2;
83 BOOL b;
84 DWORD old_prot;
85 MEMORY_BASIC_INFORMATION info;
86 HANDLE hProcess;
88 /* not exported in all windows-versions */
89 if ((!pVirtualAllocEx) || (!pVirtualFreeEx)) {
90 win_skip("Virtual{Alloc,Free}Ex not available\n");
91 return;
94 hProcess = create_target_process("sleep");
95 ok(hProcess != NULL, "Can't start process\n");
97 SetLastError(0xdeadbeef);
98 addr1 = pVirtualAllocEx(hProcess, NULL, alloc_size, MEM_COMMIT,
99 PAGE_EXECUTE_READWRITE);
100 ok(addr1 != NULL, "VirtualAllocEx error %u\n", GetLastError());
102 src = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE );
103 dst = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE );
104 for (i = 0; i < alloc_size; i++)
105 src[i] = i & 0xff;
107 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
108 ok(b && (bytes_written == alloc_size), "%lu bytes written\n",
109 bytes_written);
110 b = ReadProcessMemory(hProcess, addr1, dst, alloc_size, &bytes_read);
111 ok(b && (bytes_read == alloc_size), "%lu bytes read\n", bytes_read);
112 ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n");
114 /* test invalid source buffers */
116 b = VirtualProtect( src + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot );
117 ok( b, "VirtualProtect failed error %u\n", GetLastError() );
118 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
119 ok( !b, "WriteProcessMemory succeeded\n" );
120 ok( GetLastError() == ERROR_NOACCESS ||
121 GetLastError() == ERROR_PARTIAL_COPY, /* vista */
122 "wrong error %u\n", GetLastError() );
123 ok( bytes_written == 0, "%lu bytes written\n", bytes_written );
124 b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
125 ok( !b, "ReadProcessMemory succeeded\n" );
126 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
127 ok( bytes_read == 0, "%lu bytes written\n", bytes_read );
129 b = VirtualProtect( src, 0x2000, PAGE_NOACCESS, &old_prot );
130 ok( b, "VirtualProtect failed error %u\n", GetLastError() );
131 b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
132 ok( !b, "WriteProcessMemory succeeded\n" );
133 ok( GetLastError() == ERROR_NOACCESS ||
134 GetLastError() == ERROR_PARTIAL_COPY, /* vista */
135 "wrong error %u\n", GetLastError() );
136 ok( bytes_written == 0, "%lu bytes written\n", bytes_written );
137 b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
138 ok( !b, "ReadProcessMemory succeeded\n" );
139 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
140 ok( bytes_read == 0, "%lu bytes written\n", bytes_read );
142 b = pVirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE);
143 ok(b != 0, "VirtualFreeEx, error %u\n", GetLastError());
145 VirtualFree( src, 0, MEM_RELEASE );
146 VirtualFree( dst, 0, MEM_RELEASE );
149 * The following tests parallel those in test_VirtualAlloc()
152 SetLastError(0xdeadbeef);
153 addr1 = pVirtualAllocEx(hProcess, 0, 0, MEM_RESERVE, PAGE_NOACCESS);
154 ok(addr1 == NULL, "VirtualAllocEx should fail on zero-sized allocation\n");
155 ok(GetLastError() == ERROR_INVALID_PARAMETER,
156 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
158 addr1 = pVirtualAllocEx(hProcess, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
159 ok(addr1 != NULL, "VirtualAllocEx failed\n");
161 /* test a not committed memory */
162 memset(&info, 'q', sizeof(info));
163 ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info), "VirtualQueryEx failed\n");
164 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
165 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
166 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
167 ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
168 ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
169 ok(info.Protect == 0, "%x != PAGE_NOACCESS\n", info.Protect);
170 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
172 SetLastError(0xdeadbeef);
173 ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
174 "VirtualProtectEx should fail on a not committed memory\n");
175 ok(GetLastError() == ERROR_INVALID_ADDRESS,
176 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
178 addr2 = pVirtualAllocEx(hProcess, addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS);
179 ok(addr1 == addr2, "VirtualAllocEx failed\n");
181 /* test a committed memory */
182 ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info),
183 "VirtualQueryEx failed\n");
184 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
185 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
186 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
187 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
188 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
189 /* this time NT reports PAGE_NOACCESS as well */
190 ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
191 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
193 /* this should fail, since not the whole range is committed yet */
194 SetLastError(0xdeadbeef);
195 ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
196 "VirtualProtectEx should fail on a not committed memory\n");
197 ok(GetLastError() == ERROR_INVALID_ADDRESS,
198 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
200 old_prot = 0;
201 ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtectEx failed\n");
202 ok(old_prot == PAGE_NOACCESS, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
204 old_prot = 0;
205 ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtectEx failed\n");
206 ok(old_prot == PAGE_READONLY, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
208 ok(!pVirtualFreeEx(hProcess, addr1, 0x10000, 0),
209 "VirtualFreeEx should fail with type 0\n");
210 ok(GetLastError() == ERROR_INVALID_PARAMETER,
211 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
213 ok(pVirtualFreeEx(hProcess, addr1, 0x10000, MEM_DECOMMIT), "VirtualFreeEx failed\n");
215 /* if the type is MEM_RELEASE, size must be 0 */
216 ok(!pVirtualFreeEx(hProcess, addr1, 1, MEM_RELEASE),
217 "VirtualFreeEx should fail\n");
218 ok(GetLastError() == ERROR_INVALID_PARAMETER,
219 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
221 ok(pVirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE), "VirtualFreeEx failed\n");
223 TerminateProcess(hProcess, 0);
224 CloseHandle(hProcess);
227 static void test_VirtualAlloc(void)
229 void *addr1, *addr2;
230 DWORD old_prot;
231 MEMORY_BASIC_INFORMATION info;
232 NTSTATUS status;
233 SIZE_T size;
235 SetLastError(0xdeadbeef);
236 addr1 = VirtualAlloc(0, 0, MEM_RESERVE, PAGE_NOACCESS);
237 ok(addr1 == NULL, "VirtualAlloc should fail on zero-sized allocation\n");
238 ok(GetLastError() == ERROR_INVALID_PARAMETER,
239 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
241 addr1 = VirtualAlloc(0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
242 ok(addr1 != NULL, "VirtualAlloc failed\n");
244 /* test a not committed memory */
245 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
246 "VirtualQuery failed\n");
247 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
248 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
249 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
250 ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
251 ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
252 ok(info.Protect == 0, "%x != PAGE_NOACCESS\n", info.Protect);
253 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
255 SetLastError(0xdeadbeef);
256 ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
257 "VirtualProtect should fail on a not committed memory\n");
258 ok( GetLastError() == ERROR_INVALID_ADDRESS,
259 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
261 addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS);
262 ok(addr1 == addr2, "VirtualAlloc failed\n");
264 /* test a committed memory */
265 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
266 "VirtualQuery failed\n");
267 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
268 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
269 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
270 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
271 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
272 /* this time NT reports PAGE_NOACCESS as well */
273 ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
274 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
276 /* this should fail, since not the whole range is committed yet */
277 SetLastError(0xdeadbeef);
278 ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
279 "VirtualProtect should fail on a not committed memory\n");
280 ok( GetLastError() == ERROR_INVALID_ADDRESS,
281 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
283 ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtect failed\n");
284 ok(old_prot == PAGE_NOACCESS,
285 "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
287 ok(VirtualProtect(addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtect failed\n");
288 ok(old_prot == PAGE_READONLY,
289 "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
291 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
292 "VirtualQuery failed\n");
293 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
294 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
295 ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
296 memset( addr1, 0x55, 20 );
297 ok( *(DWORD *)addr1 == 0x55555555, "wrong data %x\n", *(DWORD *)addr1 );
299 addr2 = VirtualAlloc( addr1, 0x1000, MEM_RESET, PAGE_NOACCESS );
300 ok( addr2 == addr1, "VirtualAlloc failed err %u\n", GetLastError() );
301 ok( *(DWORD *)addr1 == 0x55555555 || *(DWORD *)addr1 == 0, "wrong data %x\n", *(DWORD *)addr1 );
302 ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
303 "VirtualQuery failed\n");
304 ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
305 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
306 ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
308 addr2 = VirtualAlloc( (char *)addr1 + 0x1000, 0x1000, MEM_RESET, PAGE_NOACCESS );
309 ok( (char *)addr2 == (char *)addr1 + 0x1000, "VirtualAlloc failed\n" );
311 ok(VirtualQuery(addr2, &info, sizeof(info)) == sizeof(info),
312 "VirtualQuery failed\n");
313 ok(info.RegionSize == 0xf000, "%lx != 0xf000\n", info.RegionSize);
314 ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
315 ok(info.Protect == 0, "%x != 0\n", info.Protect);
317 addr2 = VirtualAlloc( (char *)addr1 + 0xf000, 0x2000, MEM_RESET, PAGE_NOACCESS );
318 ok( !addr2, "VirtualAlloc failed\n" );
319 ok( GetLastError() == ERROR_INVALID_ADDRESS, "wrong error %u\n", GetLastError() );
321 /* invalid protection values */
322 SetLastError(0xdeadbeef);
323 addr2 = VirtualAlloc(NULL, 0x1000, MEM_RESERVE, 0);
324 ok(!addr2, "VirtualAlloc succeeded\n");
325 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
327 SetLastError(0xdeadbeef);
328 addr2 = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, 0);
329 ok(!addr2, "VirtualAlloc succeeded\n");
330 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
332 SetLastError(0xdeadbeef);
333 addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_READONLY | PAGE_EXECUTE);
334 ok(!addr2, "VirtualAlloc succeeded\n");
335 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
337 SetLastError(0xdeadbeef);
338 ok(!VirtualProtect(addr1, 0x1000, PAGE_READWRITE | PAGE_EXECUTE_WRITECOPY, &old_prot),
339 "VirtualProtect succeeded\n");
340 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
342 SetLastError(0xdeadbeef);
343 ok(!VirtualProtect(addr1, 0x1000, 0, &old_prot), "VirtualProtect succeeded\n");
344 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
346 SetLastError(0xdeadbeef);
347 ok(!VirtualFree(addr1, 0x10000, 0), "VirtualFree should fail with type 0\n");
348 ok(GetLastError() == ERROR_INVALID_PARAMETER,
349 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
351 SetLastError(0xdeadbeef);
352 ok(!VirtualFree(addr1, 0, MEM_FREE), "VirtualFree should fail with type MEM_FREE\n");
353 ok(GetLastError() == ERROR_INVALID_PARAMETER,
354 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
356 ok(VirtualFree(addr1, 0x10000, MEM_DECOMMIT), "VirtualFree failed\n");
358 /* if the type is MEM_RELEASE, size must be 0 */
359 ok(!VirtualFree(addr1, 1, MEM_RELEASE), "VirtualFree should fail\n");
360 ok(GetLastError() == ERROR_INVALID_PARAMETER,
361 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
363 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
365 /* memory returned by VirtualAlloc should be aligned to 64k */
366 addr1 = VirtualAlloc(0, 0x2000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
367 ok(addr1 != NULL, "VirtualAlloc failed\n");
368 ok(!((ULONG_PTR)addr1 & 0xffff), "returned memory %p is not aligned to 64k\n", addr1);
369 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
370 addr2 = VirtualAlloc(addr1, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
371 ok(addr2 == addr1, "VirtualAlloc returned %p, expected %p\n", addr2, addr1);
373 /* allocation conflicts because of 64k align */
374 size = 0x1000;
375 addr2 = (char *)addr1 + 0x1000;
376 status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 0, &size,
377 MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
378 ok(status == STATUS_CONFLICTING_ADDRESSES, "NtAllocateVirtualMemory returned %08x\n", status);
380 /* it should conflict, even when zero_bits is explicitly set */
381 size = 0x1000;
382 addr2 = (char *)addr1 + 0x1000;
383 status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 12, &size,
384 MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
385 todo_wine
386 ok(status == STATUS_CONFLICTING_ADDRESSES, "NtAllocateVirtualMemory returned %08x\n", status);
387 if (status == STATUS_SUCCESS) ok(VirtualFree(addr2, 0, MEM_RELEASE), "VirtualFree failed\n");
389 /* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
390 SetLastError(0xdeadbeef);
391 addr2 = VirtualAlloc(addr1, 0x1000, MEM_RESERVE | MEM_COMMIT | AT_ROUND_TO_PAGE, PAGE_EXECUTE_READWRITE);
392 ok(!addr2, "VirtualAlloc unexpectedly succeeded\n");
393 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
395 /* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
396 size = 0x1000;
397 addr2 = (char *)addr1 + 0x1000;
398 status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 0, &size, MEM_RESERVE |
399 MEM_COMMIT | AT_ROUND_TO_PAGE, PAGE_EXECUTE_READWRITE);
400 todo_wine
401 ok(status == STATUS_INVALID_PARAMETER_5, "NtAllocateVirtualMemory returned %08x\n", status);
403 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
406 static void test_MapViewOfFile(void)
408 static const char testfile[] = "testfile.xxx";
409 const char *name;
410 HANDLE file, mapping, map2;
411 void *ptr, *ptr2, *addr;
412 SECTION_BASIC_INFORMATION section_info;
413 MEMORY_BASIC_INFORMATION info;
414 BOOL ret;
415 SIZE_T size;
416 NTSTATUS status;
417 ULONG info_size;
418 LARGE_INTEGER map_size;
420 SetLastError(0xdeadbeef);
421 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
422 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
423 SetFilePointer( file, 12288, NULL, FILE_BEGIN );
424 SetEndOfFile( file );
426 /* read/write mapping */
428 SetLastError(0xdeadbeef);
429 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
430 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
432 SetLastError(0xdeadbeef);
433 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
434 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
435 UnmapViewOfFile( ptr );
437 SetLastError(0xdeadbeef);
438 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
439 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
440 UnmapViewOfFile( ptr );
442 SetLastError(0xdeadbeef);
443 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
444 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
445 UnmapViewOfFile( ptr );
447 SetLastError(0xdeadbeef);
448 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
449 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
450 UnmapViewOfFile( ptr );
452 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
453 FILE_MAP_READ|FILE_MAP_WRITE, FALSE, 0 );
454 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
455 ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
456 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
457 UnmapViewOfFile( ptr );
458 CloseHandle( map2 );
460 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
461 FILE_MAP_READ, FALSE, 0 );
462 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
463 SetLastError(0xdeadbeef);
464 ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
465 ok( !ptr, "MapViewOfFile succeeded\n" );
466 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
467 CloseHandle( map2 );
468 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2, 0, FALSE, 0 );
469 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
470 SetLastError(0xdeadbeef);
471 ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
472 ok( !ptr, "MapViewOfFile succeeded\n" );
473 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
474 CloseHandle( map2 );
475 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
476 FILE_MAP_READ, FALSE, 0 );
477 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
478 ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
479 ok( ptr != NULL, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
481 UnmapViewOfFile( ptr );
482 CloseHandle( map2 );
483 CloseHandle( mapping );
485 /* read-only mapping */
487 SetLastError(0xdeadbeef);
488 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
489 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
491 SetLastError(0xdeadbeef);
492 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
493 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
494 UnmapViewOfFile( ptr );
496 SetLastError(0xdeadbeef);
497 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
498 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
499 UnmapViewOfFile( ptr );
501 SetLastError(0xdeadbeef);
502 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
503 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
504 UnmapViewOfFile( ptr );
506 SetLastError(0xdeadbeef);
507 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
508 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
509 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
510 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
511 CloseHandle( mapping );
513 /* copy-on-write mapping */
515 SetLastError(0xdeadbeef);
516 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
517 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
519 SetLastError(0xdeadbeef);
520 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
521 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
522 UnmapViewOfFile( ptr );
524 SetLastError(0xdeadbeef);
525 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
526 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
527 UnmapViewOfFile( ptr );
529 SetLastError(0xdeadbeef);
530 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
531 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
532 UnmapViewOfFile( ptr );
534 SetLastError(0xdeadbeef);
535 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
536 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
537 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
538 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
539 CloseHandle( mapping );
541 /* no access mapping */
543 SetLastError(0xdeadbeef);
544 mapping = CreateFileMappingA( file, NULL, PAGE_NOACCESS, 0, 4096, NULL );
545 ok( !mapping, "CreateFileMappingA succeeded\n" );
546 ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
547 CloseHandle( file );
549 /* now try read-only file */
551 SetLastError(0xdeadbeef);
552 file = CreateFileA( testfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
553 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
555 SetLastError(0xdeadbeef);
556 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
557 ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
558 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
559 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
561 SetLastError(0xdeadbeef);
562 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
563 ok( mapping != 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
564 CloseHandle( mapping );
566 SetLastError(0xdeadbeef);
567 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
568 ok( mapping != 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
569 CloseHandle( mapping );
570 CloseHandle( file );
572 /* now try no access file */
574 SetLastError(0xdeadbeef);
575 file = CreateFileA( testfile, 0, 0, NULL, OPEN_EXISTING, 0, 0 );
576 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
578 SetLastError(0xdeadbeef);
579 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
580 ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
581 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
582 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
584 SetLastError(0xdeadbeef);
585 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
586 ok( !mapping, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
587 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
588 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
590 SetLastError(0xdeadbeef);
591 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
592 ok( !mapping, "CreateFileMapping PAGE_READONLY succeeded\n" );
593 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
594 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
596 CloseHandle( file );
597 DeleteFileA( testfile );
599 SetLastError(0xdeadbeef);
600 name = "Local\\Foo";
601 file = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4090, name );
602 /* nt4 doesn't have Local\\ */
603 if (!file && GetLastError() == ERROR_PATH_NOT_FOUND)
605 name = "Foo";
606 file = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4090, name );
608 ok( file != 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
610 SetLastError(0xdeadbeef);
611 mapping = OpenFileMappingA( FILE_MAP_READ, FALSE, name );
612 ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
613 SetLastError(0xdeadbeef);
614 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
615 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
616 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
617 SetLastError(0xdeadbeef);
618 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
619 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
620 SetLastError(0xdeadbeef);
621 size = VirtualQuery( ptr, &info, sizeof(info) );
622 ok( size == sizeof(info),
623 "VirtualQuery error %u\n", GetLastError() );
624 ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
625 ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
626 ok( info.AllocationProtect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.AllocationProtect );
627 ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
628 ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
629 ok( info.Protect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.Protect );
630 UnmapViewOfFile( ptr );
631 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
632 sizeof(section_info), &info_size );
633 ok( status == STATUS_ACCESS_DENIED, "NtQuerySection failed err %x\n", status );
634 CloseHandle( mapping );
635 mapping = OpenFileMappingA( FILE_MAP_READ | SECTION_QUERY, FALSE, name );
636 ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
637 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
638 sizeof(section_info), &info_size );
639 ok( !status, "NtQuerySection failed err %x\n", status );
640 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
641 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
642 section_info.Attributes );
643 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
644 ok( section_info.Size.QuadPart == info.RegionSize, "NtQuerySection wrong size %x%08x / %08lx\n",
645 section_info.Size.u.HighPart, section_info.Size.u.LowPart, info.RegionSize );
646 CloseHandle( mapping );
648 SetLastError(0xdeadbeef);
649 mapping = OpenFileMappingA( FILE_MAP_WRITE, FALSE, name );
650 ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
651 SetLastError(0xdeadbeef);
652 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
653 ok( !ptr, "MapViewOfFile succeeded\n " );
654 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
655 SetLastError(0xdeadbeef);
656 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
657 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
658 SetLastError(0xdeadbeef);
659 size = VirtualQuery( ptr, &info, sizeof(info) );
660 ok( size == sizeof(info),
661 "VirtualQuery error %u\n", GetLastError() );
662 ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
663 ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
664 ok( info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect );
665 ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
666 ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
667 ok( info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect );
668 UnmapViewOfFile( ptr );
669 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
670 sizeof(section_info), &info_size );
671 ok( status == STATUS_ACCESS_DENIED, "NtQuerySection failed err %x\n", status );
672 CloseHandle( mapping );
674 mapping = OpenFileMappingA( FILE_MAP_WRITE | SECTION_QUERY, FALSE, name );
675 ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
676 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
677 sizeof(section_info), &info_size );
678 ok( !status, "NtQuerySection failed err %x\n", status );
679 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
680 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
681 section_info.Attributes );
682 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
683 ok( section_info.Size.QuadPart == info.RegionSize, "NtQuerySection wrong size %x%08x / %08lx\n",
684 section_info.Size.u.HighPart, section_info.Size.u.LowPart, info.RegionSize );
685 CloseHandle( mapping );
687 CloseHandle( file );
689 /* read/write mapping with SEC_RESERVE */
690 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_RESERVE, 0, MAPPING_SIZE, NULL);
691 ok(mapping != INVALID_HANDLE_VALUE, "CreateFileMappingA failed with error %d\n", GetLastError());
692 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
693 sizeof(section_info), NULL );
694 ok( !status, "NtQuerySection failed err %x\n", status );
695 ok( section_info.Attributes == SEC_RESERVE, "NtQuerySection wrong attr %08x\n",
696 section_info.Attributes );
697 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
698 ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %x%08x / %08x\n",
699 section_info.Size.u.HighPart, section_info.Size.u.LowPart, MAPPING_SIZE );
701 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
702 ok(ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
704 ptr2 = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
705 ok( ptr2 != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
706 ok( ptr != ptr2, "MapViewOfFile returned same pointer\n" );
708 ret = VirtualQuery(ptr, &info, sizeof(info));
709 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
710 ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
711 ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
712 ok(info.RegionSize == MAPPING_SIZE, "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE, info.RegionSize);
713 ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
714 ok(info.AllocationProtect == PAGE_READWRITE,
715 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
716 ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
717 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
719 ret = VirtualQuery(ptr2, &info, sizeof(info));
720 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
721 ok(info.BaseAddress == ptr2,
722 "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
723 ok(info.AllocationBase == ptr2,
724 "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
725 ok(info.AllocationProtect == PAGE_READWRITE,
726 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
727 ok(info.RegionSize == MAPPING_SIZE,
728 "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE, info.RegionSize);
729 ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
730 ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
731 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
733 ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY);
734 ok(ptr != NULL, "VirtualAlloc failed with error %d\n", GetLastError());
736 ret = VirtualQuery(ptr, &info, sizeof(info));
737 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
738 ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
739 ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
740 ok(info.RegionSize == 0x10000, "RegionSize should have been 0x10000 but was 0x%lx\n", info.RegionSize);
741 ok(info.State == MEM_COMMIT, "State should have been MEM_COMMIT instead of 0x%x\n", info.State);
742 ok(info.Protect == PAGE_READONLY, "Protect should have been PAGE_READONLY instead of 0x%x\n", info.Protect);
743 ok(info.AllocationProtect == PAGE_READWRITE,
744 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
745 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
747 /* shows that the VirtualAlloc above affects the mapping, not just the
748 * virtual memory in this process - it also affects all other processes
749 * with a view of the mapping, but that isn't tested here */
750 ret = VirtualQuery(ptr2, &info, sizeof(info));
751 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
752 ok(info.BaseAddress == ptr2,
753 "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
754 ok(info.AllocationBase == ptr2,
755 "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
756 ok(info.AllocationProtect == PAGE_READWRITE,
757 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
758 ok(info.RegionSize == 0x10000,
759 "RegionSize should have been 0x10000 but was 0x%lx\n", info.RegionSize);
760 ok(info.State == MEM_COMMIT,
761 "State should have been MEM_COMMIT instead of 0x%x\n", info.State);
762 ok(info.Protect == PAGE_READWRITE,
763 "Protect should have been PAGE_READWRITE instead of 0x%x\n", info.Protect);
764 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
766 addr = VirtualAlloc( ptr, MAPPING_SIZE, MEM_RESET, PAGE_READONLY );
767 ok( addr == ptr, "VirtualAlloc failed with error %u\n", GetLastError() );
769 ret = VirtualFree( ptr, 0x10000, MEM_DECOMMIT );
770 ok( !ret, "VirtualFree succeeded\n" );
771 ok( GetLastError() == ERROR_INVALID_PARAMETER, "VirtualFree failed with %u\n", GetLastError() );
773 ret = UnmapViewOfFile(ptr2);
774 ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
775 ret = UnmapViewOfFile(ptr);
776 ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
777 CloseHandle(mapping);
779 addr = VirtualAlloc(NULL, 0x10000, MEM_COMMIT, PAGE_READONLY );
780 ok( addr != NULL, "VirtualAlloc failed with error %u\n", GetLastError() );
782 SetLastError(0xdeadbeef);
783 ok( !UnmapViewOfFile(addr), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
784 ok( GetLastError() == ERROR_INVALID_ADDRESS,
785 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
786 SetLastError(0xdeadbeef);
787 ok( !UnmapViewOfFile((char *)addr + 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
788 ok( GetLastError() == ERROR_INVALID_ADDRESS,
789 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
790 SetLastError(0xdeadbeef);
791 ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
792 ok( GetLastError() == ERROR_INVALID_ADDRESS,
793 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
795 ok( VirtualFree(addr, 0, MEM_RELEASE), "VirtualFree failed\n" );
797 /* close named mapping handle without unmapping */
798 name = "Foo";
799 SetLastError(0xdeadbeef);
800 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
801 ok( mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
802 SetLastError(0xdeadbeef);
803 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
804 ok( ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError() );
805 SetLastError(0xdeadbeef);
806 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
807 ok( map2 != 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
808 SetLastError(0xdeadbeef);
809 ret = CloseHandle(map2);
810 ok(ret, "CloseHandle error %d\n", GetLastError());
811 SetLastError(0xdeadbeef);
812 ret = CloseHandle(mapping);
813 ok(ret, "CloseHandle error %d\n", GetLastError());
815 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
816 ok( !ret, "memory is not accessible\n" );
818 ret = VirtualQuery(ptr, &info, sizeof(info));
819 ok(ret, "VirtualQuery error %d\n", GetLastError());
820 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
821 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
822 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
823 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
824 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
825 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
826 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
828 SetLastError(0xdeadbeef);
829 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
830 todo_wine
831 ok( map2 == 0, "OpenFileMappingA succeeded\n" );
832 todo_wine
833 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %d\n", GetLastError() );
834 if (map2) CloseHandle(map2); /* FIXME: remove once Wine is fixed */
835 SetLastError(0xdeadbeef);
836 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
837 ok( mapping != 0, "CreateFileMappingA failed\n" );
838 todo_wine
839 ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %d\n", GetLastError() );
840 SetLastError(0xdeadbeef);
841 ret = CloseHandle(mapping);
842 ok(ret, "CloseHandle error %d\n", GetLastError());
844 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
845 ok( !ret, "memory is not accessible\n" );
847 ret = VirtualQuery(ptr, &info, sizeof(info));
848 ok(ret, "VirtualQuery error %d\n", GetLastError());
849 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
850 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
851 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
852 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
853 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
854 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
855 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
857 SetLastError(0xdeadbeef);
858 ret = UnmapViewOfFile(ptr);
859 ok( ret, "UnmapViewOfFile failed with error %d\n", GetLastError() );
861 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
862 ok( ret, "memory is accessible\n" );
864 ret = VirtualQuery(ptr, &info, sizeof(info));
865 ok(ret, "VirtualQuery error %d\n", GetLastError());
866 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
867 ok(info.Protect == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", info.Protect);
868 ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase);
869 ok(info.AllocationProtect == 0, "%#x != 0\n", info.AllocationProtect);
870 ok(info.State == MEM_FREE, "%#x != MEM_FREE\n", info.State);
871 ok(info.Type == 0, "%#x != 0\n", info.Type);
873 SetLastError(0xdeadbeef);
874 file = CreateFileA(testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
875 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
876 SetFilePointer(file, 4096, NULL, FILE_BEGIN);
877 SetEndOfFile(file);
879 SetLastError(0xdeadbeef);
880 mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
881 ok( mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
882 SetLastError(0xdeadbeef);
883 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
884 ok( ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError() );
885 SetLastError(0xdeadbeef);
886 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
887 ok( map2 != 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
888 SetLastError(0xdeadbeef);
889 ret = CloseHandle(map2);
890 ok(ret, "CloseHandle error %d\n", GetLastError());
891 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
892 sizeof(section_info), &info_size );
893 ok( !status, "NtQuerySection failed err %x\n", status );
894 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
895 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
896 section_info.Attributes );
897 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
898 ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %x%08x\n",
899 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
900 SetLastError(0xdeadbeef);
901 ret = CloseHandle(mapping);
902 ok(ret, "CloseHandle error %d\n", GetLastError());
904 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
905 ok( !ret, "memory is not accessible\n" );
907 ret = VirtualQuery(ptr, &info, sizeof(info));
908 ok(ret, "VirtualQuery error %d\n", GetLastError());
909 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
910 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
911 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
912 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
913 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
914 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
915 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
917 SetLastError(0xdeadbeef);
918 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
919 todo_wine
920 ok( map2 == 0, "OpenFileMappingA succeeded\n" );
921 todo_wine
922 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %d\n", GetLastError() );
923 CloseHandle(map2);
924 SetLastError(0xdeadbeef);
925 mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
926 ok( mapping != 0, "CreateFileMappingA failed\n" );
927 todo_wine
928 ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %d\n", GetLastError() );
929 SetLastError(0xdeadbeef);
930 ret = CloseHandle(mapping);
931 ok(ret, "CloseHandle error %d\n", GetLastError());
933 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
934 ok( !ret, "memory is not accessible\n" );
936 ret = VirtualQuery(ptr, &info, sizeof(info));
937 ok(ret, "VirtualQuery error %d\n", GetLastError());
938 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
939 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
940 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
941 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
942 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
943 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
944 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
946 SetLastError(0xdeadbeef);
947 ret = UnmapViewOfFile(ptr);
948 ok( ret, "UnmapViewOfFile failed with error %d\n", GetLastError() );
950 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
951 ok( ret, "memory is accessible\n" );
953 ret = VirtualQuery(ptr, &info, sizeof(info));
954 ok(ret, "VirtualQuery error %d\n", GetLastError());
955 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
956 ok(info.Protect == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", info.Protect);
957 ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase);
958 ok(info.AllocationProtect == 0, "%#x != 0\n", info.AllocationProtect);
959 ok(info.State == MEM_FREE, "%#x != MEM_FREE\n", info.State);
960 ok(info.Type == 0, "%#x != 0\n", info.Type);
962 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 12288, NULL );
963 ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
965 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
966 ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
968 ret = UnmapViewOfFile( (char *)ptr + 100 );
969 ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
971 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
972 ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
974 ret = UnmapViewOfFile( (char *)ptr + 4096 );
975 ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
977 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
978 ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
980 ret = UnmapViewOfFile( (char *)ptr + 4096 + 100 );
981 ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
983 CloseHandle(mapping);
985 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 36, NULL );
986 ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
987 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
988 sizeof(section_info), &info_size );
989 ok( !status, "NtQuerySection failed err %x\n", status );
990 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
991 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
992 section_info.Attributes );
993 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
994 todo_wine
995 ok( section_info.Size.QuadPart == 36, "NtQuerySection wrong size %x%08x\n",
996 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
997 CloseHandle(mapping);
999 SetFilePointer(file, 0x3456, NULL, FILE_BEGIN);
1000 SetEndOfFile(file);
1001 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 0, NULL );
1002 ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
1003 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
1004 sizeof(section_info), &info_size );
1005 ok( !status, "NtQuerySection failed err %x\n", status );
1006 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
1007 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1008 section_info.Attributes );
1009 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1010 todo_wine
1011 ok( section_info.Size.QuadPart == 0x3456, "NtQuerySection wrong size %x%08x\n",
1012 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1013 CloseHandle(mapping);
1015 map_size.QuadPart = 0x3457;
1016 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1017 &map_size, PAGE_READONLY, SEC_COMMIT, file );
1018 todo_wine
1019 ok( status == STATUS_SECTION_TOO_BIG, "NtCreateSection failed %x\n", status );
1020 if (!status) CloseHandle( mapping );
1021 map_size.QuadPart = 0x3452;
1022 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1023 &map_size, PAGE_READONLY, SEC_COMMIT, file );
1024 ok( !status, "NtCreateSection failed %x\n", status );
1025 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info), NULL );
1026 ok( !status, "NtQuerySection failed err %x\n", status );
1027 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1028 section_info.Attributes );
1029 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1030 todo_wine
1031 ok( section_info.Size.QuadPart == 0x3452, "NtQuerySection wrong size %x%08x\n",
1032 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1033 CloseHandle(mapping);
1035 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1036 &map_size, PAGE_READONLY, SEC_COMMIT, 0 );
1037 ok( !status, "NtCreateSection failed %x\n", status );
1038 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info), NULL );
1039 ok( !status, "NtQuerySection failed err %x\n", status );
1040 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
1041 section_info.Attributes );
1042 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1043 ok( section_info.Size.QuadPart == 0x4000, "NtQuerySection wrong size %x%08x\n",
1044 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1045 CloseHandle(mapping);
1047 CloseHandle(file);
1048 DeleteFileA(testfile);
1051 static void test_NtMapViewOfSection(void)
1053 HANDLE hProcess;
1055 static const char testfile[] = "testfile.xxx";
1056 static const char data[] = "test data for NtMapViewOfSection";
1057 char buffer[sizeof(data)];
1058 HANDLE file, mapping;
1059 void *ptr, *ptr2;
1060 BOOL is_wow64, ret;
1061 DWORD status, written;
1062 SIZE_T size, result;
1063 LARGE_INTEGER offset;
1065 if (!pNtMapViewOfSection || !pNtUnmapViewOfSection)
1067 win_skip( "NtMapViewOfSection not available\n" );
1068 return;
1071 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1072 ok( file != INVALID_HANDLE_VALUE, "Failed to create test file\n" );
1073 WriteFile( file, data, sizeof(data), &written, NULL );
1074 SetFilePointer( file, 4096, NULL, FILE_BEGIN );
1075 SetEndOfFile( file );
1077 /* read/write mapping */
1079 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
1080 ok( mapping != 0, "CreateFileMapping failed\n" );
1082 hProcess = create_target_process("sleep");
1083 ok(hProcess != NULL, "Can't start process\n");
1085 ptr = NULL;
1086 size = 0;
1087 offset.QuadPart = 0;
1088 status = pNtMapViewOfSection( mapping, hProcess, &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1089 ok( !status, "NtMapViewOfSection failed status %x\n", status );
1090 ok( !((ULONG_PTR)ptr & 0xffff), "returned memory %p is not aligned to 64k\n", ptr );
1092 ret = ReadProcessMemory( hProcess, ptr, buffer, sizeof(buffer), &result );
1093 ok( ret, "ReadProcessMemory failed\n" );
1094 ok( result == sizeof(buffer), "ReadProcessMemory didn't read all data (%lx)\n", result );
1095 ok( !memcmp( buffer, data, sizeof(buffer) ), "Wrong data read\n" );
1097 /* for some unknown reason NtMapViewOfSection fails with STATUS_NO_MEMORY when zero_bits != 0 ? */
1098 ptr2 = NULL;
1099 size = 0;
1100 offset.QuadPart = 0;
1101 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 12, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1102 todo_wine
1103 ok( status == STATUS_NO_MEMORY, "NtMapViewOfSection returned %x\n", status );
1104 if (status == STATUS_SUCCESS)
1106 status = pNtUnmapViewOfSection( hProcess, ptr2 );
1107 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1110 ptr2 = NULL;
1111 size = 0;
1112 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1113 todo_wine
1114 ok( status == STATUS_NO_MEMORY, "NtMapViewOfSection returned %x\n", status );
1115 if (status == STATUS_SUCCESS)
1117 status = pNtUnmapViewOfSection( hProcess, ptr2 );
1118 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1121 /* mapping at the same page conflicts */
1122 ptr2 = ptr;
1123 size = 0;
1124 offset.QuadPart = 0;
1125 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1126 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
1128 /* offset has to be aligned */
1129 ptr2 = ptr;
1130 size = 0;
1131 offset.QuadPart = 1;
1132 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1133 ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
1135 /* ptr has to be aligned */
1136 ptr2 = (char *)ptr + 42;
1137 size = 0;
1138 offset.QuadPart = 0;
1139 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1140 ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
1142 /* still not 64k aligned */
1143 ptr2 = (char *)ptr + 0x1000;
1144 size = 0;
1145 offset.QuadPart = 0;
1146 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1147 ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
1149 /* zero_bits != 0 is not allowed when an address is set */
1150 ptr2 = (char *)ptr + 0x1000;
1151 size = 0;
1152 offset.QuadPart = 0;
1153 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 12, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1154 ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1156 ptr2 = (char *)ptr + 0x1000;
1157 size = 0;
1158 offset.QuadPart = 0;
1159 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1160 ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1162 ptr2 = (char *)ptr + 0x1001;
1163 size = 0;
1164 offset.QuadPart = 0;
1165 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1166 ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1168 ptr2 = (char *)ptr + 0x1000;
1169 size = 0;
1170 offset.QuadPart = 1;
1171 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1172 ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1174 if (sizeof(void *) == sizeof(int) && (!pIsWow64Process ||
1175 !pIsWow64Process( GetCurrentProcess(), &is_wow64 ) || !is_wow64))
1177 /* new memory region conflicts with previous mapping */
1178 ptr2 = ptr;
1179 size = 0;
1180 offset.QuadPart = 0;
1181 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1182 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1183 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
1185 ptr2 = (char *)ptr + 42;
1186 size = 0;
1187 offset.QuadPart = 0;
1188 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1189 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1190 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
1192 /* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
1193 ptr2 = (char *)ptr + 0x1000;
1194 size = 0;
1195 offset.QuadPart = 0;
1196 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1197 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1198 ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
1199 ok( (char *)ptr2 == (char *)ptr + 0x1000,
1200 "expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2 );
1201 status = pNtUnmapViewOfSection( hProcess, ptr2 );
1202 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1204 /* the address is rounded down if not on a page boundary */
1205 ptr2 = (char *)ptr + 0x1001;
1206 size = 0;
1207 offset.QuadPart = 0;
1208 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1209 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1210 ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
1211 ok( (char *)ptr2 == (char *)ptr + 0x1000,
1212 "expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2 );
1213 status = pNtUnmapViewOfSection( hProcess, ptr2 );
1214 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1216 ptr2 = (char *)ptr + 0x2000;
1217 size = 0;
1218 offset.QuadPart = 0;
1219 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1220 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1221 ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
1222 ok( (char *)ptr2 == (char *)ptr + 0x2000,
1223 "expected address %p, got %p\n", (char *)ptr + 0x2000, ptr2 );
1224 status = pNtUnmapViewOfSection( hProcess, ptr2 );
1225 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1227 else
1229 ptr2 = (char *)ptr + 0x1000;
1230 size = 0;
1231 offset.QuadPart = 0;
1232 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1233 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1234 todo_wine
1235 ok( status == STATUS_INVALID_PARAMETER_9, "NtMapViewOfSection returned %x\n", status );
1238 status = pNtUnmapViewOfSection( hProcess, ptr );
1239 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1241 CloseHandle( mapping );
1242 CloseHandle( file );
1243 DeleteFileA( testfile );
1245 TerminateProcess(hProcess, 0);
1246 CloseHandle(hProcess);
1249 static void test_NtAreMappedFilesTheSame(void)
1251 static const char testfile[] = "testfile.xxx";
1252 HANDLE file, file2, mapping, map2;
1253 void *ptr, *ptr2;
1254 NTSTATUS status;
1255 char path[MAX_PATH];
1257 if (!pNtAreMappedFilesTheSame)
1259 win_skip( "NtAreMappedFilesTheSame not available\n" );
1260 return;
1263 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
1264 NULL, CREATE_ALWAYS, 0, 0 );
1265 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1266 SetFilePointer( file, 4096, NULL, FILE_BEGIN );
1267 SetEndOfFile( file );
1269 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
1270 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1272 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1273 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1275 file2 = CreateFileA( testfile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1276 NULL, OPEN_EXISTING, 0, 0 );
1277 ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1279 map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY, 0, 4096, NULL );
1280 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1281 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
1282 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1283 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1284 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1285 UnmapViewOfFile( ptr2 );
1287 ptr2 = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1288 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1289 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1290 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1291 UnmapViewOfFile( ptr2 );
1292 CloseHandle( map2 );
1294 map2 = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
1295 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1296 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
1297 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1298 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1299 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1300 UnmapViewOfFile( ptr2 );
1301 CloseHandle( map2 );
1302 CloseHandle( file2 );
1304 status = pNtAreMappedFilesTheSame( ptr, ptr );
1305 ok( status == STATUS_SUCCESS || broken(status == STATUS_NOT_SAME_DEVICE),
1306 "NtAreMappedFilesTheSame returned %x\n", status );
1308 status = pNtAreMappedFilesTheSame( ptr, (char *)ptr + 30 );
1309 ok( status == STATUS_SUCCESS || broken(status == STATUS_NOT_SAME_DEVICE),
1310 "NtAreMappedFilesTheSame returned %x\n", status );
1312 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1313 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1315 status = pNtAreMappedFilesTheSame( ptr, (void *)0xdeadbeef );
1316 ok( status == STATUS_CONFLICTING_ADDRESSES || status == STATUS_INVALID_ADDRESS,
1317 "NtAreMappedFilesTheSame returned %x\n", status );
1319 status = pNtAreMappedFilesTheSame( ptr, NULL );
1320 ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
1322 status = pNtAreMappedFilesTheSame( ptr, (void *)GetProcessHeap() );
1323 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
1325 status = pNtAreMappedFilesTheSame( NULL, NULL );
1326 ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
1328 ptr2 = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE );
1329 ok( ptr2 != NULL, "VirtualAlloc error %u\n", GetLastError() );
1330 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1331 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
1332 VirtualFree( ptr2, 0, MEM_RELEASE );
1334 UnmapViewOfFile( ptr );
1335 CloseHandle( mapping );
1336 CloseHandle( file );
1338 status = pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
1339 GetModuleHandleA("kernel32.dll") );
1340 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1341 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1342 GetModuleHandleA("kernel32.dll") );
1343 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1344 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1345 (char *)GetModuleHandleA("kernel32.dll") + 4096 );
1346 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1348 GetSystemDirectoryA( path, MAX_PATH );
1349 strcat( path, "\\kernel32.dll" );
1350 file = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
1351 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1353 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
1354 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1355 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1356 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1357 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1358 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1359 UnmapViewOfFile( ptr );
1360 CloseHandle( mapping );
1362 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
1363 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1364 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
1365 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1366 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1367 todo_wine
1368 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1370 file2 = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
1371 ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1372 map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
1373 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1374 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 0 );
1375 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1376 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1377 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1378 UnmapViewOfFile( ptr2 );
1379 CloseHandle( map2 );
1380 CloseHandle( file2 );
1382 UnmapViewOfFile( ptr );
1383 CloseHandle( mapping );
1385 CloseHandle( file );
1386 DeleteFileA( testfile );
1389 static void test_CreateFileMapping(void)
1391 HANDLE handle, handle2;
1393 /* test case sensitivity */
1395 SetLastError(0xdeadbeef);
1396 handle = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1397 "Wine Test Mapping");
1398 ok( handle != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
1399 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1401 SetLastError(0xdeadbeef);
1402 handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1403 "Wine Test Mapping");
1404 ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
1405 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
1406 CloseHandle( handle2 );
1408 SetLastError(0xdeadbeef);
1409 handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1410 "WINE TEST MAPPING");
1411 ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
1412 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1413 CloseHandle( handle2 );
1415 SetLastError(0xdeadbeef);
1416 handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "Wine Test Mapping");
1417 ok( handle2 != NULL, "OpenFileMapping failed with error %d\n", GetLastError());
1418 CloseHandle( handle2 );
1420 SetLastError(0xdeadbeef);
1421 handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "WINE TEST MAPPING");
1422 ok( !handle2, "OpenFileMapping succeeded\n");
1423 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
1425 CloseHandle( handle );
1428 static void test_IsBadReadPtr(void)
1430 BOOL ret;
1431 void *ptr = (void *)0xdeadbeef;
1432 char stackvar;
1434 ret = IsBadReadPtr(NULL, 0);
1435 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1437 ret = IsBadReadPtr(NULL, 1);
1438 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1440 ret = IsBadReadPtr(ptr, 0);
1441 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1443 ret = IsBadReadPtr(ptr, 1);
1444 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1446 ret = IsBadReadPtr(&stackvar, 0);
1447 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1449 ret = IsBadReadPtr(&stackvar, sizeof(char));
1450 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1453 static void test_IsBadWritePtr(void)
1455 BOOL ret;
1456 void *ptr = (void *)0xdeadbeef;
1457 char stackval;
1459 ret = IsBadWritePtr(NULL, 0);
1460 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1462 ret = IsBadWritePtr(NULL, 1);
1463 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1465 ret = IsBadWritePtr(ptr, 0);
1466 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1468 ret = IsBadWritePtr(ptr, 1);
1469 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1471 ret = IsBadWritePtr(&stackval, 0);
1472 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1474 ret = IsBadWritePtr(&stackval, sizeof(char));
1475 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1478 static void test_IsBadCodePtr(void)
1480 BOOL ret;
1481 void *ptr = (void *)0xdeadbeef;
1482 char stackval;
1484 ret = IsBadCodePtr(NULL);
1485 ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1487 ret = IsBadCodePtr(ptr);
1488 ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1490 ret = IsBadCodePtr((void *)&stackval);
1491 ok(ret == FALSE, "Expected IsBadCodePtr to return FALSE, got %d\n", ret);
1494 static void test_write_watch(void)
1496 static const char pipename[] = "\\\\.\\pipe\\test_write_watch_pipe";
1497 static const char testdata[] = "Hello World";
1498 DWORD ret, size, old_prot, num_bytes;
1499 MEMORY_BASIC_INFORMATION info;
1500 HANDLE readpipe, writepipe;
1501 OVERLAPPED overlapped;
1502 void *results[64];
1503 ULONG_PTR count;
1504 ULONG pagesize;
1505 BOOL success;
1506 char *base;
1508 if (!pGetWriteWatch || !pResetWriteWatch)
1510 win_skip( "GetWriteWatch not supported\n" );
1511 return;
1514 size = 0x10000;
1515 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE );
1516 if (!base &&
1517 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
1519 win_skip( "MEM_WRITE_WATCH not supported\n" );
1520 return;
1522 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1523 ret = VirtualQuery( base, &info, sizeof(info) );
1524 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1525 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1526 ok( info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect %x\n", info.AllocationProtect );
1527 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1528 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1529 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1530 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
1532 count = 64;
1533 SetLastError( 0xdeadbeef );
1534 ret = pGetWriteWatch( 0, NULL, size, results, &count, &pagesize );
1535 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1536 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
1537 broken( GetLastError() == 0xdeadbeef ), /* win98 */
1538 "wrong error %u\n", GetLastError() );
1540 SetLastError( 0xdeadbeef );
1541 ret = pGetWriteWatch( 0, GetModuleHandleW(NULL), size, results, &count, &pagesize );
1542 if (ret)
1544 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1545 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1547 else /* win98 */
1549 ok( count == 0, "wrong count %lu\n", count );
1552 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1553 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1554 ok( count == 0, "wrong count %lu\n", count );
1556 base[pagesize + 1] = 0x44;
1558 count = 64;
1559 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1560 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1561 ok( count == 1, "wrong count %lu\n", count );
1562 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1564 count = 64;
1565 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1566 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1567 ok( count == 1, "wrong count %lu\n", count );
1568 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1570 count = 64;
1571 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1572 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1573 ok( count == 0, "wrong count %lu\n", count );
1575 base[2*pagesize + 3] = 0x11;
1576 base[4*pagesize + 8] = 0x11;
1578 count = 64;
1579 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1580 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1581 ok( count == 2, "wrong count %lu\n", count );
1582 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1583 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1585 count = 64;
1586 ret = pGetWriteWatch( 0, base + 3*pagesize, 2*pagesize, results, &count, &pagesize );
1587 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1588 ok( count == 1, "wrong count %lu\n", count );
1589 ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1591 ret = pResetWriteWatch( base, 3*pagesize );
1592 ok( !ret, "pResetWriteWatch failed %u\n", GetLastError() );
1594 count = 64;
1595 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1596 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1597 ok( count == 1, "wrong count %lu\n", count );
1598 ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1600 *(DWORD *)(base + 2*pagesize - 2) = 0xdeadbeef;
1602 count = 64;
1603 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1604 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1605 ok( count == 3, "wrong count %lu\n", count );
1606 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1607 ok( results[1] == base + 2*pagesize, "wrong result %p\n", results[1] );
1608 ok( results[2] == base + 4*pagesize, "wrong result %p\n", results[2] );
1610 count = 1;
1611 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1612 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1613 ok( count == 1, "wrong count %lu\n", count );
1614 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1616 count = 64;
1617 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1618 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1619 ok( count == 2, "wrong count %lu\n", count );
1620 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1621 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1623 /* changing protections doesn't affect watches */
1625 ret = VirtualProtect( base, 3*pagesize, PAGE_READONLY, &old_prot );
1626 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1627 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1629 ret = VirtualQuery( base, &info, sizeof(info) );
1630 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1631 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1632 ok( info.RegionSize == 3*pagesize, "wrong RegionSize 0x%lx\n", info.RegionSize );
1633 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1634 ok( info.Protect == PAGE_READONLY, "wrong Protect 0x%x\n", info.Protect );
1636 ret = VirtualProtect( base, 3*pagesize, PAGE_READWRITE, &old_prot );
1637 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1638 ok( old_prot == PAGE_READONLY, "wrong old prot %x\n", old_prot );
1640 count = 64;
1641 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1642 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1643 ok( count == 2, "wrong count %lu\n", count );
1644 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1645 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1647 ret = VirtualQuery( base, &info, sizeof(info) );
1648 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1649 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1650 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1651 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1652 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1654 /* ReadFile should trigger write watches */
1656 memset( &overlapped, 0, sizeof(overlapped) );
1657 overlapped.hEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
1659 readpipe = CreateNamedPipeA( pipename, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_INBOUND,
1660 PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024,
1661 NMPWAIT_USE_DEFAULT_WAIT, NULL );
1662 ok( readpipe != INVALID_HANDLE_VALUE, "CreateNamedPipeA failed %u\n", GetLastError() );
1664 success = ConnectNamedPipe( readpipe, &overlapped );
1665 ok( !success, "ConnectNamedPipe unexpectedly succeeded\n" );
1666 ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1668 writepipe = CreateFileA( pipename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
1669 ok( writepipe != INVALID_HANDLE_VALUE, "CreateFileA failed %u\n", GetLastError() );
1671 ret = WaitForSingleObject( overlapped.hEvent, 1000 );
1672 ok( ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret );
1674 memset( base, 0, size );
1676 count = 64;
1677 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1678 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1679 ok( count == 16, "wrong count %lu\n", count );
1681 success = ReadFile( readpipe, base, size, NULL, &overlapped );
1682 ok( !success, "ReadFile unexpectedly succeeded\n" );
1683 ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1685 count = 64;
1686 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1687 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1688 ok( count == 16, "wrong count %lu\n", count );
1690 num_bytes = 0;
1691 success = WriteFile( writepipe, testdata, sizeof(testdata), &num_bytes, NULL );
1692 ok( success, "WriteFile failed %u\n", GetLastError() );
1693 ok( num_bytes == sizeof(testdata), "wrong number of bytes written\n" );
1695 num_bytes = 0;
1696 success = GetOverlappedResult( readpipe, &overlapped, &num_bytes, TRUE );
1697 todo_wine ok( success, "GetOverlappedResult failed %u\n", GetLastError() );
1698 todo_wine ok( num_bytes == sizeof(testdata), "wrong number of bytes read\n" );
1699 todo_wine ok( !memcmp( base, testdata, sizeof(testdata)), "didn't receive expected data\n" );
1701 count = 64;
1702 memset( results, 0, sizeof(results) );
1703 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1704 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1705 todo_wine ok( count == 1, "wrong count %lu\n", count );
1706 todo_wine ok( results[0] == base, "wrong result %p\n", results[0] );
1708 CloseHandle( readpipe );
1709 CloseHandle( writepipe );
1710 CloseHandle( overlapped.hEvent );
1712 /* some invalid parameter tests */
1714 SetLastError( 0xdeadbeef );
1715 count = 0;
1716 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1717 if (ret)
1719 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1720 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1722 SetLastError( 0xdeadbeef );
1723 ret = pGetWriteWatch( 0, base, size, results, NULL, &pagesize );
1724 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1725 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1727 SetLastError( 0xdeadbeef );
1728 count = 64;
1729 ret = pGetWriteWatch( 0, base, size, results, &count, NULL );
1730 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1731 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1733 SetLastError( 0xdeadbeef );
1734 count = 64;
1735 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1736 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1737 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1739 SetLastError( 0xdeadbeef );
1740 count = 0;
1741 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1742 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1743 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1745 SetLastError( 0xdeadbeef );
1746 count = 64;
1747 ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
1748 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1749 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1751 SetLastError( 0xdeadbeef );
1752 count = 64;
1753 ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
1754 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1755 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1757 SetLastError( 0xdeadbeef );
1758 count = 64;
1759 ret = pGetWriteWatch( 0, base, size * 2, results, &count, &pagesize );
1760 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1761 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1763 SetLastError( 0xdeadbeef );
1764 count = 64;
1765 ret = pGetWriteWatch( 0, base + size - pagesize, pagesize + 1, results, &count, &pagesize );
1766 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1767 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1769 SetLastError( 0xdeadbeef );
1770 ret = pResetWriteWatch( base, 0 );
1771 ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
1772 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1774 SetLastError( 0xdeadbeef );
1775 ret = pResetWriteWatch( GetModuleHandleW(NULL), size );
1776 ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
1777 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1779 else /* win98 is completely different */
1781 SetLastError( 0xdeadbeef );
1782 count = 64;
1783 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1784 ok( ret == ERROR_INVALID_PARAMETER, "GetWriteWatch succeeded %u\n", ret );
1785 ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
1787 count = 0;
1788 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1789 ok( !ret, "GetWriteWatch failed %u\n", ret );
1791 count = 64;
1792 ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
1793 ok( !ret, "GetWriteWatch failed %u\n", ret );
1795 count = 64;
1796 ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
1797 ok( !ret, "GetWriteWatch failed %u\n", ret );
1799 ret = pResetWriteWatch( base, 0 );
1800 ok( !ret, "ResetWriteWatch failed %u\n", ret );
1802 ret = pResetWriteWatch( GetModuleHandleW(NULL), size );
1803 ok( !ret, "ResetWriteWatch failed %u\n", ret );
1806 VirtualFree( base, 0, MEM_RELEASE );
1808 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_READWRITE );
1809 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1810 VirtualFree( base, 0, MEM_RELEASE );
1812 base = VirtualAlloc( 0, size, MEM_WRITE_WATCH, PAGE_READWRITE );
1813 ok( !base, "VirtualAlloc succeeded\n" );
1814 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1816 /* initial protect doesn't matter */
1818 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_NOACCESS );
1819 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1820 base = VirtualAlloc( base, size, MEM_COMMIT, PAGE_NOACCESS );
1821 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1823 count = 64;
1824 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1825 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1826 ok( count == 0, "wrong count %lu\n", count );
1828 ret = VirtualProtect( base, 6*pagesize, PAGE_READWRITE, &old_prot );
1829 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1830 ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
1832 base[5*pagesize + 200] = 3;
1834 ret = VirtualProtect( base, 6*pagesize, PAGE_NOACCESS, &old_prot );
1835 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1836 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1838 count = 64;
1839 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1840 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1841 ok( count == 1, "wrong count %lu\n", count );
1842 ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
1844 ret = VirtualFree( base, size, MEM_DECOMMIT );
1845 ok( ret, "VirtualFree failed %u\n", GetLastError() );
1847 count = 64;
1848 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1849 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1850 ok( count == 1 || broken(count == 0), /* win98 */
1851 "wrong count %lu\n", count );
1852 if (count) ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
1854 VirtualFree( base, 0, MEM_RELEASE );
1857 #if defined(__i386__) || defined(__x86_64__)
1859 static DWORD WINAPI stack_commit_func( void *arg )
1861 volatile char *p = (char *)&p;
1863 /* trigger all guard pages, to ensure that the pages are committed */
1864 while (p >= (char *)NtCurrentTeb()->DeallocationStack + 4 * 0x1000)
1866 p[0] |= 0;
1867 p -= 0x1000;
1870 ok( arg == (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg );
1871 return 42;
1874 static void test_stack_commit(void)
1876 #ifdef __i386__
1877 static const char code_call_on_stack[] = {
1878 0x55, /* pushl %ebp */
1879 0x56, /* pushl %esi */
1880 0x89, 0xe6, /* movl %esp,%esi */
1881 0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */
1882 0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */
1883 0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */
1884 0x83, 0xe0, 0xf0, /* andl $~15,%eax */
1885 0x83, 0xe8, 0x0c, /* subl $12,%eax */
1886 0x89, 0xc4, /* movl %eax,%esp */
1887 0x52, /* pushl %edx */
1888 0x31, 0xed, /* xorl %ebp,%ebp */
1889 0xff, 0xd1, /* call *%ecx */
1890 0x89, 0xf4, /* movl %esi,%esp */
1891 0x5e, /* popl %esi */
1892 0x5d, /* popl %ebp */
1893 0xc2, 0x0c, 0x00 }; /* ret $12 */
1894 #else
1895 static const char code_call_on_stack[] = {
1896 0x55, /* pushq %rbp */
1897 0x48, 0x89, 0xe5, /* movq %rsp,%rbp */
1898 /* %rcx - func, %rdx - arg, %r8 - stack */
1899 0x48, 0x87, 0xca, /* xchgq %rcx,%rdx */
1900 0x49, 0x83, 0xe0, 0xf0, /* andq $~15,%r8 */
1901 0x49, 0x83, 0xe8, 0x20, /* subq $0x20,%r8 */
1902 0x4c, 0x89, 0xc4, /* movq %r8,%rsp */
1903 0xff, 0xd2, /* callq *%rdx */
1904 0x48, 0x89, 0xec, /* movq %rbp,%rsp */
1905 0x5d, /* popq %rbp */
1906 0xc3 }; /* ret */
1907 #endif
1908 DWORD (WINAPI *call_on_stack)( DWORD (WINAPI *func)(void *), void *arg, void *stack );
1909 void *old_stack, *old_stack_base, *old_stack_limit;
1910 void *new_stack, *new_stack_base;
1911 DWORD result;
1913 call_on_stack = VirtualAlloc( 0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE );
1914 ok( call_on_stack != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1915 memcpy( call_on_stack, code_call_on_stack, sizeof(code_call_on_stack) );
1917 /* allocate a new stack, only the first guard page is committed */
1918 new_stack = VirtualAlloc( 0, 0x400000, MEM_RESERVE, PAGE_READWRITE );
1919 ok( new_stack != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1920 new_stack_base = (char *)new_stack + 0x400000;
1921 VirtualAlloc( (char *)new_stack_base - 0x1000, 0x1000, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
1923 old_stack = NtCurrentTeb()->DeallocationStack;
1924 old_stack_base = NtCurrentTeb()->Tib.StackBase;
1925 old_stack_limit = NtCurrentTeb()->Tib.StackLimit;
1927 NtCurrentTeb()->DeallocationStack = new_stack;
1928 NtCurrentTeb()->Tib.StackBase = new_stack_base;
1929 NtCurrentTeb()->Tib.StackLimit = new_stack_base;
1931 result = call_on_stack( stack_commit_func, (void *)0xdeadbeef, new_stack_base );
1933 NtCurrentTeb()->DeallocationStack = old_stack;
1934 NtCurrentTeb()->Tib.StackBase = old_stack_base;
1935 NtCurrentTeb()->Tib.StackLimit = old_stack_limit;
1937 ok( result == 42, "expected 42, got %u\n", result );
1939 VirtualFree( new_stack, 0, MEM_RELEASE );
1940 VirtualFree( call_on_stack, 0, MEM_RELEASE );
1943 #endif /* defined(__i386__) || defined(__x86_64__) */
1944 #ifdef __i386__
1946 static LONG num_guard_page_calls;
1948 static DWORD guard_page_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
1949 CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
1951 trace( "exception: %08x flags:%x addr:%p\n",
1952 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
1954 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
1955 ok( rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION, "ExceptionCode is %08x instead of %08x\n",
1956 rec->ExceptionCode, STATUS_GUARD_PAGE_VIOLATION );
1958 InterlockedIncrement( &num_guard_page_calls );
1959 *(int *)rec->ExceptionInformation[1] += 0x100;
1961 return ExceptionContinueExecution;
1964 static void test_guard_page(void)
1966 EXCEPTION_REGISTRATION_RECORD frame;
1967 MEMORY_BASIC_INFORMATION info;
1968 DWORD ret, size, old_prot;
1969 int *value, old_value;
1970 void *results[64];
1971 ULONG_PTR count;
1972 ULONG pagesize;
1973 BOOL success;
1974 char *base;
1976 size = 0x1000;
1977 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
1978 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1979 value = (int *)base;
1981 /* verify info structure */
1982 ret = VirtualQuery( base, &info, sizeof(info) );
1983 ok( ret, "VirtualQuery failed %u\n", GetLastError());
1984 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1985 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
1986 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1987 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1988 ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%x\n", info.Protect );
1989 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
1991 /* put some initial value into the memory */
1992 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
1993 ok( success, "VirtualProtect failed %u\n", GetLastError() );
1994 ok( old_prot == (PAGE_READWRITE | PAGE_GUARD), "wrong old prot %x\n", old_prot );
1996 *value = 1;
1997 *(value + 1) = 2;
1999 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2000 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2001 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2003 /* test behaviour of VirtualLock - first attempt should fail */
2004 SetLastError( 0xdeadbeef );
2005 success = VirtualLock( base, size );
2006 ok( !success, "VirtualLock unexpectedly succeeded\n" );
2007 todo_wine
2008 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %u\n", GetLastError() );
2010 success = VirtualLock( base, size );
2011 todo_wine
2012 ok( success, "VirtualLock failed %u\n", GetLastError() );
2013 if (success)
2015 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2016 success = VirtualUnlock( base, size );
2017 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2020 /* check info structure again, PAGE_GUARD should be removed now */
2021 ret = VirtualQuery( base, &info, sizeof(info) );
2022 ok( ret, "VirtualQuery failed %u\n", GetLastError());
2023 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
2024 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
2025 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
2026 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
2027 todo_wine
2028 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
2029 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
2031 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2032 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2033 todo_wine
2034 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2036 /* test directly accessing the memory - we need to setup an exception handler first */
2037 frame.Handler = guard_page_handler;
2038 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2039 NtCurrentTeb()->Tib.ExceptionList = &frame;
2041 InterlockedExchange( &num_guard_page_calls, 0 );
2042 InterlockedExchange( &old_value, *value ); /* exception handler increments value by 0x100 */
2043 *value = 2;
2044 ok( old_value == 0x101, "memory block contains wrong value, expected 0x101, got 0x%x\n", old_value );
2045 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2047 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2049 /* check info structure again, PAGE_GUARD should be removed now */
2050 ret = VirtualQuery( base, &info, sizeof(info) );
2051 ok( ret, "VirtualQuery failed %u\n", GetLastError());
2052 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
2054 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2055 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2056 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2058 /* test accessing second integer in memory */
2059 frame.Handler = guard_page_handler;
2060 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2061 NtCurrentTeb()->Tib.ExceptionList = &frame;
2063 InterlockedExchange( &num_guard_page_calls, 0 );
2064 old_value = *(value + 1);
2065 ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value );
2066 ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value );
2067 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2069 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2071 success = VirtualLock( base, size );
2072 ok( success, "VirtualLock failed %u\n", GetLastError() );
2073 if (success)
2075 ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value );
2076 success = VirtualUnlock( base, size );
2077 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2080 VirtualFree( base, 0, MEM_RELEASE );
2082 /* combined guard page / write watch tests */
2083 if (!pGetWriteWatch || !pResetWriteWatch)
2085 win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" );
2086 return;
2089 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE | PAGE_GUARD );
2090 if (!base && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
2092 win_skip( "MEM_WRITE_WATCH not supported\n" );
2093 return;
2095 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2096 value = (int *)base;
2098 ret = VirtualQuery( base, &info, sizeof(info) );
2099 ok( ret, "VirtualQuery failed %u\n", GetLastError() );
2100 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
2101 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
2102 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
2103 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
2104 ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%x\n", info.Protect );
2105 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
2107 count = 64;
2108 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
2109 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2110 ok( count == 0, "wrong count %lu\n", count );
2112 /* writing to a page should trigger should trigger guard page, even if write watch is set */
2113 frame.Handler = guard_page_handler;
2114 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2115 NtCurrentTeb()->Tib.ExceptionList = &frame;
2117 InterlockedExchange( &num_guard_page_calls, 0 );
2118 *value = 1;
2119 *(value + 1) = 2;
2120 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2122 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2124 count = 64;
2125 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2126 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2127 ok( count == 1, "wrong count %lu\n", count );
2128 ok( results[0] == base, "wrong result %p\n", results[0] );
2130 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2131 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2133 /* write watch is triggered from inside of the guard page handler */
2134 frame.Handler = guard_page_handler;
2135 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2136 NtCurrentTeb()->Tib.ExceptionList = &frame;
2138 InterlockedExchange( &num_guard_page_calls, 0 );
2139 old_value = *(value + 1); /* doesn't trigger write watch */
2140 ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value );
2141 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2142 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2144 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2146 count = 64;
2147 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2148 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2149 ok( count == 1, "wrong count %lu\n", count );
2150 ok( results[0] == base, "wrong result %p\n", results[0] );
2152 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2153 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2155 /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */
2156 SetLastError( 0xdeadbeef );
2157 success = VirtualLock( base, size );
2158 ok( !success, "VirtualLock unexpectedly succeeded\n" );
2159 todo_wine
2160 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %u\n", GetLastError() );
2162 count = 64;
2163 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
2164 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2165 ok( count == 0, "wrong count %lu\n", count );
2167 success = VirtualLock( base, size );
2168 todo_wine
2169 ok( success, "VirtualLock failed %u\n", GetLastError() );
2170 if (success)
2172 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2173 success = VirtualUnlock( base, size );
2174 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2177 count = 64;
2178 results[0] = (void *)0xdeadbeef;
2179 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2180 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2181 todo_wine
2182 ok( count == 1 || broken(count == 0) /* Windows 8 */, "wrong count %lu\n", count );
2183 todo_wine
2184 ok( results[0] == base || broken(results[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results[0] );
2186 VirtualFree( base, 0, MEM_RELEASE );
2189 static LONG num_execute_fault_calls;
2191 static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
2192 CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
2194 ULONG flags = MEM_EXECUTE_OPTION_ENABLE;
2195 DWORD err;
2197 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2198 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
2199 rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] );
2201 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
2202 ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION || rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION,
2203 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec->ExceptionCode );
2205 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags), NULL );
2207 if (rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
2210 err = IsProcessorFeaturePresent( PF_NX_ENABLED ) ? EXCEPTION_EXECUTE_FAULT : EXCEPTION_READ_FAULT;
2211 ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %d instead of %d\n",
2212 (DWORD)rec->ExceptionInformation[0], err );
2214 InterlockedIncrement( &num_guard_page_calls );
2216 else if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION)
2218 DWORD old_prot;
2219 BOOL success;
2221 err = (flags & MEM_EXECUTE_OPTION_DISABLE) ? EXCEPTION_EXECUTE_FAULT : EXCEPTION_READ_FAULT;
2222 ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %d instead of %d\n",
2223 (DWORD)rec->ExceptionInformation[0], err );
2225 success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
2226 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2227 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2229 InterlockedIncrement( &num_execute_fault_calls );
2232 return ExceptionContinueExecution;
2235 static LONG CALLBACK execute_fault_vec_handler( EXCEPTION_POINTERS *ExceptionInfo )
2237 PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
2238 DWORD old_prot;
2239 BOOL success;
2241 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2242 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
2243 rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] );
2245 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
2246 ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION,
2247 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec->ExceptionCode );
2249 if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION)
2250 InterlockedIncrement( &num_execute_fault_calls );
2252 if (rec->ExceptionInformation[0] == EXCEPTION_READ_FAULT)
2253 return EXCEPTION_CONTINUE_SEARCH;
2255 success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
2256 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2257 ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
2259 return EXCEPTION_CONTINUE_EXECUTION;
2262 static inline DWORD send_message_excpt( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2264 EXCEPTION_REGISTRATION_RECORD frame;
2265 DWORD ret;
2267 frame.Handler = execute_fault_seh_handler;
2268 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2269 NtCurrentTeb()->Tib.ExceptionList = &frame;
2271 InterlockedExchange( &num_guard_page_calls, 0 );
2272 InterlockedExchange( &num_execute_fault_calls, 0 );
2273 ret = SendMessageA( hWnd, uMsg, wParam, lParam );
2275 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2277 return ret;
2280 static inline DWORD call_proc_excpt( DWORD (CALLBACK *code)(void *), void *arg )
2282 EXCEPTION_REGISTRATION_RECORD frame;
2283 DWORD ret;
2285 frame.Handler = execute_fault_seh_handler;
2286 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2287 NtCurrentTeb()->Tib.ExceptionList = &frame;
2289 InterlockedExchange( &num_guard_page_calls, 0 );
2290 InterlockedExchange( &num_execute_fault_calls, 0 );
2291 ret = code( arg );
2293 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2295 return ret;
2298 static LRESULT CALLBACK jmp_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2300 if (uMsg == WM_USER)
2301 return 42;
2303 return DefWindowProcA( hWnd, uMsg, wParam, lParam );
2306 static LRESULT CALLBACK atl_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2308 DWORD arg = (DWORD)hWnd;
2309 if (uMsg == WM_USER)
2310 ok( arg == 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg );
2311 else
2312 ok( arg != 0x11223344, "arg is unexpectedly 0x11223344\n" );
2313 return 43;
2316 static DWORD CALLBACK atl5_test_func( void )
2318 return 44;
2321 static void test_atl_thunk_emulation( ULONG dep_flags )
2323 static const char code_jmp[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
2324 static const char code_atl1[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2325 static const char code_atl2[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2326 static const char code_atl3[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1};
2327 static const char code_atl4[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
2328 static const char code_atl5[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04};
2329 static const char cls_name[] = "atl_thunk_class";
2330 DWORD ret, size, old_prot;
2331 ULONG old_flags = MEM_EXECUTE_OPTION_ENABLE;
2332 BOOL success, restore_flags = FALSE;
2333 void *results[64];
2334 ULONG_PTR count;
2335 ULONG pagesize;
2336 WNDCLASSEXA wc;
2337 char *base;
2338 HWND hWnd;
2340 trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
2342 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags), NULL );
2343 if (old_flags != dep_flags)
2345 ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &dep_flags, sizeof(dep_flags) );
2346 if (ret == STATUS_INVALID_INFO_CLASS) /* Windows 2000 */
2348 win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
2349 return;
2351 ok( !ret, "NtSetInformationProcess failed with status %08x\n", ret );
2352 restore_flags = TRUE;
2355 size = 0x1000;
2356 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
2357 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2359 /* Check result of GetProcessDEPPolicy */
2360 if (!pGetProcessDEPPolicy)
2361 win_skip( "GetProcessDEPPolicy not supported\n" );
2362 else
2364 BOOL (WINAPI *get_dep_policy)(HANDLE, LPDWORD, PBOOL) = (void *)base;
2365 BOOL policy_permanent = 0xdeadbeef;
2366 DWORD policy_flags = 0xdeadbeef;
2368 /* GetProcessDEPPolicy crashes on Windows when a NULL pointer is passed.
2369 * Moreover this function has a bug on Windows 8, which has the effect that
2370 * policy_permanent is set to the content of the CL register instead of 0,
2371 * when the policy is not permanent. To detect that we use an assembler
2372 * wrapper to call the function. */
2374 memcpy( base, code_atl2, sizeof(code_atl2) );
2375 *(DWORD *)(base + 6) = (DWORD_PTR)pGetProcessDEPPolicy - (DWORD_PTR)(base + 10);
2377 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2378 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2380 success = get_dep_policy( GetCurrentProcess(), &policy_flags, &policy_permanent );
2381 ok( success, "GetProcessDEPPolicy failed %u\n", GetLastError() );
2383 ret = 0;
2384 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2385 ret |= PROCESS_DEP_ENABLE;
2386 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)
2387 ret |= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION;
2389 ok( policy_flags == ret, "expected policy flags %d, got %d\n", ret, policy_flags );
2390 ok( !policy_permanent || broken(policy_permanent == 0x44),
2391 "expected policy permanent FALSE, got %d\n", policy_permanent );
2394 memcpy( base, code_jmp, sizeof(code_jmp) );
2395 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2397 /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
2398 * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
2399 * where it is active, so that application which depend on that still work properly.
2400 * We have no exception handler enabled yet, so give proper EXECUTE permissions to
2401 * prevent crashes while creating the window. */
2403 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2404 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2406 memset( &wc, 0, sizeof(wc) );
2407 wc.cbSize = sizeof(wc);
2408 wc.style = CS_VREDRAW | CS_HREDRAW;
2409 wc.hInstance = GetModuleHandleA( 0 );
2410 wc.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW );
2411 wc.hbrBackground = NULL;
2412 wc.lpszClassName = cls_name;
2413 wc.lpfnWndProc = (WNDPROC)base;
2414 success = RegisterClassExA(&wc) != 0;
2415 ok( success, "RegisterClassExA failed %u\n", GetLastError() );
2417 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2418 ok( hWnd != 0, "CreateWindowExA failed %u\n", GetLastError() );
2420 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2421 ok( ret == 42, "SendMessage returned unexpected result %d\n", ret );
2423 /* At first try with an instruction which is not recognized as proper ATL thunk
2424 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2425 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2427 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2428 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2430 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2431 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2432 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2433 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && !IsProcessorFeaturePresent( PF_NX_ENABLED ))
2435 trace( "DEP hardware support is not available\n" );
2436 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2437 dep_flags = MEM_EXECUTE_OPTION_ENABLE;
2439 else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2441 trace( "DEP hardware support is available\n" );
2442 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2444 else
2445 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2447 /* Now a bit more complicated, the page containing the code is protected with
2448 * PAGE_GUARD memory protection. */
2450 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2451 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2453 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2454 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2455 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2456 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2457 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2458 else
2459 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2461 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2462 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2463 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2464 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2466 /* Now test with a proper ATL thunk instruction. */
2468 memcpy( base, code_atl1, sizeof(code_atl1) );
2469 *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
2471 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2472 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2474 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2475 ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
2477 /* Try executing with PAGE_READWRITE protection. */
2479 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2480 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2482 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2483 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2484 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2485 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2486 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2487 else
2488 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2490 /* Now a bit more complicated, the page containing the code is protected with
2491 * PAGE_GUARD memory protection. */
2493 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2494 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2496 /* the same, but with PAGE_GUARD set */
2497 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2498 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2499 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2500 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2501 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2502 else
2503 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2505 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2506 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2507 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2508 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2510 /* The following test shows that on Windows, even a vectored exception handler
2511 * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */
2513 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && !(dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2515 if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
2517 PVOID vectored_handler;
2519 success = VirtualProtect( base, size, PAGE_NOACCESS, &old_prot );
2520 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2522 vectored_handler = pRtlAddVectoredExceptionHandler( TRUE, &execute_fault_vec_handler );
2523 ok( vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n" );
2525 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2527 pRtlRemoveVectoredExceptionHandler( vectored_handler );
2529 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2530 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2532 else
2533 win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" );
2536 /* Test alternative ATL thunk instructions. */
2538 memcpy( base, code_atl2, sizeof(code_atl2) );
2539 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 10);
2541 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2542 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2544 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2545 /* FIXME: we don't check the content of the register ECX yet */
2546 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2547 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2548 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2549 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2550 else
2551 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2553 memcpy( base, code_atl3, sizeof(code_atl3) );
2554 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func;
2556 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2557 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2559 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2560 /* FIXME: we don't check the content of the registers ECX/EDX yet */
2561 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2562 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2563 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2564 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2565 else
2566 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2568 memcpy( base, code_atl4, sizeof(code_atl4) );
2569 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func;
2571 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2572 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2574 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2575 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2576 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2577 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2578 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2579 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2580 else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2581 ok( num_execute_fault_calls == 0 || broken(num_execute_fault_calls == 1) /* Windows XP */,
2582 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2583 else
2584 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2586 memcpy( base, code_atl5, sizeof(code_atl5) );
2588 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2589 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2591 ret = (DWORD_PTR)atl5_test_func;
2592 ret = call_proc_excpt( (void *)base, &ret - 1 );
2593 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2594 ok( ret == 44, "call returned wrong result, expected 44, got %d\n", ret );
2595 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2596 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2597 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2598 else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2599 ok( num_execute_fault_calls == 0 || broken(num_execute_fault_calls == 1) /* Windows XP */,
2600 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2601 else
2602 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2604 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2606 memcpy( base, code_jmp, sizeof(code_jmp) );
2607 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2609 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2610 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2612 DestroyWindow( hWnd );
2614 success = UnregisterClassA( cls_name, GetModuleHandleA(0) );
2615 ok( success, "UnregisterClass failed %u\n", GetLastError() );
2617 VirtualFree( base, 0, MEM_RELEASE );
2619 /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */
2621 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE );
2622 if (!base && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
2624 win_skip( "MEM_WRITE_WATCH not supported\n" );
2625 goto out;
2627 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2629 count = 64;
2630 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2631 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2632 ok( count == 0, "wrong count %lu\n", count );
2634 memcpy( base, code_jmp, sizeof(code_jmp) );
2635 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2637 count = 64;
2638 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2639 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2640 ok( count == 1, "wrong count %lu\n", count );
2641 ok( results[0] == base, "wrong result %p\n", results[0] );
2643 /* Create a new window class and associated Window (see above) */
2645 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2646 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2648 memset( &wc, 0, sizeof(wc) );
2649 wc.cbSize = sizeof(wc);
2650 wc.style = CS_VREDRAW | CS_HREDRAW;
2651 wc.hInstance = GetModuleHandleA( 0 );
2652 wc.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW );
2653 wc.hbrBackground = NULL;
2654 wc.lpszClassName = cls_name;
2655 wc.lpfnWndProc = (WNDPROC)base;
2656 success = RegisterClassExA(&wc) != 0;
2657 ok( success, "RegisterClassExA failed %u\n", GetLastError() );
2659 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2660 ok( hWnd != 0, "CreateWindowExA failed %u\n", GetLastError() );
2662 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2663 ok( ret == 42, "SendMessage returned unexpected result %d\n", ret );
2665 count = 64;
2666 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2667 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2668 ok( count == 0, "wrong count %lu\n", count );
2670 /* At first try with an instruction which is not recognized as proper ATL thunk
2671 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2672 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2674 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2675 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2677 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2678 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2679 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2680 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2681 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2682 else
2683 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2685 count = 64;
2686 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2687 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2688 ok( count == 0, "wrong count %lu\n", count );
2690 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2691 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2692 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2693 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2695 /* Now a bit more complicated, the page containing the code is protected with
2696 * PAGE_GUARD memory protection. */
2698 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2699 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2701 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2702 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2703 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2704 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2705 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2706 else
2707 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2709 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2710 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2711 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2712 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2714 count = 64;
2715 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2716 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2717 ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
2719 /* Now test with a proper ATL thunk instruction. */
2721 memcpy( base, code_atl1, sizeof(code_atl1) );
2722 *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
2724 count = 64;
2725 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2726 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2727 ok( count == 1, "wrong count %lu\n", count );
2728 ok( results[0] == base, "wrong result %p\n", results[0] );
2730 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2731 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2733 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2734 ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
2736 /* Try executing with PAGE_READWRITE protection. */
2738 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2739 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2741 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2742 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2743 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2744 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2745 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2746 else
2747 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2749 count = 64;
2750 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2751 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2752 ok( count == 0, "wrong count %lu\n", count );
2754 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2755 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2756 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2757 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2758 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2759 else
2760 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2762 /* Now a bit more complicated, the page containing the code is protected with
2763 * PAGE_GUARD memory protection. */
2765 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2766 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2768 /* the same, but with PAGE_GUARD set */
2769 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2770 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2771 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2772 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2773 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2774 else
2775 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2777 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2778 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2779 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2780 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2782 count = 64;
2783 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2784 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2785 ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
2787 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2789 memcpy( base, code_jmp, sizeof(code_jmp) );
2790 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2792 count = 64;
2793 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2794 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2795 ok( count == 1, "wrong count %lu\n", count );
2796 ok( results[0] == base, "wrong result %p\n", results[0] );
2798 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2799 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2801 DestroyWindow( hWnd );
2803 success = UnregisterClassA( cls_name, GetModuleHandleA(0) );
2804 ok( success, "UnregisterClass failed %u\n", GetLastError() );
2806 VirtualFree( base, 0, MEM_RELEASE );
2808 out:
2809 if (restore_flags)
2811 ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags) );
2812 ok( !ret, "NtSetInformationProcess failed with status %08x\n", ret );
2816 #endif /* __i386__ */
2818 static void test_VirtualProtect(void)
2820 static const struct test_data
2822 DWORD prot_set, prot_get;
2823 } td[] =
2825 { 0, 0 }, /* 0x00 */
2826 { PAGE_NOACCESS, PAGE_NOACCESS }, /* 0x01 */
2827 { PAGE_READONLY, PAGE_READONLY }, /* 0x02 */
2828 { PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x03 */
2829 { PAGE_READWRITE, PAGE_READWRITE }, /* 0x04 */
2830 { PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x05 */
2831 { PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x06 */
2832 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x07 */
2833 { PAGE_WRITECOPY, 0 }, /* 0x08 */
2834 { PAGE_WRITECOPY | PAGE_NOACCESS, 0 }, /* 0x09 */
2835 { PAGE_WRITECOPY | PAGE_READONLY, 0 }, /* 0x0a */
2836 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, 0 }, /* 0x0b */
2837 { PAGE_WRITECOPY | PAGE_READWRITE, 0 }, /* 0x0c */
2838 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x0d */
2839 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x0e */
2840 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x0f */
2842 { PAGE_EXECUTE, PAGE_EXECUTE }, /* 0x10 */
2843 { PAGE_EXECUTE_READ, PAGE_EXECUTE_READ }, /* 0x20 */
2844 { PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x30 */
2845 { PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_READWRITE }, /* 0x40 */
2846 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0x50 */
2847 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0x60 */
2848 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x70 */
2849 { PAGE_EXECUTE_WRITECOPY, 0 }, /* 0x80 */
2850 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, 0 }, /* 0x90 */
2851 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, 0 }, /* 0xa0 */
2852 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0xb0 */
2853 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, 0 }, /* 0xc0 */
2854 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0xd0 */
2855 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0xe0 */
2856 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 } /* 0xf0 */
2858 char *base, *ptr;
2859 DWORD ret, old_prot, rw_prot, exec_prot, i, j;
2860 MEMORY_BASIC_INFORMATION info;
2861 SYSTEM_INFO si;
2862 void *addr;
2863 SIZE_T size;
2864 NTSTATUS status;
2866 GetSystemInfo(&si);
2867 trace("system page size %#x\n", si.dwPageSize);
2869 SetLastError(0xdeadbeef);
2870 base = VirtualAlloc(0, si.dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
2871 ok(base != NULL, "VirtualAlloc failed %d\n", GetLastError());
2873 SetLastError(0xdeadbeef);
2874 ret = VirtualProtect(base, si.dwPageSize, PAGE_READONLY, NULL);
2875 ok(!ret, "VirtualProtect should fail\n");
2876 ok(GetLastError() == ERROR_NOACCESS, "expected ERROR_NOACCESS, got %d\n", GetLastError());
2877 old_prot = 0xdeadbeef;
2878 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
2879 ok(ret, "VirtualProtect failed %d\n", GetLastError());
2880 ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
2882 addr = base;
2883 size = si.dwPageSize;
2884 status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_READONLY, NULL);
2885 ok(status == STATUS_ACCESS_VIOLATION, "NtProtectVirtualMemory should fail, got %08x\n", status);
2886 addr = base;
2887 size = si.dwPageSize;
2888 old_prot = 0xdeadbeef;
2889 status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_NOACCESS, &old_prot);
2890 ok(status == STATUS_SUCCESS, "NtProtectVirtualMemory should succeed, got %08x\n", status);
2891 ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
2893 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2895 SetLastError(0xdeadbeef);
2896 ret = VirtualQuery(base, &info, sizeof(info));
2897 ok(ret, "VirtualQuery failed %d\n", GetLastError());
2898 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
2899 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
2900 ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect);
2901 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
2902 ok(info.AllocationProtect == PAGE_NOACCESS, "%d: %#x != PAGE_NOACCESS\n", i, info.AllocationProtect);
2903 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
2904 ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
2906 old_prot = 0xdeadbeef;
2907 SetLastError(0xdeadbeef);
2908 ret = VirtualProtect(base, si.dwPageSize, td[i].prot_set, &old_prot);
2909 if (td[i].prot_get)
2911 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
2912 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
2914 SetLastError(0xdeadbeef);
2915 ret = VirtualQuery(base, &info, sizeof(info));
2916 ok(ret, "VirtualQuery failed %d\n", GetLastError());
2917 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
2918 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
2919 ok(info.Protect == td[i].prot_get, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_get);
2920 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
2921 ok(info.AllocationProtect == PAGE_NOACCESS, "%d: %#x != PAGE_NOACCESS\n", i, info.AllocationProtect);
2922 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
2923 ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
2925 else
2927 ok(!ret, "%d: VirtualProtect should fail\n", i);
2928 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
2931 old_prot = 0xdeadbeef;
2932 SetLastError(0xdeadbeef);
2933 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
2934 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
2935 if (td[i].prot_get)
2936 ok(old_prot == td[i].prot_get, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_get);
2937 else
2938 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
2941 exec_prot = 0;
2943 for (i = 0; i <= 4; i++)
2945 rw_prot = 0;
2947 for (j = 0; j <= 4; j++)
2949 DWORD prot = exec_prot | rw_prot;
2951 SetLastError(0xdeadbeef);
2952 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, prot);
2953 if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
2955 ok(!ptr, "VirtualAlloc(%02x) should fail\n", prot);
2956 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2958 else
2960 if (prot & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))
2962 ok(!ptr, "VirtualAlloc(%02x) should fail\n", prot);
2963 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2965 else
2967 ok(ptr != NULL, "VirtualAlloc(%02x) error %d\n", prot, GetLastError());
2968 ok(ptr == base, "expected %p, got %p\n", base, ptr);
2972 SetLastError(0xdeadbeef);
2973 ret = VirtualProtect(base, si.dwPageSize, prot, &old_prot);
2974 if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
2976 ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
2977 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2979 else
2981 if (prot & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))
2983 ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
2984 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2986 else
2987 ok(ret, "VirtualProtect(%02x) error %d\n", prot, GetLastError());
2990 rw_prot = 1 << j;
2993 exec_prot = 1 << (i + 4);
2996 VirtualFree(base, 0, MEM_RELEASE);
2999 static BOOL is_mem_writable(DWORD prot)
3001 switch (prot & 0xff)
3003 case PAGE_READWRITE:
3004 case PAGE_WRITECOPY:
3005 case PAGE_EXECUTE_READWRITE:
3006 case PAGE_EXECUTE_WRITECOPY:
3007 return TRUE;
3009 default:
3010 return FALSE;
3014 static void test_VirtualAlloc_protection(void)
3016 static const struct test_data
3018 DWORD prot;
3019 BOOL success;
3020 } td[] =
3022 { 0, FALSE }, /* 0x00 */
3023 { PAGE_NOACCESS, TRUE }, /* 0x01 */
3024 { PAGE_READONLY, TRUE }, /* 0x02 */
3025 { PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x03 */
3026 { PAGE_READWRITE, TRUE }, /* 0x04 */
3027 { PAGE_READWRITE | PAGE_NOACCESS, FALSE }, /* 0x05 */
3028 { PAGE_READWRITE | PAGE_READONLY, FALSE }, /* 0x06 */
3029 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x07 */
3030 { PAGE_WRITECOPY, FALSE }, /* 0x08 */
3031 { PAGE_WRITECOPY | PAGE_NOACCESS, FALSE }, /* 0x09 */
3032 { PAGE_WRITECOPY | PAGE_READONLY, FALSE }, /* 0x0a */
3033 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, FALSE }, /* 0x0b */
3034 { PAGE_WRITECOPY | PAGE_READWRITE, FALSE }, /* 0x0c */
3035 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, FALSE }, /* 0x0d */
3036 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, FALSE }, /* 0x0e */
3037 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x0f */
3039 { PAGE_EXECUTE, TRUE }, /* 0x10 */
3040 { PAGE_EXECUTE_READ, TRUE }, /* 0x20 */
3041 { PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0x30 */
3042 { PAGE_EXECUTE_READWRITE, TRUE }, /* 0x40 */
3043 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE }, /* 0x50 */
3044 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE }, /* 0x60 */
3045 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0x70 */
3046 { PAGE_EXECUTE_WRITECOPY, FALSE }, /* 0x80 */
3047 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, FALSE }, /* 0x90 */
3048 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, FALSE }, /* 0xa0 */
3049 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0xb0 */
3050 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, FALSE }, /* 0xc0 */
3051 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE }, /* 0xd0 */
3052 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE }, /* 0xe0 */
3053 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE } /* 0xf0 */
3055 char *base, *ptr;
3056 DWORD ret, i;
3057 MEMORY_BASIC_INFORMATION info;
3058 SYSTEM_INFO si;
3060 GetSystemInfo(&si);
3061 trace("system page size %#x\n", si.dwPageSize);
3063 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3065 SetLastError(0xdeadbeef);
3066 base = VirtualAlloc(0, si.dwPageSize, MEM_COMMIT, td[i].prot);
3068 if (td[i].success)
3070 ok(base != NULL, "%d: VirtualAlloc failed %d\n", i, GetLastError());
3072 SetLastError(0xdeadbeef);
3073 ret = VirtualQuery(base, &info, sizeof(info));
3074 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3075 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
3076 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
3077 ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
3078 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
3079 ok(info.AllocationProtect == td[i].prot, "%d: %#x != %#x\n", i, info.AllocationProtect, td[i].prot);
3080 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
3081 ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
3083 if (is_mem_writable(info.Protect))
3085 base[0] = 0xfe;
3087 SetLastError(0xdeadbeef);
3088 ret = VirtualQuery(base, &info, sizeof(info));
3089 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3090 ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
3093 SetLastError(0xdeadbeef);
3094 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, td[i].prot);
3095 ok(ptr == base, "%d: VirtualAlloc failed %d\n", i, GetLastError());
3097 VirtualFree(base, 0, MEM_RELEASE);
3099 else
3101 ok(!base, "%d: VirtualAlloc should fail\n", i);
3102 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3107 static void test_CreateFileMapping_protection(void)
3109 static const struct test_data
3111 DWORD prot;
3112 BOOL success;
3113 DWORD prot_after_write;
3114 } td[] =
3116 { 0, FALSE, 0 }, /* 0x00 */
3117 { PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x01 */
3118 { PAGE_READONLY, TRUE, PAGE_READONLY }, /* 0x02 */
3119 { PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x03 */
3120 { PAGE_READWRITE, TRUE, PAGE_READWRITE }, /* 0x04 */
3121 { PAGE_READWRITE | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x05 */
3122 { PAGE_READWRITE | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x06 */
3123 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x07 */
3124 { PAGE_WRITECOPY, TRUE, PAGE_READWRITE }, /* 0x08 */
3125 { PAGE_WRITECOPY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x09 */
3126 { PAGE_WRITECOPY | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0a */
3127 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0b */
3128 { PAGE_WRITECOPY | PAGE_READWRITE, FALSE, PAGE_NOACCESS }, /* 0x0c */
3129 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x0d */
3130 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0e */
3131 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x0f */
3133 { PAGE_EXECUTE, FALSE, PAGE_EXECUTE }, /* 0x10 */
3134 { PAGE_EXECUTE_READ, TRUE, PAGE_EXECUTE_READ }, /* 0x20 */
3135 { PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_EXECUTE_READ }, /* 0x30 */
3136 { PAGE_EXECUTE_READWRITE, TRUE, PAGE_EXECUTE_READWRITE }, /* 0x40 */
3137 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x50 */
3138 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0x60 */
3139 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x70 */
3140 { PAGE_EXECUTE_WRITECOPY, TRUE, PAGE_EXECUTE_READWRITE }, /* 0x80 */
3141 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x90 */
3142 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0xa0 */
3143 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0xb0 */
3144 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, FALSE, PAGE_NOACCESS }, /* 0xc0 */
3145 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0xd0 */
3146 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0xe0 */
3147 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS } /* 0xf0 */
3149 char *base, *ptr;
3150 DWORD ret, i, alloc_prot, prot, old_prot;
3151 MEMORY_BASIC_INFORMATION info;
3152 SYSTEM_INFO si;
3153 char temp_path[MAX_PATH];
3154 char file_name[MAX_PATH];
3155 HANDLE hfile, hmap;
3156 BOOL page_exec_supported = TRUE;
3158 GetSystemInfo(&si);
3159 trace("system page size %#x\n", si.dwPageSize);
3161 GetTempPathA(MAX_PATH, temp_path);
3162 GetTempFileNameA(temp_path, "map", 0, file_name);
3164 SetLastError(0xdeadbeef);
3165 hfile = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
3166 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
3167 SetFilePointer(hfile, si.dwPageSize, NULL, FILE_BEGIN);
3168 SetEndOfFile(hfile);
3170 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3172 SetLastError(0xdeadbeef);
3173 hmap = CreateFileMappingW(hfile, NULL, td[i].prot | SEC_COMMIT, 0, si.dwPageSize, NULL);
3175 if (td[i].success)
3177 if (!hmap)
3179 trace("%d: CreateFileMapping(%04x) failed: %d\n", i, td[i].prot, GetLastError());
3180 /* NT4 and win2k don't support EXEC on file mappings */
3181 if (td[i].prot == PAGE_EXECUTE_READ || td[i].prot == PAGE_EXECUTE_READWRITE)
3183 page_exec_supported = FALSE;
3184 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i);
3185 continue;
3187 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3188 if (td[i].prot == PAGE_EXECUTE_WRITECOPY)
3190 page_exec_supported = FALSE;
3191 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
3192 continue;
3195 ok(hmap != 0, "%d: CreateFileMapping(%04x) error %d\n", i, td[i].prot, GetLastError());
3197 base = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0);
3198 ok(base != NULL, "%d: MapViewOfFile failed %d\n", i, GetLastError());
3200 SetLastError(0xdeadbeef);
3201 ret = VirtualQuery(base, &info, sizeof(info));
3202 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3203 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
3204 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
3205 ok(info.Protect == PAGE_READONLY, "%d: got %#x != expected PAGE_READONLY\n", i, info.Protect);
3206 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
3207 ok(info.AllocationProtect == PAGE_READONLY, "%d: %#x != PAGE_READONLY\n", i, info.AllocationProtect);
3208 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
3209 ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
3211 if (is_mem_writable(info.Protect))
3213 base[0] = 0xfe;
3215 SetLastError(0xdeadbeef);
3216 ret = VirtualQuery(base, &info, sizeof(info));
3217 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3218 ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
3221 SetLastError(0xdeadbeef);
3222 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, td[i].prot);
3223 ok(!ptr, "%d: VirtualAlloc(%02x) should fail\n", i, td[i].prot);
3224 /* FIXME: remove once Wine is fixed */
3225 todo_wine_if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
3226 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
3228 SetLastError(0xdeadbeef);
3229 ret = VirtualProtect(base, si.dwPageSize, td[i].prot, &old_prot);
3230 if (td[i].prot == PAGE_READONLY || td[i].prot == PAGE_WRITECOPY)
3231 ok(ret, "%d: VirtualProtect(%02x) error %d\n", i, td[i].prot, GetLastError());
3232 else
3234 ok(!ret, "%d: VirtualProtect(%02x) should fail\n", i, td[i].prot);
3235 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3238 UnmapViewOfFile(base);
3239 CloseHandle(hmap);
3241 else
3243 ok(!hmap, "%d: CreateFileMapping should fail\n", i);
3244 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3248 if (page_exec_supported) alloc_prot = PAGE_EXECUTE_READWRITE;
3249 else alloc_prot = PAGE_READWRITE;
3250 SetLastError(0xdeadbeef);
3251 hmap = CreateFileMappingW(hfile, NULL, alloc_prot, 0, si.dwPageSize, NULL);
3252 ok(hmap != 0, "%d: CreateFileMapping error %d\n", i, GetLastError());
3254 SetLastError(0xdeadbeef);
3255 base = MapViewOfFile(hmap, FILE_MAP_READ | FILE_MAP_WRITE | (page_exec_supported ? FILE_MAP_EXECUTE : 0), 0, 0, 0);
3256 ok(base != NULL, "MapViewOfFile failed %d\n", GetLastError());
3258 old_prot = 0xdeadbeef;
3259 SetLastError(0xdeadbeef);
3260 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
3261 ok(ret, "VirtualProtect error %d\n", GetLastError());
3262 ok(old_prot == alloc_prot, "got %#x != expected %#x\n", old_prot, alloc_prot);
3264 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3266 SetLastError(0xdeadbeef);
3267 ret = VirtualQuery(base, &info, sizeof(info));
3268 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3269 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
3270 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
3271 ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect);
3272 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
3273 ok(info.AllocationProtect == alloc_prot, "%d: %#x != %#x\n", i, info.AllocationProtect, alloc_prot);
3274 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
3275 ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
3277 old_prot = 0xdeadbeef;
3278 SetLastError(0xdeadbeef);
3279 ret = VirtualProtect(base, si.dwPageSize, td[i].prot, &old_prot);
3280 if (td[i].success || td[i].prot == PAGE_NOACCESS || td[i].prot == PAGE_EXECUTE)
3282 if (!ret)
3284 /* win2k and XP don't support EXEC on file mappings */
3285 if (td[i].prot == PAGE_EXECUTE)
3287 ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i);
3288 continue;
3290 /* NT4 and win2k don't support EXEC on file mappings */
3291 if (td[i].prot == PAGE_EXECUTE_READ || td[i].prot == PAGE_EXECUTE_READWRITE)
3293 ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i);
3294 continue;
3296 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3297 if (td[i].prot == PAGE_EXECUTE_WRITECOPY)
3299 ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
3300 continue;
3304 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
3305 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
3307 prot = td[i].prot;
3308 /* looks strange but Windows doesn't do this for PAGE_WRITECOPY */
3309 if (prot == PAGE_EXECUTE_WRITECOPY) prot = PAGE_EXECUTE_READWRITE;
3311 SetLastError(0xdeadbeef);
3312 ret = VirtualQuery(base, &info, sizeof(info));
3313 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3314 ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
3315 ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
3316 /* FIXME: remove the condition below once Wine is fixed */
3317 todo_wine_if (td[i].prot == PAGE_EXECUTE_WRITECOPY)
3318 ok(info.Protect == prot, "%d: got %#x != expected %#x\n", i, info.Protect, prot);
3319 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
3320 ok(info.AllocationProtect == alloc_prot, "%d: %#x != %#x\n", i, info.AllocationProtect, alloc_prot);
3321 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
3322 ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
3324 if (is_mem_writable(info.Protect))
3326 base[0] = 0xfe;
3328 SetLastError(0xdeadbeef);
3329 ret = VirtualQuery(base, &info, sizeof(info));
3330 ok(ret, "VirtualQuery failed %d\n", GetLastError());
3331 /* FIXME: remove the condition below once Wine is fixed */
3332 todo_wine_if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
3333 ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
3336 else
3338 ok(!ret, "%d: VirtualProtect should fail\n", i);
3339 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3340 continue;
3343 old_prot = 0xdeadbeef;
3344 SetLastError(0xdeadbeef);
3345 ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
3346 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
3347 /* FIXME: remove the condition below once Wine is fixed */
3348 todo_wine_if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
3349 ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
3352 UnmapViewOfFile(base);
3353 CloseHandle(hmap);
3355 CloseHandle(hfile);
3356 DeleteFileA(file_name);
3359 #define ACCESS_READ 0x01
3360 #define ACCESS_WRITE 0x02
3361 #define ACCESS_EXECUTE 0x04
3362 #define ACCESS_WRITECOPY 0x08
3364 static DWORD page_prot_to_access(DWORD prot)
3366 switch (prot)
3368 case PAGE_READWRITE:
3369 return ACCESS_READ | ACCESS_WRITE;
3371 case PAGE_EXECUTE:
3372 case PAGE_EXECUTE_READ:
3373 return ACCESS_READ | ACCESS_EXECUTE;
3375 case PAGE_EXECUTE_READWRITE:
3376 return ACCESS_READ | ACCESS_WRITE | ACCESS_WRITECOPY | ACCESS_EXECUTE;
3378 case PAGE_EXECUTE_WRITECOPY:
3379 return ACCESS_READ | ACCESS_WRITECOPY | ACCESS_EXECUTE;
3381 case PAGE_READONLY:
3382 return ACCESS_READ;
3384 case PAGE_WRITECOPY:
3385 return ACCESS_READ;
3387 default:
3388 return 0;
3392 static BOOL is_compatible_protection(DWORD map_prot, DWORD view_prot, DWORD prot)
3394 DWORD map_access, view_access, prot_access;
3396 map_access = page_prot_to_access(map_prot);
3397 view_access = page_prot_to_access(view_prot);
3398 prot_access = page_prot_to_access(prot);
3400 if (view_access == prot_access) return TRUE;
3401 if (!view_access) return FALSE;
3403 if ((view_access & prot_access) != prot_access) return FALSE;
3404 if ((map_access & prot_access) == prot_access) return TRUE;
3406 return FALSE;
3409 static DWORD map_prot_to_access(DWORD prot)
3411 switch (prot)
3413 case PAGE_READWRITE:
3414 case PAGE_EXECUTE_READWRITE:
3415 return SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT | SECTION_QUERY;
3416 case PAGE_READONLY:
3417 case PAGE_WRITECOPY:
3418 case PAGE_EXECUTE:
3419 case PAGE_EXECUTE_READ:
3420 case PAGE_EXECUTE_WRITECOPY:
3421 return SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT | SECTION_QUERY;
3422 default:
3423 return 0;
3427 static BOOL is_compatible_access(DWORD map_prot, DWORD view_prot)
3429 DWORD access = map_prot_to_access(map_prot);
3430 if (!view_prot) view_prot = SECTION_MAP_READ;
3431 return (view_prot & access) == view_prot;
3434 static void *map_view_of_file(HANDLE handle, DWORD access)
3436 NTSTATUS status;
3437 LARGE_INTEGER offset;
3438 SIZE_T count;
3439 ULONG protect;
3440 BOOL exec;
3441 void *addr;
3443 if (!pNtMapViewOfSection) return NULL;
3445 count = 0;
3446 offset.u.LowPart = 0;
3447 offset.u.HighPart = 0;
3449 exec = access & FILE_MAP_EXECUTE;
3450 access &= ~FILE_MAP_EXECUTE;
3452 if (access == FILE_MAP_COPY)
3454 if (exec)
3455 protect = PAGE_EXECUTE_WRITECOPY;
3456 else
3457 protect = PAGE_WRITECOPY;
3459 else if (access & FILE_MAP_WRITE)
3461 if (exec)
3462 protect = PAGE_EXECUTE_READWRITE;
3463 else
3464 protect = PAGE_READWRITE;
3466 else if (access & FILE_MAP_READ)
3468 if (exec)
3469 protect = PAGE_EXECUTE_READ;
3470 else
3471 protect = PAGE_READONLY;
3473 else protect = PAGE_NOACCESS;
3475 addr = NULL;
3476 status = pNtMapViewOfSection(handle, GetCurrentProcess(), &addr, 0, 0, &offset,
3477 &count, 1 /* ViewShare */, 0, protect);
3478 if (status)
3480 /* for simplicity */
3481 SetLastError(ERROR_ACCESS_DENIED);
3482 addr = NULL;
3484 return addr;
3487 static void test_mapping(void)
3489 static const DWORD page_prot[] =
3491 PAGE_NOACCESS, PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY,
3492 PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY
3494 static const struct
3496 DWORD access, prot;
3497 } view[] =
3499 { 0, PAGE_NOACCESS }, /* 0x00 */
3500 { FILE_MAP_COPY, PAGE_WRITECOPY }, /* 0x01 */
3501 { FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x02 */
3502 { FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x03 */
3503 { FILE_MAP_READ, PAGE_READONLY }, /* 0x04 */
3504 { FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x05 */
3505 { FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x06 */
3506 { FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x07 */
3507 { SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x08 */
3508 { SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x09 */
3509 { SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0a */
3510 { SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0b */
3511 { SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_READONLY }, /* 0x0c */
3512 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x0d */
3513 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0e */
3514 { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0f */
3515 { FILE_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x20 */
3516 { FILE_MAP_EXECUTE | FILE_MAP_COPY, PAGE_EXECUTE_WRITECOPY }, /* 0x21 */
3517 { FILE_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x22 */
3518 { FILE_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x23 */
3519 { FILE_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x24 */
3520 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x25 */
3521 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x26 */
3522 { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x27 */
3523 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x28 */
3524 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x29 */
3525 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2a */
3526 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x2b */
3527 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x2c */
3528 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x2d */
3529 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2e */
3530 { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE } /* 0x2f */
3532 void *base, *nt_base, *ptr;
3533 DWORD i, j, k, ret, old_prot, prev_prot;
3534 SYSTEM_INFO si;
3535 char temp_path[MAX_PATH];
3536 char file_name[MAX_PATH];
3537 HANDLE hfile, hmap;
3538 MEMORY_BASIC_INFORMATION info, nt_info;
3540 GetSystemInfo(&si);
3541 trace("system page size %#x\n", si.dwPageSize);
3543 GetTempPathA(MAX_PATH, temp_path);
3544 GetTempFileNameA(temp_path, "map", 0, file_name);
3546 SetLastError(0xdeadbeef);
3547 hfile = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
3548 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
3549 SetFilePointer(hfile, si.dwPageSize, NULL, FILE_BEGIN);
3550 SetEndOfFile(hfile);
3552 for (i = 0; i < sizeof(page_prot)/sizeof(page_prot[0]); i++)
3554 SetLastError(0xdeadbeef);
3555 hmap = CreateFileMappingW(hfile, NULL, page_prot[i] | SEC_COMMIT, 0, si.dwPageSize, NULL);
3557 if (page_prot[i] == PAGE_NOACCESS)
3559 HANDLE hmap2;
3561 ok(!hmap, "CreateFileMapping(PAGE_NOACCESS) should fail\n");
3562 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3564 /* A trick to create a not accessible mapping */
3565 SetLastError(0xdeadbeef);
3566 hmap = CreateFileMappingW(hfile, NULL, PAGE_READWRITE | SEC_COMMIT, 0, si.dwPageSize, NULL);
3567 ok(hmap != 0, "CreateFileMapping(PAGE_READWRITE) error %d\n", GetLastError());
3568 SetLastError(0xdeadbeef);
3569 ret = DuplicateHandle(GetCurrentProcess(), hmap, GetCurrentProcess(), &hmap2, 0, FALSE, 0);
3570 ok(ret, "DuplicateHandle error %d\n", GetLastError());
3571 CloseHandle(hmap);
3572 hmap = hmap2;
3575 if (!hmap)
3577 trace("%d: CreateFileMapping(%04x) failed: %d\n", i, page_prot[i], GetLastError());
3579 /* NT4 and win2k don't support EXEC on file mappings */
3580 if (page_prot[i] == PAGE_EXECUTE_READ || page_prot[i] == PAGE_EXECUTE_READWRITE)
3582 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i);
3583 continue;
3585 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3586 if (page_prot[i] == PAGE_EXECUTE_WRITECOPY)
3588 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
3589 continue;
3593 ok(hmap != 0, "%d: CreateFileMapping(%04x) error %d\n", i, page_prot[i], GetLastError());
3595 for (j = 0; j < sizeof(view)/sizeof(view[0]); j++)
3597 nt_base = map_view_of_file(hmap, view[j].access);
3598 if (nt_base)
3600 SetLastError(0xdeadbeef);
3601 ret = VirtualQuery(nt_base, &nt_info, sizeof(nt_info));
3602 ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
3603 UnmapViewOfFile(nt_base);
3606 SetLastError(0xdeadbeef);
3607 base = MapViewOfFile(hmap, view[j].access, 0, 0, 0);
3609 /* Vista+ supports FILE_MAP_EXECUTE properly, earlier versions don't */
3610 ok(!nt_base == !base ||
3611 broken((view[j].access & FILE_MAP_EXECUTE) && !nt_base != !base),
3612 "%d: (%04x/%04x) NT %p kernel %p\n", j, page_prot[i], view[j].access, nt_base, base);
3614 if (!is_compatible_access(page_prot[i], view[j].access))
3616 ok(!base, "%d: MapViewOfFile(%04x/%04x) should fail\n", j, page_prot[i], view[j].access);
3617 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
3618 continue;
3621 /* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */
3622 if (!base && (view[j].access & FILE_MAP_EXECUTE))
3624 ok(broken(!base), "%d: MapViewOfFile(%04x/%04x) failed %d\n", j, page_prot[i], view[j].access, GetLastError());
3625 continue;
3628 ok(base != NULL, "%d: MapViewOfFile(%04x/%04x) failed %d\n", j, page_prot[i], view[j].access, GetLastError());
3630 SetLastError(0xdeadbeef);
3631 ret = VirtualQuery(base, &info, sizeof(info));
3632 ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
3633 ok(info.BaseAddress == base, "%d: (%04x) got %p, expected %p\n", j, view[j].access, info.BaseAddress, base);
3634 ok(info.RegionSize == si.dwPageSize, "%d: (%04x) got %#lx != expected %#x\n", j, view[j].access, info.RegionSize, si.dwPageSize);
3635 ok(info.Protect == view[j].prot ||
3636 broken(view[j].prot == PAGE_EXECUTE_READ && info.Protect == PAGE_READONLY) || /* win2k */
3637 broken(view[j].prot == PAGE_EXECUTE_READWRITE && info.Protect == PAGE_READWRITE) || /* win2k */
3638 broken(view[j].prot == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
3639 "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.Protect, view[j].prot);
3640 ok(info.AllocationBase == base, "%d: (%04x) got %p, expected %p\n", j, view[j].access, info.AllocationBase, base);
3641 ok(info.AllocationProtect == info.Protect, "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.AllocationProtect, info.Protect);
3642 ok(info.State == MEM_COMMIT, "%d: (%04x) got %#x, expected MEM_COMMIT\n", j, view[j].access, info.State);
3643 ok(info.Type == MEM_MAPPED, "%d: (%04x) got %#x, expected MEM_MAPPED\n", j, view[j].access, info.Type);
3645 if (nt_base && base)
3647 ok(nt_info.RegionSize == info.RegionSize, "%d: (%04x) got %#lx != expected %#lx\n", j, view[j].access, nt_info.RegionSize, info.RegionSize);
3648 ok(nt_info.Protect == info.Protect /* Vista+ */ ||
3649 broken(nt_info.AllocationProtect == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
3650 "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.Protect, info.Protect);
3651 ok(nt_info.AllocationProtect == info.AllocationProtect /* Vista+ */ ||
3652 broken(nt_info.AllocationProtect == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
3653 "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.AllocationProtect, info.AllocationProtect);
3654 ok(nt_info.State == info.State, "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.State, info.State);
3655 ok(nt_info.Type == info.Type, "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, nt_info.Type, info.Type);
3658 prev_prot = info.Protect;
3660 for (k = 0; k < sizeof(page_prot)/sizeof(page_prot[0]); k++)
3662 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3663 SetLastError(0xdeadbeef);
3664 old_prot = 0xdeadbeef;
3665 ret = VirtualProtect(base, si.dwPageSize, page_prot[k], &old_prot);
3666 if (is_compatible_protection(page_prot[i], view[j].prot, page_prot[k]))
3668 /* win2k and XP don't support EXEC on file mappings */
3669 if (!ret && page_prot[k] == PAGE_EXECUTE)
3671 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3672 continue;
3674 /* NT4 and win2k don't support EXEC on file mappings */
3675 if (!ret && (page_prot[k] == PAGE_EXECUTE_READ || page_prot[k] == PAGE_EXECUTE_READWRITE))
3677 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3678 continue;
3680 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3681 if (!ret && page_prot[k] == PAGE_EXECUTE_WRITECOPY)
3683 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n");
3684 continue;
3686 /* win2k and XP don't support PAGE_EXECUTE_WRITECOPY views properly */
3687 if (!ret && view[j].prot == PAGE_EXECUTE_WRITECOPY)
3689 ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY view properly\n");
3690 continue;
3693 ok(ret, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot[i], view[j].prot, page_prot[k]);
3694 ok(old_prot == prev_prot, "got %#x, expected %#x\n", old_prot, prev_prot);
3695 prev_prot = page_prot[k];
3697 else
3699 /* NT4 doesn't fail on incompatible map and view */
3700 if (ret)
3702 ok(broken(ret), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
3703 skip("Incompatible map and view are not properly handled on this platform\n");
3704 break; /* NT4 won't pass remaining tests */
3707 ok(!ret, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
3708 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3712 for (k = 0; k < sizeof(page_prot)/sizeof(page_prot[0]); k++)
3714 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3715 SetLastError(0xdeadbeef);
3716 ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, page_prot[k]);
3717 ok(!ptr, "VirtualAlloc(%02x) should fail\n", page_prot[k]);
3718 /* FIXME: remove once Wine is fixed */
3719 todo_wine_if (page_prot[k] == PAGE_WRITECOPY || page_prot[k] == PAGE_EXECUTE_WRITECOPY)
3720 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3723 UnmapViewOfFile(base);
3726 CloseHandle(hmap);
3729 CloseHandle(hfile);
3730 DeleteFileA(file_name);
3733 static void test_shared_memory(BOOL is_child)
3735 HANDLE mapping;
3736 LONG *p;
3738 SetLastError(0xdeadbef);
3739 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_virtual.c");
3740 ok(mapping != 0, "CreateFileMapping error %d\n", GetLastError());
3741 if (is_child)
3742 ok(GetLastError() == ERROR_ALREADY_EXISTS, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3744 SetLastError(0xdeadbef);
3745 p = MapViewOfFile(mapping, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 4096);
3746 ok(p != NULL, "MapViewOfFile error %d\n", GetLastError());
3748 if (is_child)
3750 ok(*p == 0x1a2b3c4d, "expected 0x1a2b3c4d in child, got %#x\n", *p);
3752 else
3754 char **argv;
3755 char cmdline[MAX_PATH];
3756 PROCESS_INFORMATION pi;
3757 STARTUPINFOA si = { sizeof(si) };
3758 DWORD ret;
3760 *p = 0x1a2b3c4d;
3762 winetest_get_mainargs(&argv);
3763 sprintf(cmdline, "\"%s\" virtual sharedmem", argv[0]);
3764 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
3765 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
3766 winetest_wait_child_process(pi.hProcess);
3767 CloseHandle(pi.hThread);
3768 CloseHandle(pi.hProcess);
3771 UnmapViewOfFile(p);
3772 CloseHandle(mapping);
3775 static void test_shared_memory_ro(BOOL is_child, DWORD child_access)
3777 HANDLE mapping;
3778 LONG *p;
3780 SetLastError(0xdeadbef);
3781 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_virtual.c_ro");
3782 ok(mapping != 0, "CreateFileMapping error %d\n", GetLastError());
3783 if (is_child)
3784 ok(GetLastError() == ERROR_ALREADY_EXISTS, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3786 SetLastError(0xdeadbef);
3787 p = MapViewOfFile(mapping, is_child ? child_access : FILE_MAP_READ, 0, 0, 4096);
3788 ok(p != NULL, "MapViewOfFile error %d\n", GetLastError());
3790 if (is_child)
3792 *p = 0xdeadbeef;
3794 else
3796 char **argv;
3797 char cmdline[MAX_PATH];
3798 PROCESS_INFORMATION pi;
3799 STARTUPINFOA si = { sizeof(si) };
3800 DWORD ret;
3802 winetest_get_mainargs(&argv);
3803 sprintf(cmdline, "\"%s\" virtual sharedmemro %x", argv[0], child_access);
3804 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
3805 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
3806 winetest_wait_child_process(pi.hProcess);
3807 CloseHandle(pi.hThread);
3808 CloseHandle(pi.hProcess);
3810 if(child_access & FILE_MAP_WRITE)
3811 ok(*p == 0xdeadbeef, "*p = %x, expected 0xdeadbeef\n", *p);
3812 else
3813 ok(!*p, "*p = %x, expected 0\n", *p);
3816 UnmapViewOfFile(p);
3817 CloseHandle(mapping);
3820 START_TEST(virtual)
3822 int argc;
3823 char **argv;
3824 argc = winetest_get_mainargs( &argv );
3826 if (argc >= 3)
3828 if (!strcmp(argv[2], "sleep"))
3830 Sleep(5000); /* spawned process runs for at most 5 seconds */
3831 return;
3833 if (!strcmp(argv[2], "sharedmem"))
3835 test_shared_memory(TRUE);
3836 return;
3838 if (!strcmp(argv[2], "sharedmemro"))
3840 test_shared_memory_ro(TRUE, strtol(argv[3], NULL, 16));
3841 return;
3843 while (1)
3845 void *mem;
3846 BOOL ret;
3847 mem = VirtualAlloc(NULL, 1<<20, MEM_COMMIT|MEM_RESERVE,
3848 PAGE_EXECUTE_READWRITE);
3849 ok(mem != NULL, "VirtualAlloc failed %u\n", GetLastError());
3850 if (mem == NULL) break;
3851 ret = VirtualFree(mem, 0, MEM_RELEASE);
3852 ok(ret, "VirtualFree failed %u\n", GetLastError());
3853 if (!ret) break;
3855 return;
3858 hkernel32 = GetModuleHandleA("kernel32.dll");
3859 hntdll = GetModuleHandleA("ntdll.dll");
3861 pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
3862 pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
3863 pGetWriteWatch = (void *) GetProcAddress(hkernel32, "GetWriteWatch");
3864 pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch");
3865 pGetProcessDEPPolicy = (void *)GetProcAddress( hkernel32, "GetProcessDEPPolicy" );
3866 pIsWow64Process = (void *)GetProcAddress( hkernel32, "IsWow64Process" );
3867 pNtAreMappedFilesTheSame = (void *)GetProcAddress( hntdll, "NtAreMappedFilesTheSame" );
3868 pNtCreateSection = (void *)GetProcAddress( hntdll, "NtCreateSection" );
3869 pNtMapViewOfSection = (void *)GetProcAddress( hntdll, "NtMapViewOfSection" );
3870 pNtUnmapViewOfSection = (void *)GetProcAddress( hntdll, "NtUnmapViewOfSection" );
3871 pNtQuerySection = (void *)GetProcAddress( hntdll, "NtQuerySection" );
3872 pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlAddVectoredExceptionHandler" );
3873 pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlRemoveVectoredExceptionHandler" );
3874 pNtProtectVirtualMemory = (void *)GetProcAddress( hntdll, "NtProtectVirtualMemory" );
3875 pNtAllocateVirtualMemory = (void *)GetProcAddress( hntdll, "NtAllocateVirtualMemory" );
3876 pNtFreeVirtualMemory = (void *)GetProcAddress( hntdll, "NtFreeVirtualMemory" );
3878 test_shared_memory(FALSE);
3879 test_shared_memory_ro(FALSE, FILE_MAP_READ|FILE_MAP_WRITE);
3880 test_shared_memory_ro(FALSE, FILE_MAP_COPY);
3881 test_shared_memory_ro(FALSE, FILE_MAP_COPY|FILE_MAP_WRITE);
3882 test_mapping();
3883 test_CreateFileMapping_protection();
3884 test_VirtualAlloc_protection();
3885 test_VirtualProtect();
3886 test_VirtualAllocEx();
3887 test_VirtualAlloc();
3888 test_MapViewOfFile();
3889 test_NtMapViewOfSection();
3890 test_NtAreMappedFilesTheSame();
3891 test_CreateFileMapping();
3892 test_IsBadReadPtr();
3893 test_IsBadWritePtr();
3894 test_IsBadCodePtr();
3895 test_write_watch();
3896 #if defined(__i386__) || defined(__x86_64__)
3897 test_stack_commit();
3898 #endif
3899 #ifdef __i386__
3900 test_guard_page();
3901 /* The following tests should be executed as a last step, and in exactly this
3902 * order, since ATL thunk emulation cannot be enabled anymore on Windows. */
3903 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE );
3904 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE );
3905 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION );
3906 #endif