018b7e9ae07d8a18ea42529200cc934a2962649c
[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 /* 21 zero bits is valid */
407 size = 0x1000;
408 addr2 = NULL;
409 status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 21, &size,
410 MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
411 ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY,
412 "NtAllocateVirtualMemory returned %08x\n", status);
413 if (status == STATUS_SUCCESS) ok(VirtualFree(addr2, 0, MEM_RELEASE), "VirtualFree failed\n");
414
415 /* 22 zero bits is invalid */
416 size = 0x1000;
417 addr2 = NULL;
418 status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 22, &size,
419 MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
420 ok(status == STATUS_INVALID_PARAMETER_3, "NtAllocateVirtualMemory returned %08x\n", status);
421 if (status == STATUS_SUCCESS) ok(VirtualFree(addr2, 0, MEM_RELEASE), "VirtualFree failed\n");
422
423 /* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
424 SetLastError(0xdeadbeef);
425 addr2 = VirtualAlloc(addr1, 0x1000, MEM_RESERVE | MEM_COMMIT | AT_ROUND_TO_PAGE, PAGE_EXECUTE_READWRITE);
426 ok(!addr2, "VirtualAlloc unexpectedly succeeded\n");
427 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
428
429 /* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
430 size = 0x1000;
431 addr2 = (char *)addr1 + 0x1000;
432 status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 0, &size, MEM_RESERVE |
433 MEM_COMMIT | AT_ROUND_TO_PAGE, PAGE_EXECUTE_READWRITE);
434 todo_wine
435 ok(status == STATUS_INVALID_PARAMETER_5, "NtAllocateVirtualMemory returned %08x\n", status);
436
437 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
438 }
439
440 static void test_MapViewOfFile(void)
441 {
442 static const char testfile[] = "testfile.xxx";
443 const char *name;
444 HANDLE file, mapping, map2;
445 void *ptr, *ptr2, *addr;
446 SECTION_BASIC_INFORMATION section_info;
447 SECTION_IMAGE_INFORMATION image_info;
448 MEMORY_BASIC_INFORMATION info;
449 BOOL ret;
450 SIZE_T size;
451 NTSTATUS status;
452 ULONG info_size;
453 LARGE_INTEGER map_size;
454
455 SetLastError(0xdeadbeef);
456 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
457 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
458 SetFilePointer( file, 12288, NULL, FILE_BEGIN );
459 SetEndOfFile( file );
460
461 /* read/write mapping */
462
463 SetLastError(0xdeadbeef);
464 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
465 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
466
467 SetLastError(0xdeadbeef);
468 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
469 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
470 UnmapViewOfFile( ptr );
471
472 SetLastError(0xdeadbeef);
473 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
474 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
475 UnmapViewOfFile( ptr );
476
477 SetLastError(0xdeadbeef);
478 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
479 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
480 UnmapViewOfFile( ptr );
481
482 SetLastError(0xdeadbeef);
483 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
484 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
485 UnmapViewOfFile( ptr );
486
487 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
488 FILE_MAP_READ|FILE_MAP_WRITE, FALSE, 0 );
489 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
490 ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
491 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
492 UnmapViewOfFile( ptr );
493 CloseHandle( map2 );
494
495 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
496 FILE_MAP_READ, FALSE, 0 );
497 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
498 SetLastError(0xdeadbeef);
499 ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
500 ok( !ptr, "MapViewOfFile succeeded\n" );
501 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
502 CloseHandle( map2 );
503 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2, 0, FALSE, 0 );
504 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
505 SetLastError(0xdeadbeef);
506 ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
507 ok( !ptr, "MapViewOfFile succeeded\n" );
508 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
509 CloseHandle( map2 );
510 ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
511 FILE_MAP_READ, FALSE, 0 );
512 ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
513 ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
514 ok( ptr != NULL, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
515
516 UnmapViewOfFile( ptr );
517 CloseHandle( map2 );
518 CloseHandle( mapping );
519
520 /* read-only mapping */
521
522 SetLastError(0xdeadbeef);
523 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
524 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
525
526 SetLastError(0xdeadbeef);
527 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
528 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
529 UnmapViewOfFile( ptr );
530
531 SetLastError(0xdeadbeef);
532 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
533 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
534 UnmapViewOfFile( ptr );
535
536 SetLastError(0xdeadbeef);
537 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
538 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
539 UnmapViewOfFile( ptr );
540
541 SetLastError(0xdeadbeef);
542 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
543 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
544 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
545 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
546 CloseHandle( mapping );
547
548 /* copy-on-write mapping */
549
550 SetLastError(0xdeadbeef);
551 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
552 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
553
554 SetLastError(0xdeadbeef);
555 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
556 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
557 UnmapViewOfFile( ptr );
558
559 SetLastError(0xdeadbeef);
560 ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
561 ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
562 UnmapViewOfFile( ptr );
563
564 SetLastError(0xdeadbeef);
565 ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
566 ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
567 UnmapViewOfFile( ptr );
568
569 SetLastError(0xdeadbeef);
570 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
571 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
572 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
573 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
574 CloseHandle( mapping );
575
576 /* no access mapping */
577
578 SetLastError(0xdeadbeef);
579 mapping = CreateFileMappingA( file, NULL, PAGE_NOACCESS, 0, 4096, NULL );
580 ok( !mapping, "CreateFileMappingA succeeded\n" );
581 ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
582 CloseHandle( file );
583
584 /* now try read-only file */
585
586 SetLastError(0xdeadbeef);
587 file = CreateFileA( testfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
588 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
589
590 SetLastError(0xdeadbeef);
591 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
592 ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
593 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
594 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
595
596 SetLastError(0xdeadbeef);
597 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
598 ok( mapping != 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
599 CloseHandle( mapping );
600
601 SetLastError(0xdeadbeef);
602 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
603 ok( mapping != 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
604 CloseHandle( mapping );
605 CloseHandle( file );
606
607 /* now try no access file */
608
609 SetLastError(0xdeadbeef);
610 file = CreateFileA( testfile, 0, 0, NULL, OPEN_EXISTING, 0, 0 );
611 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
612
613 SetLastError(0xdeadbeef);
614 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
615 ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
616 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
617 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
618
619 SetLastError(0xdeadbeef);
620 mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
621 ok( !mapping, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
622 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
623 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
624
625 SetLastError(0xdeadbeef);
626 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
627 ok( !mapping, "CreateFileMapping PAGE_READONLY succeeded\n" );
628 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
629 GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
630
631 CloseHandle( file );
632 DeleteFileA( testfile );
633
634 SetLastError(0xdeadbeef);
635 name = "Local\\Foo";
636 file = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4090, name );
637 /* nt4 doesn't have Local\\ */
638 if (!file && GetLastError() == ERROR_PATH_NOT_FOUND)
639 {
640 name = "Foo";
641 file = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4090, name );
642 }
643 ok( file != 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
644
645 SetLastError(0xdeadbeef);
646 mapping = OpenFileMappingA( FILE_MAP_READ, FALSE, name );
647 ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
648 SetLastError(0xdeadbeef);
649 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
650 ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
651 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
652 SetLastError(0xdeadbeef);
653 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
654 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
655 SetLastError(0xdeadbeef);
656 size = VirtualQuery( ptr, &info, sizeof(info) );
657 ok( size == sizeof(info),
658 "VirtualQuery error %u\n", GetLastError() );
659 ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
660 ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
661 ok( info.AllocationProtect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.AllocationProtect );
662 ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
663 ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
664 ok( info.Protect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.Protect );
665 UnmapViewOfFile( ptr );
666 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
667 sizeof(section_info), &info_size );
668 ok( status == STATUS_ACCESS_DENIED, "NtQuerySection failed err %x\n", status );
669 CloseHandle( mapping );
670 mapping = OpenFileMappingA( FILE_MAP_READ | SECTION_QUERY, FALSE, name );
671 ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
672 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
673 sizeof(section_info), &info_size );
674 ok( !status, "NtQuerySection failed err %x\n", status );
675 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
676 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
677 section_info.Attributes );
678 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
679 ok( section_info.Size.QuadPart == info.RegionSize, "NtQuerySection wrong size %x%08x / %08lx\n",
680 section_info.Size.u.HighPart, section_info.Size.u.LowPart, info.RegionSize );
681 CloseHandle( mapping );
682
683 SetLastError(0xdeadbeef);
684 mapping = OpenFileMappingA( FILE_MAP_WRITE, FALSE, name );
685 ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
686 SetLastError(0xdeadbeef);
687 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
688 ok( !ptr, "MapViewOfFile succeeded\n" );
689 ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
690 SetLastError(0xdeadbeef);
691 ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
692 ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
693 SetLastError(0xdeadbeef);
694 size = VirtualQuery( ptr, &info, sizeof(info) );
695 ok( size == sizeof(info),
696 "VirtualQuery error %u\n", GetLastError() );
697 ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
698 ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
699 ok( info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect );
700 ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
701 ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
702 ok( info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect );
703 UnmapViewOfFile( ptr );
704 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
705 sizeof(section_info), &info_size );
706 ok( status == STATUS_ACCESS_DENIED, "NtQuerySection failed err %x\n", status );
707 CloseHandle( mapping );
708
709 mapping = OpenFileMappingA( FILE_MAP_WRITE | SECTION_QUERY, FALSE, name );
710 ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
711 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
712 sizeof(section_info), &info_size );
713 ok( !status, "NtQuerySection failed err %x\n", status );
714 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
715 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
716 section_info.Attributes );
717 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
718 ok( section_info.Size.QuadPart == info.RegionSize, "NtQuerySection wrong size %x%08x / %08lx\n",
719 section_info.Size.u.HighPart, section_info.Size.u.LowPart, info.RegionSize );
720 CloseHandle( mapping );
721
722 CloseHandle( file );
723
724 /* read/write mapping with SEC_RESERVE */
725 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_RESERVE, 0, MAPPING_SIZE, NULL);
726 ok(mapping != INVALID_HANDLE_VALUE, "CreateFileMappingA failed with error %d\n", GetLastError());
727 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
728 sizeof(section_info), NULL );
729 ok( !status, "NtQuerySection failed err %x\n", status );
730 ok( section_info.Attributes == SEC_RESERVE, "NtQuerySection wrong attr %08x\n",
731 section_info.Attributes );
732 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
733 ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %x%08x / %08x\n",
734 section_info.Size.u.HighPart, section_info.Size.u.LowPart, MAPPING_SIZE );
735
736 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
737 ok(ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
738
739 ptr2 = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
740 ok( ptr2 != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
741 ok( ptr != ptr2, "MapViewOfFile returned same pointer\n" );
742
743 ret = VirtualQuery(ptr, &info, sizeof(info));
744 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
745 ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
746 ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
747 ok(info.RegionSize == MAPPING_SIZE, "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE, info.RegionSize);
748 ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
749 ok(info.AllocationProtect == PAGE_READWRITE,
750 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
751 ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
752 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
753
754 ret = VirtualQuery(ptr2, &info, sizeof(info));
755 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
756 ok(info.BaseAddress == ptr2,
757 "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
758 ok(info.AllocationBase == ptr2,
759 "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
760 ok(info.AllocationProtect == PAGE_READWRITE,
761 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
762 ok(info.RegionSize == MAPPING_SIZE,
763 "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE, info.RegionSize);
764 ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
765 ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
766 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
767
768 ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY);
769 ok(ptr != NULL, "VirtualAlloc failed with error %d\n", GetLastError());
770
771 ret = VirtualQuery(ptr, &info, sizeof(info));
772 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
773 ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
774 ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
775 ok(info.RegionSize == 0x10000, "RegionSize should have been 0x10000 but was 0x%lx\n", info.RegionSize);
776 ok(info.State == MEM_COMMIT, "State should have been MEM_COMMIT instead of 0x%x\n", info.State);
777 ok(info.Protect == PAGE_READONLY, "Protect should have been PAGE_READONLY instead of 0x%x\n", info.Protect);
778 ok(info.AllocationProtect == PAGE_READWRITE,
779 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
780 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
781
782 /* shows that the VirtualAlloc above affects the mapping, not just the
783 * virtual memory in this process - it also affects all other processes
784 * with a view of the mapping, but that isn't tested here */
785 ret = VirtualQuery(ptr2, &info, sizeof(info));
786 ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
787 ok(info.BaseAddress == ptr2,
788 "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
789 ok(info.AllocationBase == ptr2,
790 "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
791 ok(info.AllocationProtect == PAGE_READWRITE,
792 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
793 ok(info.RegionSize == 0x10000,
794 "RegionSize should have been 0x10000 but was 0x%lx\n", info.RegionSize);
795 ok(info.State == MEM_COMMIT,
796 "State should have been MEM_COMMIT instead of 0x%x\n", info.State);
797 ok(info.Protect == PAGE_READWRITE,
798 "Protect should have been PAGE_READWRITE instead of 0x%x\n", info.Protect);
799 ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
800
801 addr = VirtualAlloc( ptr, MAPPING_SIZE, MEM_RESET, PAGE_READONLY );
802 ok( addr == ptr, "VirtualAlloc failed with error %u\n", GetLastError() );
803
804 ret = VirtualFree( ptr, 0x10000, MEM_DECOMMIT );
805 ok( !ret, "VirtualFree succeeded\n" );
806 ok( GetLastError() == ERROR_INVALID_PARAMETER, "VirtualFree failed with %u\n", GetLastError() );
807
808 ret = UnmapViewOfFile(ptr2);
809 ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
810 ret = UnmapViewOfFile(ptr);
811 ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
812 CloseHandle(mapping);
813
814 addr = VirtualAlloc(NULL, 0x10000, MEM_COMMIT, PAGE_READONLY );
815 ok( addr != NULL, "VirtualAlloc failed with error %u\n", GetLastError() );
816
817 SetLastError(0xdeadbeef);
818 ok( !UnmapViewOfFile(addr), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
819 ok( GetLastError() == ERROR_INVALID_ADDRESS,
820 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
821 SetLastError(0xdeadbeef);
822 ok( !UnmapViewOfFile((char *)addr + 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
823 ok( GetLastError() == ERROR_INVALID_ADDRESS,
824 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
825 SetLastError(0xdeadbeef);
826 ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
827 ok( GetLastError() == ERROR_INVALID_ADDRESS,
828 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
829
830 ok( VirtualFree(addr, 0, MEM_RELEASE), "VirtualFree failed\n" );
831
832 /* close named mapping handle without unmapping */
833 name = "Foo";
834 SetLastError(0xdeadbeef);
835 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
836 ok( mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
837 SetLastError(0xdeadbeef);
838 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
839 ok( ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError() );
840 SetLastError(0xdeadbeef);
841 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
842 ok( map2 != 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
843 SetLastError(0xdeadbeef);
844 ret = CloseHandle(map2);
845 ok(ret, "CloseHandle error %d\n", GetLastError());
846 SetLastError(0xdeadbeef);
847 ret = CloseHandle(mapping);
848 ok(ret, "CloseHandle error %d\n", GetLastError());
849
850 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
851 ok( !ret, "memory is not accessible\n" );
852
853 ret = VirtualQuery(ptr, &info, sizeof(info));
854 ok(ret, "VirtualQuery error %d\n", GetLastError());
855 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
856 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
857 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
858 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
859 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
860 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
861 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
862
863 SetLastError(0xdeadbeef);
864 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
865 todo_wine
866 ok( map2 == 0, "OpenFileMappingA succeeded\n" );
867 todo_wine
868 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %d\n", GetLastError() );
869 if (map2) CloseHandle(map2); /* FIXME: remove once Wine is fixed */
870 SetLastError(0xdeadbeef);
871 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
872 ok( mapping != 0, "CreateFileMappingA failed\n" );
873 todo_wine
874 ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %d\n", GetLastError() );
875 SetLastError(0xdeadbeef);
876 ret = CloseHandle(mapping);
877 ok(ret, "CloseHandle error %d\n", GetLastError());
878
879 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
880 ok( !ret, "memory is not 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.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
886 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
887 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
888 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
889 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
890 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
891
892 SetLastError(0xdeadbeef);
893 ret = UnmapViewOfFile(ptr);
894 ok( ret, "UnmapViewOfFile failed with error %d\n", GetLastError() );
895
896 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
897 ok( ret, "memory is accessible\n" );
898
899 ret = VirtualQuery(ptr, &info, sizeof(info));
900 ok(ret, "VirtualQuery error %d\n", GetLastError());
901 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
902 ok(info.Protect == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", info.Protect);
903 ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase);
904 ok(info.AllocationProtect == 0, "%#x != 0\n", info.AllocationProtect);
905 ok(info.State == MEM_FREE, "%#x != MEM_FREE\n", info.State);
906 ok(info.Type == 0, "%#x != 0\n", info.Type);
907
908 SetLastError(0xdeadbeef);
909 file = CreateFileA(testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
910 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
911 SetFilePointer(file, 4096, NULL, FILE_BEGIN);
912 SetEndOfFile(file);
913
914 SetLastError(0xdeadbeef);
915 mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
916 ok( mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
917 SetLastError(0xdeadbeef);
918 ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
919 ok( ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError() );
920 SetLastError(0xdeadbeef);
921 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
922 ok( map2 != 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
923 SetLastError(0xdeadbeef);
924 ret = CloseHandle(map2);
925 ok(ret, "CloseHandle error %d\n", GetLastError());
926 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
927 sizeof(section_info), &info_size );
928 ok( !status, "NtQuerySection failed err %x\n", status );
929 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
930 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
931 section_info.Attributes );
932 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
933 ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %x%08x\n",
934 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
935 SetLastError(0xdeadbeef);
936 ret = CloseHandle(mapping);
937 ok(ret, "CloseHandle error %d\n", GetLastError());
938
939 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
940 ok( !ret, "memory is not accessible\n" );
941
942 ret = VirtualQuery(ptr, &info, sizeof(info));
943 ok(ret, "VirtualQuery error %d\n", GetLastError());
944 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
945 ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
946 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
947 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
948 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
949 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
950 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
951
952 SetLastError(0xdeadbeef);
953 map2 = OpenFileMappingA(FILE_MAP_READ, FALSE, name);
954 todo_wine
955 ok( map2 == 0, "OpenFileMappingA succeeded\n" );
956 todo_wine
957 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %d\n", GetLastError() );
958 CloseHandle(map2);
959 SetLastError(0xdeadbeef);
960 mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, MAPPING_SIZE, name);
961 ok( mapping != 0, "CreateFileMappingA failed\n" );
962 todo_wine
963 ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %d\n", GetLastError() );
964 SetLastError(0xdeadbeef);
965 ret = CloseHandle(mapping);
966 ok(ret, "CloseHandle error %d\n", GetLastError());
967
968 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
969 ok( !ret, "memory is not 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.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
975 ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
976 ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
977 ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
978 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
979 ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
980
981 SetLastError(0xdeadbeef);
982 ret = UnmapViewOfFile(ptr);
983 ok( ret, "UnmapViewOfFile failed with error %d\n", GetLastError() );
984
985 ret = IsBadReadPtr(ptr, MAPPING_SIZE);
986 ok( ret, "memory is accessible\n" );
987
988 ret = VirtualQuery(ptr, &info, sizeof(info));
989 ok(ret, "VirtualQuery error %d\n", GetLastError());
990 ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
991 ok(info.Protect == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", info.Protect);
992 ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase);
993 ok(info.AllocationProtect == 0, "%#x != 0\n", info.AllocationProtect);
994 ok(info.State == MEM_FREE, "%#x != MEM_FREE\n", info.State);
995 ok(info.Type == 0, "%#x != 0\n", info.Type);
996
997 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 12288, NULL );
998 ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
999
1000 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
1001 ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
1002
1003 ret = UnmapViewOfFile( (char *)ptr + 100 );
1004 ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
1005
1006 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
1007 ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
1008
1009 ret = UnmapViewOfFile( (char *)ptr + 4096 );
1010 ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
1011
1012 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
1013 ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
1014
1015 ret = UnmapViewOfFile( (char *)ptr + 4096 + 100 );
1016 ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
1017
1018 CloseHandle(mapping);
1019
1020 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 36, NULL );
1021 ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
1022 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
1023 sizeof(section_info), &info_size );
1024 ok( !status, "NtQuerySection failed err %x\n", status );
1025 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
1026 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1027 section_info.Attributes );
1028 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1029 ok( section_info.Size.QuadPart == 36, "NtQuerySection wrong size %x%08x\n",
1030 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1031 CloseHandle(mapping);
1032
1033 SetFilePointer(file, 0x3456, NULL, FILE_BEGIN);
1034 SetEndOfFile(file);
1035 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 0, NULL );
1036 ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
1037 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
1038 sizeof(section_info), &info_size );
1039 ok( !status, "NtQuerySection failed err %x\n", status );
1040 ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
1041 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1042 section_info.Attributes );
1043 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1044 ok( section_info.Size.QuadPart == 0x3456, "NtQuerySection wrong size %x%08x\n",
1045 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1046 CloseHandle(mapping);
1047
1048 map_size.QuadPart = 0x3457;
1049 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1050 &map_size, PAGE_READONLY, SEC_COMMIT, file );
1051 ok( status == STATUS_SECTION_TOO_BIG, "NtCreateSection failed %x\n", status );
1052 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1053 &map_size, PAGE_READONLY, SEC_IMAGE, file );
1054 ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection failed %x\n", status );
1055 if (!status) CloseHandle( mapping );
1056 map_size.QuadPart = 0x3452;
1057 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1058 &map_size, PAGE_READONLY, SEC_COMMIT, file );
1059 ok( !status, "NtCreateSection failed %x\n", status );
1060 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info), NULL );
1061 ok( !status, "NtQuerySection failed err %x\n", status );
1062 ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1063 section_info.Attributes );
1064 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1065 ok( section_info.Size.QuadPart == 0x3452, "NtQuerySection wrong size %x%08x\n",
1066 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1067 size = map_size.QuadPart;
1068 status = pNtMapViewOfSection( mapping, GetCurrentProcess(), &ptr, 0, 0, NULL,
1069 &size, ViewShare, 0, PAGE_READONLY );
1070 ok( !status, "NtMapViewOfSection failed err %x\n", status );
1071 pNtUnmapViewOfSection( GetCurrentProcess(), ptr );
1072 size = map_size.QuadPart + 1;
1073 status = pNtMapViewOfSection( mapping, GetCurrentProcess(), &ptr, 0, 0, NULL,
1074 &size, ViewShare, 0, PAGE_READONLY );
1075 ok( status == STATUS_INVALID_VIEW_SIZE, "NtMapViewOfSection failed err %x\n", status );
1076 CloseHandle(mapping);
1077
1078 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1079 &map_size, PAGE_READONLY, SEC_COMMIT, 0 );
1080 ok( !status, "NtCreateSection failed %x\n", status );
1081 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info), NULL );
1082 ok( !status, "NtQuerySection failed err %x\n", status );
1083 ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
1084 section_info.Attributes );
1085 ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1086 ok( section_info.Size.QuadPart == 0x4000, "NtQuerySection wrong size %x%08x\n",
1087 section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1088 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info)-1, NULL );
1089 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQuerySection failed err %x\n", status );
1090 status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info)+1, NULL );
1091 ok( !status, "NtQuerySection failed err %x\n", status );
1092 status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info)-1, NULL );
1093 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQuerySection failed err %x\n", status );
1094 status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info), NULL );
1095 ok( status == STATUS_SECTION_NOT_IMAGE, "NtQuerySection failed err %x\n", status );
1096 status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info)+1, NULL );
1097 ok( status == STATUS_SECTION_NOT_IMAGE, "NtQuerySection failed err %x\n", status );
1098 CloseHandle(mapping);
1099
1100 SetFilePointer(file, 0, NULL, FILE_BEGIN);
1101 SetEndOfFile(file);
1102 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1103 NULL, PAGE_READONLY, SEC_COMMIT, file );
1104 ok( status == STATUS_MAPPED_FILE_SIZE_ZERO, "NtCreateSection failed %x\n", status );
1105 status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1106 NULL, PAGE_READONLY, SEC_IMAGE, file );
1107 ok( status == STATUS_INVALID_FILE_FOR_SECTION, "NtCreateSection failed %x\n", status );
1108
1109 CloseHandle(file);
1110 DeleteFileA(testfile);
1111 }
1112
1113 static void test_NtMapViewOfSection(void)
1114 {
1115 HANDLE hProcess;
1116
1117 static const char testfile[] = "testfile.xxx";
1118 static const char data[] = "test data for NtMapViewOfSection";
1119 char buffer[sizeof(data)];
1120 HANDLE file, mapping;
1121 void *ptr, *ptr2;
1122 BOOL is_wow64, ret;
1123 DWORD status, written;
1124 SIZE_T size, result;
1125 LARGE_INTEGER offset;
1126
1127 if (!pNtMapViewOfSection || !pNtUnmapViewOfSection)
1128 {
1129 win_skip( "NtMapViewOfSection not available\n" );
1130 return;
1131 }
1132
1133 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1134 ok( file != INVALID_HANDLE_VALUE, "Failed to create test file\n" );
1135 WriteFile( file, data, sizeof(data), &written, NULL );
1136 SetFilePointer( file, 4096, NULL, FILE_BEGIN );
1137 SetEndOfFile( file );
1138
1139 /* read/write mapping */
1140
1141 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
1142 ok( mapping != 0, "CreateFileMapping failed\n" );
1143
1144 hProcess = create_target_process("sleep");
1145 ok(hProcess != NULL, "Can't start process\n");
1146
1147 ptr = NULL;
1148 size = 0;
1149 offset.QuadPart = 0;
1150 status = pNtMapViewOfSection( mapping, hProcess, &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1151 ok( !status, "NtMapViewOfSection failed status %x\n", status );
1152 ok( !((ULONG_PTR)ptr & 0xffff), "returned memory %p is not aligned to 64k\n", ptr );
1153
1154 ret = ReadProcessMemory( hProcess, ptr, buffer, sizeof(buffer), &result );
1155 ok( ret, "ReadProcessMemory failed\n" );
1156 ok( result == sizeof(buffer), "ReadProcessMemory didn't read all data (%lx)\n", result );
1157 ok( !memcmp( buffer, data, sizeof(buffer) ), "Wrong data read\n" );
1158
1159 /* for some unknown reason NtMapViewOfSection fails with STATUS_NO_MEMORY when zero_bits != 0 ? */
1160 ptr2 = NULL;
1161 size = 0;
1162 offset.QuadPart = 0;
1163 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 12, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1164 todo_wine
1165 ok( status == STATUS_NO_MEMORY, "NtMapViewOfSection returned %x\n", status );
1166 if (status == STATUS_SUCCESS)
1167 {
1168 status = pNtUnmapViewOfSection( hProcess, ptr2 );
1169 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1170 }
1171
1172 ptr2 = NULL;
1173 size = 0;
1174 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1175 todo_wine
1176 ok( status == STATUS_NO_MEMORY, "NtMapViewOfSection returned %x\n", status );
1177 if (status == STATUS_SUCCESS)
1178 {
1179 status = pNtUnmapViewOfSection( hProcess, ptr2 );
1180 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1181 }
1182
1183 /* 22 zero bits isn't acceptable */
1184 ptr2 = NULL;
1185 size = 0;
1186 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 22, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1187 ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1188 if (status == STATUS_SUCCESS)
1189 {
1190 status = pNtUnmapViewOfSection( hProcess, ptr2 );
1191 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1192 }
1193
1194 /* mapping at the same page conflicts */
1195 ptr2 = ptr;
1196 size = 0;
1197 offset.QuadPart = 0;
1198 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1199 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
1200
1201 /* offset has to be aligned */
1202 ptr2 = ptr;
1203 size = 0;
1204 offset.QuadPart = 1;
1205 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1206 ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
1207
1208 /* ptr has to be aligned */
1209 ptr2 = (char *)ptr + 42;
1210 size = 0;
1211 offset.QuadPart = 0;
1212 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1213 ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
1214
1215 /* still not 64k aligned */
1216 ptr2 = (char *)ptr + 0x1000;
1217 size = 0;
1218 offset.QuadPart = 0;
1219 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1220 ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
1221
1222 /* zero_bits != 0 is not allowed when an address is set */
1223 ptr2 = (char *)ptr + 0x1000;
1224 size = 0;
1225 offset.QuadPart = 0;
1226 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 12, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1227 ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1228
1229 ptr2 = (char *)ptr + 0x1000;
1230 size = 0;
1231 offset.QuadPart = 0;
1232 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1233 ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1234
1235 ptr2 = (char *)ptr + 0x1001;
1236 size = 0;
1237 offset.QuadPart = 0;
1238 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1239 ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1240
1241 ptr2 = (char *)ptr + 0x1000;
1242 size = 0;
1243 offset.QuadPart = 1;
1244 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1245 ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1246
1247 if (sizeof(void *) == sizeof(int) && (!pIsWow64Process ||
1248 !pIsWow64Process( GetCurrentProcess(), &is_wow64 ) || !is_wow64))
1249 {
1250 /* new memory region conflicts with previous mapping */
1251 ptr2 = ptr;
1252 size = 0;
1253 offset.QuadPart = 0;
1254 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1255 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1256 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
1257
1258 ptr2 = (char *)ptr + 42;
1259 size = 0;
1260 offset.QuadPart = 0;
1261 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1262 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1263 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
1264
1265 /* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
1266 ptr2 = (char *)ptr + 0x1000;
1267 size = 0;
1268 offset.QuadPart = 0;
1269 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1270 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1271 ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
1272 ok( (char *)ptr2 == (char *)ptr + 0x1000,
1273 "expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2 );
1274 status = pNtUnmapViewOfSection( hProcess, ptr2 );
1275 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1276
1277 /* the address is rounded down if not on a page boundary */
1278 ptr2 = (char *)ptr + 0x1001;
1279 size = 0;
1280 offset.QuadPart = 0;
1281 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1282 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1283 ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
1284 ok( (char *)ptr2 == (char *)ptr + 0x1000,
1285 "expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2 );
1286 status = pNtUnmapViewOfSection( hProcess, ptr2 );
1287 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1288
1289 ptr2 = (char *)ptr + 0x2000;
1290 size = 0;
1291 offset.QuadPart = 0;
1292 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1293 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1294 ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
1295 ok( (char *)ptr2 == (char *)ptr + 0x2000,
1296 "expected address %p, got %p\n", (char *)ptr + 0x2000, ptr2 );
1297 status = pNtUnmapViewOfSection( hProcess, ptr2 );
1298 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1299 }
1300 else
1301 {
1302 ptr2 = (char *)ptr + 0x1000;
1303 size = 0;
1304 offset.QuadPart = 0;
1305 status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1306 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
1307 todo_wine
1308 ok( status == STATUS_INVALID_PARAMETER_9, "NtMapViewOfSection returned %x\n", status );
1309 }
1310
1311 status = pNtUnmapViewOfSection( hProcess, ptr );
1312 ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1313
1314 CloseHandle( mapping );
1315 CloseHandle( file );
1316 DeleteFileA( testfile );
1317
1318 TerminateProcess(hProcess, 0);
1319 CloseHandle(hProcess);
1320 }
1321
1322 static void test_NtAreMappedFilesTheSame(void)
1323 {
1324 static const char testfile[] = "testfile.xxx";
1325 HANDLE file, file2, mapping, map2;
1326 void *ptr, *ptr2;
1327 NTSTATUS status;
1328 char path[MAX_PATH];
1329
1330 if (!pNtAreMappedFilesTheSame)
1331 {
1332 win_skip( "NtAreMappedFilesTheSame not available\n" );
1333 return;
1334 }
1335
1336 file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
1337 NULL, CREATE_ALWAYS, 0, 0 );
1338 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1339 SetFilePointer( file, 4096, NULL, FILE_BEGIN );
1340 SetEndOfFile( file );
1341
1342 mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
1343 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1344
1345 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1346 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1347
1348 file2 = CreateFileA( testfile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1349 NULL, OPEN_EXISTING, 0, 0 );
1350 ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1351
1352 map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY, 0, 4096, NULL );
1353 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1354 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
1355 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1356 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1357 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1358 UnmapViewOfFile( ptr2 );
1359
1360 ptr2 = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1361 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1362 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1363 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1364 UnmapViewOfFile( ptr2 );
1365 CloseHandle( map2 );
1366
1367 map2 = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
1368 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1369 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
1370 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1371 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1372 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1373 UnmapViewOfFile( ptr2 );
1374 CloseHandle( map2 );
1375 CloseHandle( file2 );
1376
1377 status = pNtAreMappedFilesTheSame( ptr, ptr );
1378 ok( status == STATUS_SUCCESS || broken(status == STATUS_NOT_SAME_DEVICE),
1379 "NtAreMappedFilesTheSame returned %x\n", status );
1380
1381 status = pNtAreMappedFilesTheSame( ptr, (char *)ptr + 30 );
1382 ok( status == STATUS_SUCCESS || broken(status == STATUS_NOT_SAME_DEVICE),
1383 "NtAreMappedFilesTheSame returned %x\n", status );
1384
1385 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1386 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1387
1388 status = pNtAreMappedFilesTheSame( ptr, (void *)0xdeadbeef );
1389 ok( status == STATUS_CONFLICTING_ADDRESSES || status == STATUS_INVALID_ADDRESS,
1390 "NtAreMappedFilesTheSame returned %x\n", status );
1391
1392 status = pNtAreMappedFilesTheSame( ptr, NULL );
1393 ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
1394
1395 status = pNtAreMappedFilesTheSame( ptr, (void *)GetProcessHeap() );
1396 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
1397
1398 status = pNtAreMappedFilesTheSame( NULL, NULL );
1399 ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
1400
1401 ptr2 = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE );
1402 ok( ptr2 != NULL, "VirtualAlloc error %u\n", GetLastError() );
1403 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1404 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
1405 VirtualFree( ptr2, 0, MEM_RELEASE );
1406
1407 UnmapViewOfFile( ptr );
1408 CloseHandle( mapping );
1409 CloseHandle( file );
1410
1411 status = pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
1412 GetModuleHandleA("kernel32.dll") );
1413 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1414 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1415 GetModuleHandleA("kernel32.dll") );
1416 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1417 status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1418 (char *)GetModuleHandleA("kernel32.dll") + 4096 );
1419 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1420
1421 GetSystemDirectoryA( path, MAX_PATH );
1422 strcat( path, "\\kernel32.dll" );
1423 file = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
1424 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1425
1426 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
1427 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1428 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1429 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1430 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1431 ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1432 UnmapViewOfFile( ptr );
1433 CloseHandle( mapping );
1434
1435 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
1436 ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1437 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
1438 ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1439 status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1440 todo_wine
1441 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1442
1443 file2 = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
1444 ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1445 map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
1446 ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1447 ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 0 );
1448 ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1449 status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1450 ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1451 UnmapViewOfFile( ptr2 );
1452 CloseHandle( map2 );
1453 CloseHandle( file2 );
1454
1455 UnmapViewOfFile( ptr );
1456 CloseHandle( mapping );
1457
1458 CloseHandle( file );
1459 DeleteFileA( testfile );
1460 }
1461
1462 static void test_CreateFileMapping(void)
1463 {
1464 HANDLE handle, handle2;
1465
1466 /* test case sensitivity */
1467
1468 SetLastError(0xdeadbeef);
1469 handle = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1470 "Wine Test Mapping");
1471 ok( handle != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
1472 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1473
1474 SetLastError(0xdeadbeef);
1475 handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1476 "Wine Test Mapping");
1477 ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
1478 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
1479 CloseHandle( handle2 );
1480
1481 SetLastError(0xdeadbeef);
1482 handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1483 "WINE TEST MAPPING");
1484 ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
1485 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1486 CloseHandle( handle2 );
1487
1488 SetLastError(0xdeadbeef);
1489 handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "Wine Test Mapping");
1490 ok( handle2 != NULL, "OpenFileMapping failed with error %d\n", GetLastError());
1491 CloseHandle( handle2 );
1492
1493 SetLastError(0xdeadbeef);
1494 handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "WINE TEST MAPPING");
1495 ok( !handle2, "OpenFileMapping succeeded\n");
1496 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
1497
1498 CloseHandle( handle );
1499 }
1500
1501 static void test_IsBadReadPtr(void)
1502 {
1503 BOOL ret;
1504 void *ptr = (void *)0xdeadbeef;
1505 char stackvar;
1506
1507 ret = IsBadReadPtr(NULL, 0);
1508 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1509
1510 ret = IsBadReadPtr(NULL, 1);
1511 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1512
1513 ret = IsBadReadPtr(ptr, 0);
1514 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1515
1516 ret = IsBadReadPtr(ptr, 1);
1517 ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1518
1519 ret = IsBadReadPtr(&stackvar, 0);
1520 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1521
1522 ret = IsBadReadPtr(&stackvar, sizeof(char));
1523 ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1524 }
1525
1526 static void test_IsBadWritePtr(void)
1527 {
1528 BOOL ret;
1529 void *ptr = (void *)0xdeadbeef;
1530 char stackval;
1531
1532 ret = IsBadWritePtr(NULL, 0);
1533 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1534
1535 ret = IsBadWritePtr(NULL, 1);
1536 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1537
1538 ret = IsBadWritePtr(ptr, 0);
1539 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1540
1541 ret = IsBadWritePtr(ptr, 1);
1542 ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1543
1544 ret = IsBadWritePtr(&stackval, 0);
1545 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1546
1547 ret = IsBadWritePtr(&stackval, sizeof(char));
1548 ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1549 }
1550
1551 static void test_IsBadCodePtr(void)
1552 {
1553 BOOL ret;
1554 void *ptr = (void *)0xdeadbeef;
1555 char stackval;
1556
1557 ret = IsBadCodePtr(NULL);
1558 ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1559
1560 ret = IsBadCodePtr(ptr);
1561 ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1562
1563 ret = IsBadCodePtr((void *)&stackval);
1564 ok(ret == FALSE, "Expected IsBadCodePtr to return FALSE, got %d\n", ret);
1565 }
1566
1567 static void test_write_watch(void)
1568 {
1569 static const char pipename[] = "\\\\.\\pipe\\test_write_watch_pipe";
1570 static const char testdata[] = "Hello World";
1571 DWORD ret, size, old_prot, num_bytes;
1572 MEMORY_BASIC_INFORMATION info;
1573 HANDLE readpipe, writepipe;
1574 OVERLAPPED overlapped;
1575 void *results[64];
1576 ULONG_PTR count;
1577 ULONG pagesize;
1578 BOOL success;
1579 char *base;
1580
1581 if (!pGetWriteWatch || !pResetWriteWatch)
1582 {
1583 win_skip( "GetWriteWatch not supported\n" );
1584 return;
1585 }
1586
1587 size = 0x10000;
1588 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE );
1589 if (!base &&
1590 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
1591 {
1592 win_skip( "MEM_WRITE_WATCH not supported\n" );
1593 return;
1594 }
1595 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1596 ret = VirtualQuery( base, &info, sizeof(info) );
1597 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1598 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1599 ok( info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect %x\n", info.AllocationProtect );
1600 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1601 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1602 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1603 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
1604
1605 count = 64;
1606 SetLastError( 0xdeadbeef );
1607 ret = pGetWriteWatch( 0, NULL, size, results, &count, &pagesize );
1608 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1609 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
1610 broken( GetLastError() == 0xdeadbeef ), /* win98 */
1611 "wrong error %u\n", GetLastError() );
1612
1613 SetLastError( 0xdeadbeef );
1614 ret = pGetWriteWatch( 0, GetModuleHandleW(NULL), size, results, &count, &pagesize );
1615 if (ret)
1616 {
1617 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1618 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1619 }
1620 else /* win98 */
1621 {
1622 ok( count == 0, "wrong count %lu\n", count );
1623 }
1624
1625 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1626 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1627 ok( count == 0, "wrong count %lu\n", count );
1628
1629 base[pagesize + 1] = 0x44;
1630
1631 count = 64;
1632 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1633 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1634 ok( count == 1, "wrong count %lu\n", count );
1635 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1636
1637 count = 64;
1638 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1639 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1640 ok( count == 1, "wrong count %lu\n", count );
1641 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1642
1643 count = 64;
1644 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1645 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1646 ok( count == 0, "wrong count %lu\n", count );
1647
1648 base[2*pagesize + 3] = 0x11;
1649 base[4*pagesize + 8] = 0x11;
1650
1651 count = 64;
1652 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1653 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1654 ok( count == 2, "wrong count %lu\n", count );
1655 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1656 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1657
1658 count = 64;
1659 ret = pGetWriteWatch( 0, base + 3*pagesize, 2*pagesize, results, &count, &pagesize );
1660 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1661 ok( count == 1, "wrong count %lu\n", count );
1662 ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1663
1664 ret = pResetWriteWatch( base, 3*pagesize );
1665 ok( !ret, "pResetWriteWatch failed %u\n", GetLastError() );
1666
1667 count = 64;
1668 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1669 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1670 ok( count == 1, "wrong count %lu\n", count );
1671 ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1672
1673 *(DWORD *)(base + 2*pagesize - 2) = 0xdeadbeef;
1674
1675 count = 64;
1676 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1677 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1678 ok( count == 3, "wrong count %lu\n", count );
1679 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1680 ok( results[1] == base + 2*pagesize, "wrong result %p\n", results[1] );
1681 ok( results[2] == base + 4*pagesize, "wrong result %p\n", results[2] );
1682
1683 count = 1;
1684 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1685 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1686 ok( count == 1, "wrong count %lu\n", count );
1687 ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1688
1689 count = 64;
1690 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1691 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1692 ok( count == 2, "wrong count %lu\n", count );
1693 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1694 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1695
1696 /* changing protections doesn't affect watches */
1697
1698 ret = VirtualProtect( base, 3*pagesize, PAGE_READONLY, &old_prot );
1699 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1700 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1701
1702 ret = VirtualQuery( base, &info, sizeof(info) );
1703 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1704 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1705 ok( info.RegionSize == 3*pagesize, "wrong RegionSize 0x%lx\n", info.RegionSize );
1706 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1707 ok( info.Protect == PAGE_READONLY, "wrong Protect 0x%x\n", info.Protect );
1708
1709 ret = VirtualProtect( base, 3*pagesize, PAGE_READWRITE, &old_prot );
1710 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1711 ok( old_prot == PAGE_READONLY, "wrong old prot %x\n", old_prot );
1712
1713 count = 64;
1714 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1715 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1716 ok( count == 2, "wrong count %lu\n", count );
1717 ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1718 ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1719
1720 ret = VirtualQuery( base, &info, sizeof(info) );
1721 ok(ret, "VirtualQuery failed %u\n", GetLastError());
1722 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1723 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1724 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1725 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1726
1727 /* ReadFile should trigger write watches */
1728
1729 memset( &overlapped, 0, sizeof(overlapped) );
1730 overlapped.hEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
1731
1732 readpipe = CreateNamedPipeA( pipename, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_INBOUND,
1733 PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024,
1734 NMPWAIT_USE_DEFAULT_WAIT, NULL );
1735 ok( readpipe != INVALID_HANDLE_VALUE, "CreateNamedPipeA failed %u\n", GetLastError() );
1736
1737 success = ConnectNamedPipe( readpipe, &overlapped );
1738 ok( !success, "ConnectNamedPipe unexpectedly succeeded\n" );
1739 ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1740
1741 writepipe = CreateFileA( pipename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
1742 ok( writepipe != INVALID_HANDLE_VALUE, "CreateFileA failed %u\n", GetLastError() );
1743
1744 ret = WaitForSingleObject( overlapped.hEvent, 1000 );
1745 ok( ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret );
1746
1747 memset( base, 0, size );
1748
1749 count = 64;
1750 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1751 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1752 ok( count == 16, "wrong count %lu\n", count );
1753
1754 success = ReadFile( readpipe, base, size, NULL, &overlapped );
1755 ok( !success, "ReadFile unexpectedly succeeded\n" );
1756 ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1757
1758 count = 64;
1759 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1760 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1761 ok( count == 16, "wrong count %lu\n", count );
1762
1763 num_bytes = 0;
1764 success = WriteFile( writepipe, testdata, sizeof(testdata), &num_bytes, NULL );
1765 ok( success, "WriteFile failed %u\n", GetLastError() );
1766 ok( num_bytes == sizeof(testdata), "wrong number of bytes written\n" );
1767
1768 num_bytes = 0;
1769 success = GetOverlappedResult( readpipe, &overlapped, &num_bytes, TRUE );
1770 ok( success, "GetOverlappedResult failed %u\n", GetLastError() );
1771 ok( num_bytes == sizeof(testdata), "wrong number of bytes read\n" );
1772 ok( !memcmp( base, testdata, sizeof(testdata)), "didn't receive expected data\n" );
1773
1774 count = 64;
1775 memset( results, 0, sizeof(results) );
1776 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1777 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1778 todo_wine ok( count == 1, "wrong count %lu\n", count );
1779 ok( results[0] == base, "wrong result %p\n", results[0] );
1780
1781 CloseHandle( readpipe );
1782 CloseHandle( writepipe );
1783 CloseHandle( overlapped.hEvent );
1784
1785 /* some invalid parameter tests */
1786
1787 SetLastError( 0xdeadbeef );
1788 count = 0;
1789 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1790 if (ret)
1791 {
1792 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1793 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1794
1795 SetLastError( 0xdeadbeef );
1796 ret = pGetWriteWatch( 0, base, size, results, NULL, &pagesize );
1797 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1798 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1799
1800 SetLastError( 0xdeadbeef );
1801 count = 64;
1802 ret = pGetWriteWatch( 0, base, size, results, &count, NULL );
1803 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1804 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1805
1806 SetLastError( 0xdeadbeef );
1807 count = 64;
1808 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1809 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1810 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1811
1812 SetLastError( 0xdeadbeef );
1813 count = 0;
1814 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1815 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1816 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1817
1818 SetLastError( 0xdeadbeef );
1819 count = 64;
1820 ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
1821 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1822 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1823
1824 SetLastError( 0xdeadbeef );
1825 count = 64;
1826 ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
1827 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1828 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1829
1830 SetLastError( 0xdeadbeef );
1831 count = 64;
1832 ret = pGetWriteWatch( 0, base, size * 2, results, &count, &pagesize );
1833 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1834 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1835
1836 SetLastError( 0xdeadbeef );
1837 count = 64;
1838 ret = pGetWriteWatch( 0, base + size - pagesize, pagesize + 1, results, &count, &pagesize );
1839 ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1840 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1841
1842 SetLastError( 0xdeadbeef );
1843 ret = pResetWriteWatch( base, 0 );
1844 ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
1845 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1846
1847 SetLastError( 0xdeadbeef );
1848 ret = pResetWriteWatch( GetModuleHandleW(NULL), size );
1849 ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
1850 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1851 }
1852 else /* win98 is completely different */
1853 {
1854 SetLastError( 0xdeadbeef );
1855 count = 64;
1856 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1857 ok( ret == ERROR_INVALID_PARAMETER, "GetWriteWatch succeeded %u\n", ret );
1858 ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
1859
1860 count = 0;
1861 ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1862 ok( !ret, "GetWriteWatch failed %u\n", ret );
1863
1864 count = 64;
1865 ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
1866 ok( !ret, "GetWriteWatch failed %u\n", ret );
1867
1868 count = 64;
1869 ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
1870 ok( !ret, "GetWriteWatch failed %u\n", ret );
1871
1872 ret = pResetWriteWatch( base, 0 );
1873 ok( !ret, "ResetWriteWatch failed %u\n", ret );
1874
1875 ret = pResetWriteWatch( GetModuleHandleW(NULL), size );
1876 ok( !ret, "ResetWriteWatch failed %u\n", ret );
1877 }
1878
1879 VirtualFree( base, 0, MEM_RELEASE );
1880
1881 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_READWRITE );
1882 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1883 VirtualFree( base, 0, MEM_RELEASE );
1884
1885 base = VirtualAlloc( 0, size, MEM_WRITE_WATCH, PAGE_READWRITE );
1886 ok( !base, "VirtualAlloc succeeded\n" );
1887 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1888
1889 /* initial protect doesn't matter */
1890
1891 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_NOACCESS );
1892 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1893 base = VirtualAlloc( base, size, MEM_COMMIT, PAGE_NOACCESS );
1894 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1895
1896 count = 64;
1897 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1898 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1899 ok( count == 0, "wrong count %lu\n", count );
1900
1901 ret = VirtualProtect( base, 6*pagesize, PAGE_READWRITE, &old_prot );
1902 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1903 ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
1904
1905 base[5*pagesize + 200] = 3;
1906
1907 ret = VirtualProtect( base, 6*pagesize, PAGE_NOACCESS, &old_prot );
1908 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1909 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1910
1911 count = 64;
1912 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1913 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1914 ok( count == 1, "wrong count %lu\n", count );
1915 ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
1916
1917 ret = VirtualFree( base, size, MEM_DECOMMIT );
1918 ok( ret, "VirtualFree failed %u\n", GetLastError() );
1919
1920 count = 64;
1921 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1922 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1923 ok( count == 1 || broken(count == 0), /* win98 */
1924 "wrong count %lu\n", count );
1925 if (count) ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
1926
1927 VirtualFree( base, 0, MEM_RELEASE );
1928 }
1929
1930 #if defined(__i386__) || defined(__x86_64__)
1931
1932 static DWORD WINAPI stack_commit_func( void *arg )
1933 {
1934 volatile char *p = (char *)&p;
1935
1936 /* trigger all guard pages, to ensure that the pages are committed */
1937 while (p >= (char *)NtCurrentTeb()->DeallocationStack + 4 * 0x1000)
1938 {
1939 p[0] |= 0;
1940 p -= 0x1000;
1941 }
1942
1943 ok( arg == (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg );
1944 return 42;
1945 }
1946
1947 static void test_stack_commit(void)
1948 {
1949 #ifdef __i386__
1950 static const char code_call_on_stack[] = {
1951 0x55, /* pushl %ebp */
1952 0x56, /* pushl %esi */
1953 0x89, 0xe6, /* movl %esp,%esi */
1954 0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */
1955 0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */
1956 0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */
1957 0x83, 0xe0, 0xf0, /* andl $~15,%eax */
1958 0x83, 0xe8, 0x0c, /* subl $12,%eax */
1959 0x89, 0xc4, /* movl %eax,%esp */
1960 0x52, /* pushl %edx */
1961 0x31, 0xed, /* xorl %ebp,%ebp */
1962 0xff, 0xd1, /* call *%ecx */
1963 0x89, 0xf4, /* movl %esi,%esp */
1964 0x5e, /* popl %esi */
1965 0x5d, /* popl %ebp */
1966 0xc2, 0x0c, 0x00 }; /* ret $12 */
1967 #else
1968 static const char code_call_on_stack[] = {
1969 0x55, /* pushq %rbp */
1970 0x48, 0x89, 0xe5, /* movq %rsp,%rbp */
1971 /* %rcx - func, %rdx - arg, %r8 - stack */
1972 0x48, 0x87, 0xca, /* xchgq %rcx,%rdx */
1973 0x49, 0x83, 0xe0, 0xf0, /* andq $~15,%r8 */
1974 0x49, 0x83, 0xe8, 0x20, /* subq $0x20,%r8 */
1975 0x4c, 0x89, 0xc4, /* movq %r8,%rsp */
1976 0xff, 0xd2, /* callq *%rdx */
1977 0x48, 0x89, 0xec, /* movq %rbp,%rsp */
1978 0x5d, /* popq %rbp */
1979 0xc3 }; /* ret */
1980 #endif
1981 DWORD (WINAPI *call_on_stack)( DWORD (WINAPI *func)(void *), void *arg, void *stack );
1982 void *old_stack, *old_stack_base, *old_stack_limit;
1983 void *new_stack, *new_stack_base;
1984 DWORD result;
1985
1986 call_on_stack = VirtualAlloc( 0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE );
1987 ok( call_on_stack != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1988 memcpy( call_on_stack, code_call_on_stack, sizeof(code_call_on_stack) );
1989
1990 /* allocate a new stack, only the first guard page is committed */
1991 new_stack = VirtualAlloc( 0, 0x400000, MEM_RESERVE, PAGE_READWRITE );
1992 ok( new_stack != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1993 new_stack_base = (char *)new_stack + 0x400000;
1994 VirtualAlloc( (char *)new_stack_base - 0x1000, 0x1000, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
1995
1996 old_stack = NtCurrentTeb()->DeallocationStack;
1997 old_stack_base = NtCurrentTeb()->Tib.StackBase;
1998 old_stack_limit = NtCurrentTeb()->Tib.StackLimit;
1999
2000 NtCurrentTeb()->DeallocationStack = new_stack;
2001 NtCurrentTeb()->Tib.StackBase = new_stack_base;
2002 NtCurrentTeb()->Tib.StackLimit = new_stack_base;
2003
2004 result = call_on_stack( stack_commit_func, (void *)0xdeadbeef, new_stack_base );
2005
2006 NtCurrentTeb()->DeallocationStack = old_stack;
2007 NtCurrentTeb()->Tib.StackBase = old_stack_base;
2008 NtCurrentTeb()->Tib.StackLimit = old_stack_limit;
2009
2010 ok( result == 42, "expected 42, got %u\n", result );
2011
2012 VirtualFree( new_stack, 0, MEM_RELEASE );
2013 VirtualFree( call_on_stack, 0, MEM_RELEASE );
2014 }
2015
2016 #endif /* defined(__i386__) || defined(__x86_64__) */
2017 #ifdef __i386__
2018
2019 static LONG num_guard_page_calls;
2020
2021 static DWORD guard_page_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
2022 CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
2023 {
2024 trace( "exception: %08x flags:%x addr:%p\n",
2025 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
2026
2027 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
2028 ok( rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION, "ExceptionCode is %08x instead of %08x\n",
2029 rec->ExceptionCode, STATUS_GUARD_PAGE_VIOLATION );
2030
2031 InterlockedIncrement( &num_guard_page_calls );
2032 *(int *)rec->ExceptionInformation[1] += 0x100;
2033
2034 return ExceptionContinueExecution;
2035 }
2036
2037 static void test_guard_page(void)
2038 {
2039 EXCEPTION_REGISTRATION_RECORD frame;
2040 MEMORY_BASIC_INFORMATION info;
2041 DWORD ret, size, old_prot;
2042 int *value, old_value;
2043 void *results[64];
2044 ULONG_PTR count;
2045 ULONG pagesize;
2046 BOOL success;
2047 char *base;
2048
2049 size = 0x1000;
2050 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
2051 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2052 value = (int *)base;
2053
2054 /* verify info structure */
2055 ret = VirtualQuery( base, &info, sizeof(info) );
2056 ok( ret, "VirtualQuery failed %u\n", GetLastError());
2057 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
2058 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
2059 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
2060 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
2061 ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%x\n", info.Protect );
2062 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
2063
2064 /* put some initial value into the memory */
2065 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2066 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2067 ok( old_prot == (PAGE_READWRITE | PAGE_GUARD), "wrong old prot %x\n", old_prot );
2068
2069 *value = 1;
2070 *(value + 1) = 2;
2071
2072 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2073 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2074 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2075
2076 /* test behaviour of VirtualLock - first attempt should fail */
2077 SetLastError( 0xdeadbeef );
2078 success = VirtualLock( base, size );
2079 ok( !success, "VirtualLock unexpectedly succeeded\n" );
2080 todo_wine
2081 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %u\n", GetLastError() );
2082
2083 success = VirtualLock( base, size );
2084 todo_wine
2085 ok( success, "VirtualLock failed %u\n", GetLastError() );
2086 if (success)
2087 {
2088 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2089 success = VirtualUnlock( base, size );
2090 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2091 }
2092
2093 /* check info structure again, PAGE_GUARD should be removed now */
2094 ret = VirtualQuery( base, &info, sizeof(info) );
2095 ok( ret, "VirtualQuery failed %u\n", GetLastError());
2096 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
2097 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
2098 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
2099 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
2100 todo_wine
2101 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
2102 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
2103
2104 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2105 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2106 todo_wine
2107 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2108
2109 /* test directly accessing the memory - we need to setup an exception handler first */
2110 frame.Handler = guard_page_handler;
2111 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2112 NtCurrentTeb()->Tib.ExceptionList = &frame;
2113
2114 InterlockedExchange( &num_guard_page_calls, 0 );
2115 InterlockedExchange( &old_value, *value ); /* exception handler increments value by 0x100 */
2116 *value = 2;
2117 ok( old_value == 0x101, "memory block contains wrong value, expected 0x101, got 0x%x\n", old_value );
2118 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2119
2120 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2121
2122 /* check info structure again, PAGE_GUARD should be removed now */
2123 ret = VirtualQuery( base, &info, sizeof(info) );
2124 ok( ret, "VirtualQuery failed %u\n", GetLastError());
2125 ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
2126
2127 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2128 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2129 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2130
2131 /* test accessing second integer in memory */
2132 frame.Handler = guard_page_handler;
2133 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2134 NtCurrentTeb()->Tib.ExceptionList = &frame;
2135
2136 InterlockedExchange( &num_guard_page_calls, 0 );
2137 old_value = *(value + 1);
2138 ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value );
2139 ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value );
2140 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2141
2142 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2143
2144 success = VirtualLock( base, size );
2145 ok( success, "VirtualLock failed %u\n", GetLastError() );
2146 if (success)
2147 {
2148 ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value );
2149 success = VirtualUnlock( base, size );
2150 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2151 }
2152
2153 VirtualFree( base, 0, MEM_RELEASE );
2154
2155 /* combined guard page / write watch tests */
2156 if (!pGetWriteWatch || !pResetWriteWatch)
2157 {
2158 win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" );
2159 return;
2160 }
2161
2162 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE | PAGE_GUARD );
2163 if (!base && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
2164 {
2165 win_skip( "MEM_WRITE_WATCH not supported\n" );
2166 return;
2167 }
2168 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2169 value = (int *)base;
2170
2171 ret = VirtualQuery( base, &info, sizeof(info) );
2172 ok( ret, "VirtualQuery failed %u\n", GetLastError() );
2173 ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
2174 ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
2175 ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
2176 ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
2177 ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%x\n", info.Protect );
2178 ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
2179
2180 count = 64;
2181 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
2182 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2183 ok( count == 0, "wrong count %lu\n", count );
2184
2185 /* writing to a page should trigger should trigger guard page, even if write watch is set */
2186 frame.Handler = guard_page_handler;
2187 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2188 NtCurrentTeb()->Tib.ExceptionList = &frame;
2189
2190 InterlockedExchange( &num_guard_page_calls, 0 );
2191 *value = 1;
2192 *(value + 1) = 2;
2193 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2194
2195 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2196
2197 count = 64;
2198 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2199 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2200 ok( count == 1, "wrong count %lu\n", count );
2201 ok( results[0] == base, "wrong result %p\n", results[0] );
2202
2203 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2204 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2205
2206 /* write watch is triggered from inside of the guard page handler */
2207 frame.Handler = guard_page_handler;
2208 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2209 NtCurrentTeb()->Tib.ExceptionList = &frame;
2210
2211 InterlockedExchange( &num_guard_page_calls, 0 );
2212 old_value = *(value + 1); /* doesn't trigger write watch */
2213 ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value );
2214 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2215 ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2216
2217 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2218
2219 count = 64;
2220 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2221 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2222 ok( count == 1, "wrong count %lu\n", count );
2223 ok( results[0] == base, "wrong result %p\n", results[0] );
2224
2225 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2226 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2227
2228 /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */
2229 SetLastError( 0xdeadbeef );
2230 success = VirtualLock( base, size );
2231 ok( !success, "VirtualLock unexpectedly succeeded\n" );
2232 todo_wine
2233 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %u\n", GetLastError() );
2234
2235 count = 64;
2236 ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
2237 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2238 ok( count == 0, "wrong count %lu\n", count );
2239
2240 success = VirtualLock( base, size );
2241 todo_wine
2242 ok( success, "VirtualLock failed %u\n", GetLastError() );
2243 if (success)
2244 {
2245 ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2246 success = VirtualUnlock( base, size );
2247 ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2248 }
2249
2250 count = 64;
2251 results[0] = (void *)0xdeadbeef;
2252 ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2253 ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2254 todo_wine
2255 ok( count == 1 || broken(count == 0) /* Windows 8 */, "wrong count %lu\n", count );
2256 todo_wine
2257 ok( results[0] == base || broken(results[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results[0] );
2258
2259 VirtualFree( base, 0, MEM_RELEASE );
2260 }
2261
2262 static LONG num_execute_fault_calls;
2263
2264 static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
2265 CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
2266 {
2267 ULONG flags = MEM_EXECUTE_OPTION_ENABLE;
2268 DWORD err;
2269
2270 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2271 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
2272 rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] );
2273
2274 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
2275 ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION || rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION,
2276 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec->ExceptionCode );
2277
2278 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags), NULL );
2279
2280 if (rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
2281 {
2282
2283 err = IsProcessorFeaturePresent( PF_NX_ENABLED ) ? EXCEPTION_EXECUTE_FAULT : EXCEPTION_READ_FAULT;
2284 ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %d instead of %d\n",
2285 (DWORD)rec->ExceptionInformation[0], err );
2286
2287 InterlockedIncrement( &num_guard_page_calls );
2288 }
2289 else if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION)
2290 {
2291 DWORD old_prot;
2292 BOOL success;
2293
2294 err = (flags & MEM_EXECUTE_OPTION_DISABLE) ? EXCEPTION_EXECUTE_FAULT : EXCEPTION_READ_FAULT;
2295 ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %d instead of %d\n",
2296 (DWORD)rec->ExceptionInformation[0], err );
2297
2298 success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
2299 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2300 ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2301
2302 InterlockedIncrement( &num_execute_fault_calls );
2303 }
2304
2305 return ExceptionContinueExecution;
2306 }
2307
2308 static LONG CALLBACK execute_fault_vec_handler( EXCEPTION_POINTERS *ExceptionInfo )
2309 {
2310 PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
2311 DWORD old_prot;
2312 BOOL success;
2313
2314 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2315 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
2316 rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] );
2317
2318 ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
2319 ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION,
2320 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec->ExceptionCode );
2321
2322 if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION)
2323 InterlockedIncrement( &num_execute_fault_calls );
2324
2325 if (rec->ExceptionInformation[0] == EXCEPTION_READ_FAULT)
2326 return EXCEPTION_CONTINUE_SEARCH;
2327
2328 success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
2329 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2330 ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
2331
2332 return EXCEPTION_CONTINUE_EXECUTION;
2333 }
2334
2335 static inline DWORD send_message_excpt( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2336 {
2337 EXCEPTION_REGISTRATION_RECORD frame;
2338 DWORD ret;
2339
2340 frame.Handler = execute_fault_seh_handler;
2341 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2342 NtCurrentTeb()->Tib.ExceptionList = &frame;
2343
2344 InterlockedExchange( &num_guard_page_calls, 0 );
2345 InterlockedExchange( &num_execute_fault_calls, 0 );
2346 ret = SendMessageA( hWnd, uMsg, wParam, lParam );
2347
2348 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2349
2350 return ret;
2351 }
2352
2353 static inline DWORD call_proc_excpt( DWORD (CALLBACK *code)(void *), void *arg )
2354 {
2355 EXCEPTION_REGISTRATION_RECORD frame;
2356 DWORD ret;
2357
2358 frame.Handler = execute_fault_seh_handler;
2359 frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2360 NtCurrentTeb()->Tib.ExceptionList = &frame;
2361
2362 InterlockedExchange( &num_guard_page_calls, 0 );
2363 InterlockedExchange( &num_execute_fault_calls, 0 );
2364 ret = code( arg );
2365
2366 NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2367
2368 return ret;
2369 }
2370
2371 static LRESULT CALLBACK jmp_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2372 {
2373 if (uMsg == WM_USER)
2374 return 42;
2375
2376 return DefWindowProcA( hWnd, uMsg, wParam, lParam );
2377 }
2378
2379 static LRESULT CALLBACK atl_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2380 {
2381 DWORD arg = (DWORD)hWnd;
2382 if (uMsg == WM_USER)
2383 ok( arg == 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg );
2384 else
2385 ok( arg != 0x11223344, "arg is unexpectedly 0x11223344\n" );
2386 return 43;
2387 }
2388
2389 static DWORD CALLBACK atl5_test_func( void )
2390 {
2391 return 44;
2392 }
2393
2394 static void test_atl_thunk_emulation( ULONG dep_flags )
2395 {
2396 static const char code_jmp[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
2397 static const char code_atl1[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2398 static const char code_atl2[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2399 static const char code_atl3[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1};
2400 static const char code_atl4[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
2401 static const char code_atl5[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04};
2402 static const char cls_name[] = "atl_thunk_class";
2403 DWORD ret, size, old_prot;
2404 ULONG old_flags = MEM_EXECUTE_OPTION_ENABLE;
2405 BOOL success, restore_flags = FALSE;
2406 void *results[64];
2407 ULONG_PTR count;
2408 ULONG pagesize;
2409 WNDCLASSEXA wc;
2410 char *base;
2411 HWND hWnd;
2412
2413 trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
2414
2415 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags), NULL );
2416 if (old_flags != dep_flags)
2417 {
2418 ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &dep_flags, sizeof(dep_flags) );
2419 if (ret == STATUS_INVALID_INFO_CLASS) /* Windows 2000 */
2420 {
2421 win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
2422 return;
2423 }
2424 ok( !ret, "NtSetInformationProcess failed with status %08x\n", ret );
2425 restore_flags = TRUE;
2426 }
2427
2428 size = 0x1000;
2429 base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
2430 ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2431
2432 /* Check result of GetProcessDEPPolicy */
2433 if (!pGetProcessDEPPolicy)
2434 win_skip( "GetProcessDEPPolicy not supported\n" );
2435 else
2436 {
2437 BOOL (WINAPI *get_dep_policy)(HANDLE, LPDWORD, PBOOL) = (void *)base;
2438 BOOL policy_permanent = 0xdeadbeef;
2439 DWORD policy_flags = 0xdeadbeef;
2440
2441 /* GetProcessDEPPolicy crashes on Windows when a NULL pointer is passed.
2442 * Moreover this function has a bug on Windows 8, which has the effect that
2443 * policy_permanent is set to the content of the CL register instead of 0,
2444 * when the policy is not permanent. To detect that we use an assembler
2445 * wrapper to call the function. */
2446
2447 memcpy( base, code_atl2, sizeof(code_atl2) );
2448 *(DWORD *)(base + 6) = (DWORD_PTR)pGetProcessDEPPolicy - (DWORD_PTR)(base + 10);
2449
2450 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2451 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2452
2453 success = get_dep_policy( GetCurrentProcess(), &policy_flags, &policy_permanent );
2454 ok( success, "GetProcessDEPPolicy failed %u\n", GetLastError() );
2455
2456 ret = 0;
2457 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2458 ret |= PROCESS_DEP_ENABLE;
2459 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)
2460 ret |= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION;
2461
2462 ok( policy_flags == ret, "expected policy flags %d, got %d\n", ret, policy_flags );
2463 ok( !policy_permanent || broken(policy_permanent == 0x44),
2464 "expected policy permanent FALSE, got %d\n", policy_permanent );
2465 }
2466
2467 memcpy( base, code_jmp, sizeof(code_jmp) );
2468 *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2469
2470 /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
2471 * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
2472 * where it is active, so that application which depend on that still work properly.
2473 * We have no exception handler enabled yet, so give proper EXECUTE permissions to
2474 * prevent crashes while creating the window. */
2475
2476 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2477 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2478
2479 memset( &wc, 0, sizeof(wc) );
2480 wc.cbSize = sizeof(wc);
2481 wc.style = CS_VREDRAW | CS_HREDRAW;
2482 wc.hInstance = GetModuleHandleA( 0 );
2483 wc.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW );
2484 wc.hbrBackground = NULL;
2485 wc.lpszClassName = cls_name;
2486 wc.lpfnWndProc = (WNDPROC)base;
2487 success = RegisterClassExA(&wc) != 0;
2488 ok( success, "RegisterClassExA failed %u\n", GetLastError() );
2489
2490 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2491 ok( hWnd != 0, "CreateWindowExA failed %u\n", GetLastError() );
2492
2493 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2494 ok( ret == 42, "SendMessage returned unexpected result %d\n", ret );
2495
2496 /* At first try with an instruction which is not recognized as proper ATL thunk
2497 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2498 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2499
2500 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2501 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2502
2503 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2504 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2505 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2506 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && !IsProcessorFeaturePresent( PF_NX_ENABLED ))
2507 {
2508 trace( "DEP hardware support is not available\n" );
2509 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2510 dep_flags = MEM_EXECUTE_OPTION_ENABLE;
2511 }
2512 else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2513 {
2514 trace( "DEP hardware support is available\n" );
2515 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2516 }
2517 else
2518 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2519
2520 /* Now a bit more complicated, the page containing the code is protected with
2521 * PAGE_GUARD memory protection. */
2522
2523 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2524 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2525
2526 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2527 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2528 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2529 if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2530 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2531 else
2532 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2533
2534 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2535 ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2536 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2537 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2538
2539 /* Now test with a proper ATL thunk instruction. */
2540
2541 memcpy( base, code_atl1, sizeof(code_atl1) );
2542 *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
2543
2544 success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
2545 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2546
2547 ret = SendMessageA(hWnd, WM_USER, 0, 0);
2548 ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
2549
2550 /* Try executing with PAGE_READWRITE protection. */
2551
2552 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2553 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2554
2555 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2556 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2557 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2558 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2559 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2560 else
2561 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2562
2563 /* Now a bit more complicated, the page containing the code is protected with
2564 * PAGE_GUARD memory protection. */
2565
2566 success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
2567 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2568
2569 /* the same, but with PAGE_GUARD set */
2570 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2571 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2572 ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2573 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2574 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2575 else
2576 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2577
2578 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2579 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2580 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2581 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2582
2583 /* The following test shows that on Windows, even a vectored exception handler
2584 * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */
2585
2586 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && !(dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2587 {
2588 if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
2589 {
2590 PVOID vectored_handler;
2591
2592 success = VirtualProtect( base, size, PAGE_NOACCESS, &old_prot );
2593 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2594
2595 vectored_handler = pRtlAddVectoredExceptionHandler( TRUE, &execute_fault_vec_handler );
2596 ok( vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n" );
2597
2598 ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2599
2600 pRtlRemoveVectoredExceptionHandler( vectored_handler );
2601
2602 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2603 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2604 }
2605 else
2606 win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" );
2607 }
2608
2609 /* Test alternative ATL thunk instructions. */
2610
2611 memcpy( base, code_atl2, sizeof(code_atl2) );
2612 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 10);
2613
2614 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2615 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2616
2617 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2618 /* FIXME: we don't check the content of the register ECX yet */
2619 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2620 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2621 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2622 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2623 else
2624 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2625
2626 memcpy( base, code_atl3, sizeof(code_atl3) );
2627 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func;
2628
2629 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2630 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2631
2632 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2633 /* FIXME: we don't check the content of the registers ECX/EDX yet */
2634 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2635 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2636 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2637 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2638 else
2639 ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2640
2641 memcpy( base, code_atl4, sizeof(code_atl4) );
2642 *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func;
2643
2644 success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2645 ok( success, "VirtualProtect failed %u\n", GetLastError() );
2646
2647 ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2648 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2649 ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2650 ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2651 if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2652 ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );