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