ReactOS  0.4.13-dev-73-gcfe54aa
virtual.c
Go to the documentation of this file.
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 "precomp.h"
22 
23 #include <wine/exception.h>
24 
25 #define NUM_THREADS 4
26 #define MAPPING_SIZE 0x100000
27 
29 static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
30 static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
31 static UINT (WINAPI *pGetWriteWatch)(DWORD,LPVOID,SIZE_T,LPVOID*,ULONG_PTR*,ULONG*);
32 static UINT (WINAPI *pResetWriteWatch)(LPVOID,SIZE_T);
33 static NTSTATUS (WINAPI *pNtAreMappedFilesTheSame)(PVOID,PVOID);
34 static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *,
35  const LARGE_INTEGER *, ULONG, ULONG, HANDLE );
36 static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG);
37 static DWORD (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID);
38 static NTSTATUS (WINAPI *pNtQuerySection)(HANDLE, SECTION_INFORMATION_CLASS, void *, ULONG, ULONG *);
39 static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG, PVECTORED_EXCEPTION_HANDLER);
40 static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
41 static BOOL (WINAPI *pGetProcessDEPPolicy)(HANDLE, LPDWORD, PBOOL);
42 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
43 static NTSTATUS (WINAPI *pNtProtectVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG *);
44 static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG);
45 static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
46 
47 /* ############################### */
48 
49 static UINT_PTR page_mask = 0xfff;
50 #define ROUND_SIZE(addr,size) \
51  (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
52 
54 {
57 
59  {
60  ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);
61  if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;
62  }
63  return ret;
64 }
65 
66 static HANDLE create_target_process(const char *arg)
67 {
68  char **argv;
69  char cmdline[MAX_PATH];
71  BOOL ret;
72  STARTUPINFOA si = { 0 };
73  si.cb = sizeof(si);
74 
76  sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
77  ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
78  ok(ret, "error: %u\n", GetLastError());
79  ret = CloseHandle(pi.hThread);
80  ok(ret, "error %u\n", GetLastError());
81  return pi.hProcess;
82 }
83 
84 static void test_VirtualAllocEx(void)
85 {
86  const unsigned int alloc_size = 1<<15;
87  char *src, *dst;
88  SIZE_T bytes_written = 0, bytes_read = 0, i;
89  void *addr1, *addr2;
90  BOOL b;
91  DWORD old_prot;
94 
95  /* not exported in all windows-versions */
96  if ((!pVirtualAllocEx) || (!pVirtualFreeEx)) {
97  win_skip("Virtual{Alloc,Free}Ex not available\n");
98  return;
99  }
100 
101  hProcess = create_target_process("sleep");
102  ok(hProcess != NULL, "Can't start process\n");
103 
104  SetLastError(0xdeadbeef);
105  addr1 = pVirtualAllocEx(hProcess, NULL, alloc_size, MEM_COMMIT,
107  ok(addr1 != NULL, "VirtualAllocEx error %u\n", GetLastError());
108 
109  src = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE );
110  dst = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE );
111  for (i = 0; i < alloc_size; i++)
112  src[i] = i & 0xff;
113 
114  b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
115  ok(b && (bytes_written == alloc_size), "%lu bytes written\n",
116  bytes_written);
117  b = ReadProcessMemory(hProcess, addr1, dst, alloc_size, &bytes_read);
118  ok(b && (bytes_read == alloc_size), "%lu bytes read\n", bytes_read);
119  ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n");
120 
121  /* test invalid source buffers */
122 
123  b = VirtualProtect( src + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot );
124  ok( b, "VirtualProtect failed error %u\n", GetLastError() );
125  b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
126  ok( !b, "WriteProcessMemory succeeded\n" );
128  GetLastError() == ERROR_PARTIAL_COPY, /* vista */
129  "wrong error %u\n", GetLastError() );
130  ok( bytes_written == 0, "%lu bytes written\n", bytes_written );
131  b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
132  ok( !b, "ReadProcessMemory succeeded\n" );
133  ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
134  ok( bytes_read == 0, "%lu bytes written\n", bytes_read );
135 
136  b = VirtualProtect( src, 0x2000, PAGE_NOACCESS, &old_prot );
137  ok( b, "VirtualProtect failed error %u\n", GetLastError() );
138  b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
139  ok( !b, "WriteProcessMemory succeeded\n" );
141  GetLastError() == ERROR_PARTIAL_COPY, /* vista */
142  "wrong error %u\n", GetLastError() );
143  ok( bytes_written == 0, "%lu bytes written\n", bytes_written );
144  b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
145  ok( !b, "ReadProcessMemory succeeded\n" );
146  ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
147  ok( bytes_read == 0, "%lu bytes written\n", bytes_read );
148 
149  b = pVirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE);
150  ok(b != 0, "VirtualFreeEx, error %u\n", GetLastError());
151 
152  VirtualFree( src, 0, MEM_RELEASE );
153  VirtualFree( dst, 0, MEM_RELEASE );
154 
155  /*
156  * The following tests parallel those in test_VirtualAlloc()
157  */
158 
159  SetLastError(0xdeadbeef);
160  addr1 = pVirtualAllocEx(hProcess, 0, 0, MEM_RESERVE, PAGE_NOACCESS);
161  ok(addr1 == NULL, "VirtualAllocEx should fail on zero-sized allocation\n");
163  "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
164 
165  addr1 = pVirtualAllocEx(hProcess, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
166  ok(addr1 != NULL, "VirtualAllocEx failed\n");
167 
168  /* test a not committed memory */
169  memset(&info, 'q', sizeof(info));
170  ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info), "VirtualQueryEx failed\n");
171  ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
172  ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
173  ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
174  ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
175  ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
176  ok(info.Protect == 0, "%x != PAGE_NOACCESS\n", info.Protect);
177  ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
178 
179  SetLastError(0xdeadbeef);
180  ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
181  "VirtualProtectEx should fail on a not committed memory\n");
183  "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
184 
185  addr2 = pVirtualAllocEx(hProcess, addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS);
186  ok(addr1 == addr2, "VirtualAllocEx failed\n");
187 
188  /* test a committed memory */
189  ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info),
190  "VirtualQueryEx failed\n");
191  ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
192  ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
193  ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
194  ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
195  ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
196  /* this time NT reports PAGE_NOACCESS as well */
197  ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
198  ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
199 
200  /* this should fail, since not the whole range is committed yet */
201  SetLastError(0xdeadbeef);
202  ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
203  "VirtualProtectEx should fail on a not committed memory\n");
205  "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
206 
207  old_prot = 0;
208  ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtectEx failed\n");
209  ok(old_prot == PAGE_NOACCESS, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
210 
211  old_prot = 0;
212  ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtectEx failed\n");
213  ok(old_prot == PAGE_READONLY, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
214 
215  ok(!pVirtualFreeEx(hProcess, addr1, 0x10000, 0),
216  "VirtualFreeEx should fail with type 0\n");
218  "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
219 
220  ok(pVirtualFreeEx(hProcess, addr1, 0x10000, MEM_DECOMMIT), "VirtualFreeEx failed\n");
221 
222  /* if the type is MEM_RELEASE, size must be 0 */
223  ok(!pVirtualFreeEx(hProcess, addr1, 1, MEM_RELEASE),
224  "VirtualFreeEx should fail\n");
226  "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
227 
228  ok(pVirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE), "VirtualFreeEx failed\n");
229 
232 }
233 
234 static void test_VirtualAlloc(void)
235 {
236  void *addr1, *addr2;
237  DWORD old_prot;
240  SIZE_T size;
241 
242  SetLastError(0xdeadbeef);
243  addr1 = VirtualAlloc(0, 0, MEM_RESERVE, PAGE_NOACCESS);
244  ok(addr1 == NULL, "VirtualAlloc should fail on zero-sized allocation\n");
246  "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
247 
248  addr1 = VirtualAlloc(0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
249  ok(addr1 != NULL, "VirtualAlloc failed\n");
250 
251  /* test a not committed memory */
252  ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
253  "VirtualQuery failed\n");
254  ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
255  ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
256  ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
257  ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
258  ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
259  ok(info.Protect == 0, "%x != PAGE_NOACCESS\n", info.Protect);
260  ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
261 
262  SetLastError(0xdeadbeef);
263  ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
264  "VirtualProtect should fail on a not committed memory\n");
266  "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
267 
268  addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS);
269  ok(addr1 == addr2, "VirtualAlloc failed\n");
270 
271  /* test a committed memory */
272  ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
273  "VirtualQuery failed\n");
274  ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
275  ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
276  ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
277  ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
278  ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
279  /* this time NT reports PAGE_NOACCESS as well */
280  ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
281  ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
282 
283  /* this should fail, since not the whole range is committed yet */
284  SetLastError(0xdeadbeef);
285  ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
286  "VirtualProtect should fail on a not committed memory\n");
288  "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
289 
290  ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtect failed\n");
291  ok(old_prot == PAGE_NOACCESS,
292  "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
293 
294  ok(VirtualProtect(addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtect failed\n");
295  ok(old_prot == PAGE_READONLY,
296  "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
297 
298  ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
299  "VirtualQuery failed\n");
300  ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
301  ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
302  ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
303  memset( addr1, 0x55, 20 );
304  ok( *(DWORD *)addr1 == 0x55555555, "wrong data %x\n", *(DWORD *)addr1 );
305 
306  addr2 = VirtualAlloc( addr1, 0x1000, MEM_RESET, PAGE_NOACCESS );
307  ok( addr2 == addr1, "VirtualAlloc failed err %u\n", GetLastError() );
308  ok( *(DWORD *)addr1 == 0x55555555 || *(DWORD *)addr1 == 0, "wrong data %x\n", *(DWORD *)addr1 );
309  ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
310  "VirtualQuery failed\n");
311  ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
312  ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
313  ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
314 
315  addr2 = VirtualAlloc( (char *)addr1 + 0x1000, 0x1000, MEM_RESET, PAGE_NOACCESS );
316  ok( (char *)addr2 == (char *)addr1 + 0x1000, "VirtualAlloc failed\n" );
317 
318  ok(VirtualQuery(addr2, &info, sizeof(info)) == sizeof(info),
319  "VirtualQuery failed\n");
320  ok(info.RegionSize == 0xf000, "%lx != 0xf000\n", info.RegionSize);
321  ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
322  ok(info.Protect == 0, "%x != 0\n", info.Protect);
323 
324  addr2 = VirtualAlloc( (char *)addr1 + 0xf000, 0x2000, MEM_RESET, PAGE_NOACCESS );
325  ok( !addr2, "VirtualAlloc failed\n" );
326  ok( GetLastError() == ERROR_INVALID_ADDRESS, "wrong error %u\n", GetLastError() );
327 
328  /* invalid protection values */
329  SetLastError(0xdeadbeef);
330  addr2 = VirtualAlloc(NULL, 0x1000, MEM_RESERVE, 0);
331  ok(!addr2, "VirtualAlloc succeeded\n");
332  ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
333 
334  SetLastError(0xdeadbeef);
335  addr2 = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, 0);
336  ok(!addr2, "VirtualAlloc succeeded\n");
337  ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
338 
339  SetLastError(0xdeadbeef);
340  addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_READONLY | PAGE_EXECUTE);
341  ok(!addr2, "VirtualAlloc succeeded\n");
342  ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
343 
344  SetLastError(0xdeadbeef);
345  ok(!VirtualProtect(addr1, 0x1000, PAGE_READWRITE | PAGE_EXECUTE_WRITECOPY, &old_prot),
346  "VirtualProtect succeeded\n");
347  ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
348 
349  SetLastError(0xdeadbeef);
350  ok(!VirtualProtect(addr1, 0x1000, 0, &old_prot), "VirtualProtect succeeded\n");
351  ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
352 
353  SetLastError(0xdeadbeef);
354  ok(!VirtualFree(addr1, 0x10000, 0), "VirtualFree should fail with type 0\n");
356  "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
357 
358  SetLastError(0xdeadbeef);
359  ok(!VirtualFree(addr1, 0, MEM_FREE), "VirtualFree should fail with type MEM_FREE\n");
361  "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
362 
363  ok(VirtualFree(addr1, 0x10000, MEM_DECOMMIT), "VirtualFree failed\n");
364 
365  /* if the type is MEM_RELEASE, size must be 0 */
366  ok(!VirtualFree(addr1, 1, MEM_RELEASE), "VirtualFree should fail\n");
368  "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
369 
370  ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
371 
372  /* memory returned by VirtualAlloc should be aligned to 64k */
374  ok(addr1 != NULL, "VirtualAlloc failed\n");
375  ok(!((ULONG_PTR)addr1 & 0xffff), "returned memory %p is not aligned to 64k\n", addr1);
376  ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
377  addr2 = VirtualAlloc(addr1, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
378  ok(addr2 == addr1, "VirtualAlloc returned %p, expected %p\n", addr2, addr1);
379 
380  /* allocation conflicts because of 64k align */
381  size = 0x1000;
382  addr2 = (char *)addr1 + 0x1000;
383  status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 0, &size,
385  ok(status == STATUS_CONFLICTING_ADDRESSES, "NtAllocateVirtualMemory returned %08x\n", status);
386 
387  /* it should conflict, even when zero_bits is explicitly set */
388  size = 0x1000;
389  addr2 = (char *)addr1 + 0x1000;
390  status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 12, &size,
392  todo_wine
393  ok(status == STATUS_CONFLICTING_ADDRESSES, "NtAllocateVirtualMemory returned %08x\n", status);
394  if (status == STATUS_SUCCESS) ok(VirtualFree(addr2, 0, MEM_RELEASE), "VirtualFree failed\n");
395 
396  /* 21 zero bits is valid */
397  size = 0x1000;
398  addr2 = NULL;
399  status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 21, &size,
402  "NtAllocateVirtualMemory returned %08x\n", status);
403  if (status == STATUS_SUCCESS) ok(VirtualFree(addr2, 0, MEM_RELEASE), "VirtualFree failed\n");
404 
405  /* 22 zero bits is invalid */
406  size = 0x1000;
407  addr2 = NULL;
408  status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 22, &size,
410  ok(status == STATUS_INVALID_PARAMETER_3, "NtAllocateVirtualMemory returned %08x\n", status);
411  if (status == STATUS_SUCCESS) ok(VirtualFree(addr2, 0, MEM_RELEASE), "VirtualFree failed\n");
412 
413  /* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
414  SetLastError(0xdeadbeef);
416  ok(!addr2, "VirtualAlloc unexpectedly succeeded\n");
417  ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
418 
419  /* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
420  size = 0x1000;
421  addr2 = (char *)addr1 + 0x1000;
422  status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 0, &size, MEM_RESERVE |
424  todo_wine
425  ok(status == STATUS_INVALID_PARAMETER_5, "NtAllocateVirtualMemory returned %08x\n", status);
426 
427  ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
428 }
429 
430 static void test_MapViewOfFile(void)
431 {
432  static const char testfile[] = "testfile.xxx";
433  const char *name;
434  HANDLE file, mapping, map2;
435  void *ptr, *ptr2, *addr;
436  SECTION_BASIC_INFORMATION section_info;
437  SECTION_IMAGE_INFORMATION image_info;
439  BOOL ret;
440  SIZE_T size;
442  ULONG info_size;
443  LARGE_INTEGER map_size;
444 
445  SetLastError(0xdeadbeef);
446  file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
447  ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
448  SetFilePointer( file, 12288, NULL, FILE_BEGIN );
449  SetEndOfFile( file );
450 
451  /* read/write mapping */
452 
453  SetLastError(0xdeadbeef);
455  ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
456 
457  SetLastError(0xdeadbeef);
458  ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
459  ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
460  UnmapViewOfFile( ptr );
461 
462  SetLastError(0xdeadbeef);
463  ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
464  ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
465  UnmapViewOfFile( ptr );
466 
467  SetLastError(0xdeadbeef);
468  ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
469  ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
470  UnmapViewOfFile( ptr );
471 
472  SetLastError(0xdeadbeef);
473  ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
474  ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
475  UnmapViewOfFile( ptr );
476 
479  ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
480  ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
481  ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
482  UnmapViewOfFile( ptr );
483  CloseHandle( map2 );
484 
486  FILE_MAP_READ, FALSE, 0 );
487  ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
488  SetLastError(0xdeadbeef);
489  ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
490  ok( !ptr, "MapViewOfFile succeeded\n" );
491  ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
492  CloseHandle( map2 );
494  ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
495  SetLastError(0xdeadbeef);
496  ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
497  ok( !ptr, "MapViewOfFile succeeded\n" );
498  ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
499  CloseHandle( map2 );
501  FILE_MAP_READ, FALSE, 0 );
502  ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
503  ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
504  ok( ptr != NULL, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
505 
506  UnmapViewOfFile( ptr );
507  CloseHandle( map2 );
508  CloseHandle( mapping );
509 
510  /* read-only mapping */
511 
512  SetLastError(0xdeadbeef);
514  ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
515 
516  SetLastError(0xdeadbeef);
517  ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
518  ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
519  UnmapViewOfFile( ptr );
520 
521  SetLastError(0xdeadbeef);
522  ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
523  ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
524  UnmapViewOfFile( ptr );
525 
526  SetLastError(0xdeadbeef);
527  ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
528  ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
529  UnmapViewOfFile( ptr );
530 
531  SetLastError(0xdeadbeef);
532  ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
533  ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
535  GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
536  CloseHandle( mapping );
537 
538  /* copy-on-write mapping */
539 
540  SetLastError(0xdeadbeef);
542  ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
543 
544  SetLastError(0xdeadbeef);
545  ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
546  ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
547  UnmapViewOfFile( ptr );
548 
549  SetLastError(0xdeadbeef);
550  ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
551  ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
552  UnmapViewOfFile( ptr );
553 
554  SetLastError(0xdeadbeef);
555  ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
556  ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
557  UnmapViewOfFile( ptr );
558 
559  SetLastError(0xdeadbeef);
560  ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
561  ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
563  GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
564  CloseHandle( mapping );
565 
566  /* no access mapping */
567 
568  SetLastError(0xdeadbeef);
570  ok( !mapping, "CreateFileMappingA succeeded\n" );
571  ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
572  CloseHandle( file );
573 
574  /* now try read-only file */
575 
576  SetLastError(0xdeadbeef);
577  file = CreateFileA( testfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
578  ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
579 
580  SetLastError(0xdeadbeef);
582  ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
584  GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
585 
586  SetLastError(0xdeadbeef);
588  ok( mapping != 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
589  CloseHandle( mapping );
590 
591  SetLastError(0xdeadbeef);
593  ok( mapping != 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
594  CloseHandle( mapping );
595  CloseHandle( file );
596 
597  /* now try no access file */
598 
599  SetLastError(0xdeadbeef);
600  file = CreateFileA( testfile, 0, 0, NULL, OPEN_EXISTING, 0, 0 );
601  ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
602 
603  SetLastError(0xdeadbeef);
605  ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
607  GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
608 
609  SetLastError(0xdeadbeef);
611  ok( !mapping, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
613  GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
614 
615  SetLastError(0xdeadbeef);
617  ok( !mapping, "CreateFileMapping PAGE_READONLY succeeded\n" );
619  GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
620 
621  CloseHandle( file );
622  DeleteFileA( testfile );
623 
624  SetLastError(0xdeadbeef);
625  name = "Local\\Foo";
627  /* nt4 doesn't have Local\\ */
629  {
630  name = "Foo";
632  }
633  ok( file != 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
634 
635  SetLastError(0xdeadbeef);
637  ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
638  SetLastError(0xdeadbeef);
639  ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
640  ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
641  ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
642  SetLastError(0xdeadbeef);
643  ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
644  ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
645  SetLastError(0xdeadbeef);
646  size = VirtualQuery( ptr, &info, sizeof(info) );
647  ok( size == sizeof(info),
648  "VirtualQuery error %u\n", GetLastError() );
649  ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
650  ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
651  ok( info.AllocationProtect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.AllocationProtect );
652  ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
653  ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
654  ok( info.Protect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.Protect );
655  UnmapViewOfFile( ptr );
656  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
657  sizeof(section_info), &info_size );
658  ok( status == STATUS_ACCESS_DENIED, "NtQuerySection failed err %x\n", status );
659  CloseHandle( mapping );
661  ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
662  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
663  sizeof(section_info), &info_size );
664  ok( !status, "NtQuerySection failed err %x\n", status );
665  ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
666  ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
667  section_info.Attributes );
668  ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
669  ok( section_info.Size.QuadPart == info.RegionSize, "NtQuerySection wrong size %x%08x / %08lx\n",
670  section_info.Size.u.HighPart, section_info.Size.u.LowPart, info.RegionSize );
671  CloseHandle( mapping );
672 
673  SetLastError(0xdeadbeef);
675  ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
676  SetLastError(0xdeadbeef);
677  ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
678  ok( !ptr, "MapViewOfFile succeeded\n" );
679  ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
680  SetLastError(0xdeadbeef);
681  ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
682  ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
683  SetLastError(0xdeadbeef);
684  size = VirtualQuery( ptr, &info, sizeof(info) );
685  ok( size == sizeof(info),
686  "VirtualQuery error %u\n", GetLastError() );
687  ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
688  ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
689  ok( info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect );
690  ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
691  ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
692  ok( info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect );
693  UnmapViewOfFile( ptr );
694  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
695  sizeof(section_info), &info_size );
696  ok( status == STATUS_ACCESS_DENIED, "NtQuerySection failed err %x\n", status );
697  CloseHandle( mapping );
698 
700  ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
701  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
702  sizeof(section_info), &info_size );
703  ok( !status, "NtQuerySection failed err %x\n", status );
704  ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
705  ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
706  section_info.Attributes );
707  ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
708  ok( section_info.Size.QuadPart == info.RegionSize, "NtQuerySection wrong size %x%08x / %08lx\n",
709  section_info.Size.u.HighPart, section_info.Size.u.LowPart, info.RegionSize );
710  CloseHandle( mapping );
711 
712  CloseHandle( file );
713 
714  /* read/write mapping with SEC_RESERVE */
716  ok(mapping != INVALID_HANDLE_VALUE, "CreateFileMappingA failed with error %d\n", GetLastError());
717  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
718  sizeof(section_info), NULL );
719  ok( !status, "NtQuerySection failed err %x\n", status );
720  ok( section_info.Attributes == SEC_RESERVE, "NtQuerySection wrong attr %08x\n",
721  section_info.Attributes );
722  ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
723  ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %x%08x / %08x\n",
724  section_info.Size.u.HighPart, section_info.Size.u.LowPart, MAPPING_SIZE );
725 
727  ok(ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
728 
729  ptr2 = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
730  ok( ptr2 != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
731  ok( ptr != ptr2, "MapViewOfFile returned same pointer\n" );
732 
733  ret = VirtualQuery(ptr, &info, sizeof(info));
734  ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
735  ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
736  ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
737  ok(info.RegionSize == MAPPING_SIZE, "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE, info.RegionSize);
738  ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
739  ok(info.AllocationProtect == PAGE_READWRITE,
740  "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
741  ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
742  ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
743 
744  ret = VirtualQuery(ptr2, &info, sizeof(info));
745  ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
746  ok(info.BaseAddress == ptr2,
747  "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
748  ok(info.AllocationBase == ptr2,
749  "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
750  ok(info.AllocationProtect == PAGE_READWRITE,
751  "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
752  ok(info.RegionSize == MAPPING_SIZE,
753  "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE, info.RegionSize);
754  ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
755  ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
756  ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
757 
759  ok(ptr != NULL, "VirtualAlloc failed with error %d\n", GetLastError());
760 
761  ret = VirtualQuery(ptr, &info, sizeof(info));
762  ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
763  ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
764  ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
765  ok(info.RegionSize == 0x10000, "RegionSize should have been 0x10000 but was 0x%lx\n", info.RegionSize);
766  ok(info.State == MEM_COMMIT, "State should have been MEM_COMMIT instead of 0x%x\n", info.State);
767  ok(info.Protect == PAGE_READONLY, "Protect should have been PAGE_READONLY instead of 0x%x\n", info.Protect);
768  ok(info.AllocationProtect == PAGE_READWRITE,
769  "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
770  ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
771 
772  /* shows that the VirtualAlloc above affects the mapping, not just the
773  * virtual memory in this process - it also affects all other processes
774  * with a view of the mapping, but that isn't tested here */
775  ret = VirtualQuery(ptr2, &info, sizeof(info));
776  ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
777  ok(info.BaseAddress == ptr2,
778  "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
779  ok(info.AllocationBase == ptr2,
780  "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
781  ok(info.AllocationProtect == PAGE_READWRITE,
782  "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
783  ok(info.RegionSize == 0x10000,
784  "RegionSize should have been 0x10000 but was 0x%lx\n", info.RegionSize);
785  ok(info.State == MEM_COMMIT,
786  "State should have been MEM_COMMIT instead of 0x%x\n", info.State);
787  ok(info.Protect == PAGE_READWRITE,
788  "Protect should have been PAGE_READWRITE instead of 0x%x\n", info.Protect);
789  ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
790 
792  ok( addr == ptr, "VirtualAlloc failed with error %u\n", GetLastError() );
793 
794  ret = VirtualFree( ptr, 0x10000, MEM_DECOMMIT );
795  ok( !ret, "VirtualFree succeeded\n" );
796  ok( GetLastError() == ERROR_INVALID_PARAMETER, "VirtualFree failed with %u\n", GetLastError() );
797 
798  ret = UnmapViewOfFile(ptr2);
799  ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
801  ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
803 
805  ok( addr != NULL, "VirtualAlloc failed with error %u\n", GetLastError() );
806 
807  SetLastError(0xdeadbeef);
808  ok( !UnmapViewOfFile(addr), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
810  "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
811  SetLastError(0xdeadbeef);
812  ok( !UnmapViewOfFile((char *)addr + 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
814  "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
815  SetLastError(0xdeadbeef);
816  ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
818  "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
819 
820  ok( VirtualFree(addr, 0, MEM_RELEASE), "VirtualFree failed\n" );
821 
822  /* close named mapping handle without unmapping */
823  name = "Foo";
824  SetLastError(0xdeadbeef);
826  ok( mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
827  SetLastError(0xdeadbeef);
829  ok( ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError() );
830  SetLastError(0xdeadbeef);
832  ok( map2 != 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
833  SetLastError(0xdeadbeef);
834  ret = CloseHandle(map2);
835  ok(ret, "CloseHandle error %d\n", GetLastError());
836  SetLastError(0xdeadbeef);
838  ok(ret, "CloseHandle error %d\n", GetLastError());
839 
841  ok( !ret, "memory is not accessible\n" );
842 
843  ret = VirtualQuery(ptr, &info, sizeof(info));
844  ok(ret, "VirtualQuery error %d\n", GetLastError());
845  ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
846  ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
847  ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
848  ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
849  ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
850  ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
851  ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
852 
853  SetLastError(0xdeadbeef);
855  todo_wine
856  ok( map2 == 0, "OpenFileMappingA succeeded\n" );
857  todo_wine
858  ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %d\n", GetLastError() );
859  if (map2) CloseHandle(map2); /* FIXME: remove once Wine is fixed */
860  SetLastError(0xdeadbeef);
862  ok( mapping != 0, "CreateFileMappingA failed\n" );
863  todo_wine
864  ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %d\n", GetLastError() );
865  SetLastError(0xdeadbeef);
867  ok(ret, "CloseHandle error %d\n", GetLastError());
868 
870  ok( !ret, "memory is not accessible\n" );
871 
872  ret = VirtualQuery(ptr, &info, sizeof(info));
873  ok(ret, "VirtualQuery error %d\n", GetLastError());
874  ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
875  ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
876  ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
877  ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
878  ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
879  ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
880  ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
881 
882  SetLastError(0xdeadbeef);
884  ok( ret, "UnmapViewOfFile failed with error %d\n", GetLastError() );
885 
887  ok( ret, "memory is accessible\n" );
888 
889  ret = VirtualQuery(ptr, &info, sizeof(info));
890  ok(ret, "VirtualQuery error %d\n", GetLastError());
891  ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
892  ok(info.Protect == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", info.Protect);
893  ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase);
894  ok(info.AllocationProtect == 0, "%#x != 0\n", info.AllocationProtect);
895  ok(info.State == MEM_FREE, "%#x != MEM_FREE\n", info.State);
896  ok(info.Type == 0, "%#x != 0\n", info.Type);
897 
898  SetLastError(0xdeadbeef);
900  ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
903 
904  SetLastError(0xdeadbeef);
906  ok( mapping != 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
907  SetLastError(0xdeadbeef);
909  ok( ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError() );
910  SetLastError(0xdeadbeef);
912  ok( map2 != 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
913  SetLastError(0xdeadbeef);
914  ret = CloseHandle(map2);
915  ok(ret, "CloseHandle error %d\n", GetLastError());
916  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
917  sizeof(section_info), &info_size );
918  ok( !status, "NtQuerySection failed err %x\n", status );
919  ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
920  ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
921  section_info.Attributes );
922  ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
923  ok( section_info.Size.QuadPart == MAPPING_SIZE, "NtQuerySection wrong size %x%08x\n",
924  section_info.Size.u.HighPart, section_info.Size.u.LowPart );
925  SetLastError(0xdeadbeef);
927  ok(ret, "CloseHandle error %d\n", GetLastError());
928 
930  ok( !ret, "memory is not accessible\n" );
931 
932  ret = VirtualQuery(ptr, &info, sizeof(info));
933  ok(ret, "VirtualQuery error %d\n", GetLastError());
934  ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
935  ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
936  ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
937  ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
938  ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
939  ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
940  ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
941 
942  SetLastError(0xdeadbeef);
944  todo_wine
945  ok( map2 == 0, "OpenFileMappingA succeeded\n" );
946  todo_wine
947  ok( GetLastError() == ERROR_FILE_NOT_FOUND, "OpenFileMappingA set error %d\n", GetLastError() );
948  CloseHandle(map2);
949  SetLastError(0xdeadbeef);
951  ok( mapping != 0, "CreateFileMappingA failed\n" );
952  todo_wine
953  ok( GetLastError() == ERROR_SUCCESS, "CreateFileMappingA set error %d\n", GetLastError() );
954  SetLastError(0xdeadbeef);
956  ok(ret, "CloseHandle error %d\n", GetLastError());
957 
959  ok( !ret, "memory is not accessible\n" );
960 
961  ret = VirtualQuery(ptr, &info, sizeof(info));
962  ok(ret, "VirtualQuery error %d\n", GetLastError());
963  ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
964  ok(info.RegionSize == MAPPING_SIZE, "got %#lx != expected %#x\n", info.RegionSize, MAPPING_SIZE);
965  ok(info.Protect == PAGE_READWRITE, "got %#x != expected PAGE_READWRITE\n", info.Protect);
966  ok(info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr);
967  ok(info.AllocationProtect == PAGE_READWRITE, "%#x != PAGE_READWRITE\n", info.AllocationProtect);
968  ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
969  ok(info.Type == MEM_MAPPED, "%#x != MEM_MAPPED\n", info.Type);
970 
971  SetLastError(0xdeadbeef);
973  ok( ret, "UnmapViewOfFile failed with error %d\n", GetLastError() );
974 
976  ok( ret, "memory is accessible\n" );
977 
978  ret = VirtualQuery(ptr, &info, sizeof(info));
979  ok(ret, "VirtualQuery error %d\n", GetLastError());
980  ok(info.BaseAddress == ptr, "got %p != expected %p\n", info.BaseAddress, ptr);
981  ok(info.Protect == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", info.Protect);
982  ok(info.AllocationBase == NULL, "%p != NULL\n", info.AllocationBase);
983  ok(info.AllocationProtect == 0, "%#x != 0\n", info.AllocationProtect);
984  ok(info.State == MEM_FREE, "%#x != MEM_FREE\n", info.State);
985  ok(info.Type == 0, "%#x != 0\n", info.Type);
986 
988  ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
989 
990  ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
991  ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
992 
993  ret = UnmapViewOfFile( (char *)ptr + 100 );
994  ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
995 
996  ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
997  ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
998 
999  ret = UnmapViewOfFile( (char *)ptr + 4096 );
1000  ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
1001 
1002  ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 12288 );
1003  ok( ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError() );
1004 
1005  ret = UnmapViewOfFile( (char *)ptr + 4096 + 100 );
1006  ok( ret, "UnmapViewOfFile failed with error %u\n", GetLastError() );
1007 
1009 
1011  ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
1012  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
1013  sizeof(section_info), &info_size );
1014  ok( !status, "NtQuerySection failed err %x\n", status );
1015  ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
1016  ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1017  section_info.Attributes );
1018  ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1019  ok( section_info.Size.QuadPart == 36, "NtQuerySection wrong size %x%08x\n",
1020  section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1022 
1023  SetFilePointer(file, 0x3456, NULL, FILE_BEGIN);
1024  SetEndOfFile(file);
1026  ok( mapping != NULL, "CreateFileMappingA failed with error %u\n", GetLastError() );
1027  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info,
1028  sizeof(section_info), &info_size );
1029  ok( !status, "NtQuerySection failed err %x\n", status );
1030  ok( info_size == sizeof(section_info), "NtQuerySection wrong size %u\n", info_size );
1031  ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1032  section_info.Attributes );
1033  ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1034  ok( section_info.Size.QuadPart == 0x3456, "NtQuerySection wrong size %x%08x\n",
1035  section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1037 
1038  map_size.QuadPart = 0x3457;
1039  status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1040  &map_size, PAGE_READONLY, SEC_COMMIT, file );
1041  ok( status == STATUS_SECTION_TOO_BIG, "NtCreateSection failed %x\n", status );
1042  status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1043  &map_size, PAGE_READONLY, SEC_IMAGE, file );
1044  ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection failed %x\n", status );
1045  if (!status) CloseHandle( mapping );
1046  map_size.QuadPart = 0x3452;
1047  status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1048  &map_size, PAGE_READONLY, SEC_COMMIT, file );
1049  ok( !status, "NtCreateSection failed %x\n", status );
1050  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info), NULL );
1051  ok( !status, "NtQuerySection failed err %x\n", status );
1052  ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n",
1053  section_info.Attributes );
1054  ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1055  ok( section_info.Size.QuadPart == 0x3452, "NtQuerySection wrong size %x%08x\n",
1056  section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1057  size = map_size.QuadPart;
1058  status = pNtMapViewOfSection( mapping, GetCurrentProcess(), &ptr, 0, 0, NULL,
1059  &size, ViewShare, 0, PAGE_READONLY );
1060  ok( !status, "NtMapViewOfSection failed err %x\n", status );
1061  pNtUnmapViewOfSection( GetCurrentProcess(), ptr );
1062  size = map_size.QuadPart + 1;
1063  status = pNtMapViewOfSection( mapping, GetCurrentProcess(), &ptr, 0, 0, NULL,
1064  &size, ViewShare, 0, PAGE_READONLY );
1065  ok( status == STATUS_INVALID_VIEW_SIZE, "NtMapViewOfSection failed err %x\n", status );
1067 
1068  status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1069  &map_size, PAGE_READONLY, SEC_COMMIT, 0 );
1070  ok( !status, "NtCreateSection failed %x\n", status );
1071  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info), NULL );
1072  ok( !status, "NtQuerySection failed err %x\n", status );
1073  ok( section_info.Attributes == SEC_COMMIT, "NtQuerySection wrong attr %08x\n",
1074  section_info.Attributes );
1075  ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress );
1076  ok( section_info.Size.QuadPart == 0x4000, "NtQuerySection wrong size %x%08x\n",
1077  section_info.Size.u.HighPart, section_info.Size.u.LowPart );
1078  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info)-1, NULL );
1079  ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQuerySection failed err %x\n", status );
1080  status = pNtQuerySection( mapping, SectionBasicInformation, &section_info, sizeof(section_info)+1, NULL );
1081  ok( !status, "NtQuerySection failed err %x\n", status );
1082  status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info)-1, NULL );
1083  ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQuerySection failed err %x\n", status );
1084  status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info), NULL );
1085  ok( status == STATUS_SECTION_NOT_IMAGE, "NtQuerySection failed err %x\n", status );
1086  status = pNtQuerySection( mapping, SectionImageInformation, &image_info, sizeof(image_info)+1, NULL );
1087  ok( status == STATUS_SECTION_NOT_IMAGE, "NtQuerySection failed err %x\n", status );
1089 
1091  SetEndOfFile(file);
1092  status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1094  ok( status == STATUS_MAPPED_FILE_SIZE_ZERO, "NtCreateSection failed %x\n", status );
1095  status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL,
1097  ok( status == STATUS_INVALID_FILE_FOR_SECTION, "NtCreateSection failed %x\n", status );
1098 
1099  CloseHandle(file);
1100  DeleteFileA(testfile);
1101 }
1102 
1103 static void test_NtMapViewOfSection(void)
1104 {
1105  HANDLE hProcess;
1106 
1107  static const char testfile[] = "testfile.xxx";
1108  static const char data[] = "test data for NtMapViewOfSection";
1109  char buffer[sizeof(data)];
1110  HANDLE file, mapping;
1111  void *ptr, *ptr2;
1112  BOOL is_wow64, ret;
1113  DWORD status, written;
1114  SIZE_T size, result;
1116 
1117  if (!pNtMapViewOfSection || !pNtUnmapViewOfSection)
1118  {
1119  win_skip( "NtMapViewOfSection not available\n" );
1120  return;
1121  }
1122 
1123  file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1124  ok( file != INVALID_HANDLE_VALUE, "Failed to create test file\n" );
1125  WriteFile( file, data, sizeof(data), &written, NULL );
1126  SetFilePointer( file, 4096, NULL, FILE_BEGIN );
1127  SetEndOfFile( file );
1128 
1129  /* read/write mapping */
1130 
1132  ok( mapping != 0, "CreateFileMapping failed\n" );
1133 
1134  hProcess = create_target_process("sleep");
1135  ok(hProcess != NULL, "Can't start process\n");
1136 
1137  ptr = NULL;
1138  size = 0;
1139  offset.QuadPart = 0;
1140  status = pNtMapViewOfSection( mapping, hProcess, &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1141  ok( !status, "NtMapViewOfSection failed status %x\n", status );
1142  ok( !((ULONG_PTR)ptr & 0xffff), "returned memory %p is not aligned to 64k\n", ptr );
1143 
1144  ret = ReadProcessMemory( hProcess, ptr, buffer, sizeof(buffer), &result );
1145  ok( ret, "ReadProcessMemory failed\n" );
1146  ok( result == sizeof(buffer), "ReadProcessMemory didn't read all data (%lx)\n", result );
1147  ok( !memcmp( buffer, data, sizeof(buffer) ), "Wrong data read\n" );
1148 
1149  /* for some unknown reason NtMapViewOfSection fails with STATUS_NO_MEMORY when zero_bits != 0 ? */
1150  ptr2 = NULL;
1151  size = 0;
1152  offset.QuadPart = 0;
1153  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 12, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1154  todo_wine
1155  ok( status == STATUS_NO_MEMORY, "NtMapViewOfSection returned %x\n", status );
1156  if (status == STATUS_SUCCESS)
1157  {
1158  status = pNtUnmapViewOfSection( hProcess, ptr2 );
1159  ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1160  }
1161 
1162  ptr2 = NULL;
1163  size = 0;
1164  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1165  todo_wine
1166  ok( status == STATUS_NO_MEMORY, "NtMapViewOfSection returned %x\n", status );
1167  if (status == STATUS_SUCCESS)
1168  {
1169  status = pNtUnmapViewOfSection( hProcess, ptr2 );
1170  ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1171  }
1172 
1173  /* 22 zero bits isn't acceptable */
1174  ptr2 = NULL;
1175  size = 0;
1176  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 22, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1177  ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1178  if (status == STATUS_SUCCESS)
1179  {
1180  status = pNtUnmapViewOfSection( hProcess, ptr2 );
1181  ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1182  }
1183 
1184  /* mapping at the same page conflicts */
1185  ptr2 = ptr;
1186  size = 0;
1187  offset.QuadPart = 0;
1188  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1189  ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
1190 
1191  /* offset has to be aligned */
1192  ptr2 = ptr;
1193  size = 0;
1194  offset.QuadPart = 1;
1195  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1196  ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
1197 
1198  /* ptr has to be aligned */
1199  ptr2 = (char *)ptr + 42;
1200  size = 0;
1201  offset.QuadPart = 0;
1202  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1203  ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
1204 
1205  /* still not 64k aligned */
1206  ptr2 = (char *)ptr + 0x1000;
1207  size = 0;
1208  offset.QuadPart = 0;
1209  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1210  ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
1211 
1212  /* zero_bits != 0 is not allowed when an address is set */
1213  ptr2 = (char *)ptr + 0x1000;
1214  size = 0;
1215  offset.QuadPart = 0;
1216  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 12, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1217  ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1218 
1219  ptr2 = (char *)ptr + 0x1000;
1220  size = 0;
1221  offset.QuadPart = 0;
1222  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1223  ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1224 
1225  ptr2 = (char *)ptr + 0x1001;
1226  size = 0;
1227  offset.QuadPart = 0;
1228  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1229  ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1230 
1231  ptr2 = (char *)ptr + 0x1000;
1232  size = 0;
1233  offset.QuadPart = 1;
1234  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
1235  ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
1236 
1237  if (sizeof(void *) == sizeof(int) && (!pIsWow64Process ||
1238  !pIsWow64Process( GetCurrentProcess(), &is_wow64 ) || !is_wow64))
1239  {
1240  /* new memory region conflicts with previous mapping */
1241  ptr2 = ptr;
1242  size = 0;
1243  offset.QuadPart = 0;
1244  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1246  ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
1247 
1248  ptr2 = (char *)ptr + 42;
1249  size = 0;
1250  offset.QuadPart = 0;
1251  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1253  ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
1254 
1255  /* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
1256  ptr2 = (char *)ptr + 0x1000;
1257  size = 0;
1258  offset.QuadPart = 0;
1259  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1261  ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
1262  ok( (char *)ptr2 == (char *)ptr + 0x1000,
1263  "expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2 );
1264  status = pNtUnmapViewOfSection( hProcess, ptr2 );
1265  ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1266 
1267  /* the address is rounded down if not on a page boundary */
1268  ptr2 = (char *)ptr + 0x1001;
1269  size = 0;
1270  offset.QuadPart = 0;
1271  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1273  ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
1274  ok( (char *)ptr2 == (char *)ptr + 0x1000,
1275  "expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2 );
1276  status = pNtUnmapViewOfSection( hProcess, ptr2 );
1277  ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1278 
1279  ptr2 = (char *)ptr + 0x2000;
1280  size = 0;
1281  offset.QuadPart = 0;
1282  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1284  ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
1285  ok( (char *)ptr2 == (char *)ptr + 0x2000,
1286  "expected address %p, got %p\n", (char *)ptr + 0x2000, ptr2 );
1287  status = pNtUnmapViewOfSection( hProcess, ptr2 );
1288  ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1289  }
1290  else
1291  {
1292  ptr2 = (char *)ptr + 0x1000;
1293  size = 0;
1294  offset.QuadPart = 0;
1295  status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
1297  todo_wine
1298  ok( status == STATUS_INVALID_PARAMETER_9, "NtMapViewOfSection returned %x\n", status );
1299  }
1300 
1301  status = pNtUnmapViewOfSection( hProcess, ptr );
1302  ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
1303 
1304  CloseHandle( mapping );
1305  CloseHandle( file );
1306  DeleteFileA( testfile );
1307 
1310 }
1311 
1313 {
1314  static const char testfile[] = "testfile.xxx";
1315  HANDLE file, file2, mapping, map2;
1316  void *ptr, *ptr2;
1317  NTSTATUS status;
1318  char path[MAX_PATH];
1319 
1320  if (!pNtAreMappedFilesTheSame)
1321  {
1322  win_skip( "NtAreMappedFilesTheSame not available\n" );
1323  return;
1324  }
1325 
1327  NULL, CREATE_ALWAYS, 0, 0 );
1328  ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1329  SetFilePointer( file, 4096, NULL, FILE_BEGIN );
1330  SetEndOfFile( file );
1331 
1333  ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1334 
1335  ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1336  ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1337 
1339  NULL, OPEN_EXISTING, 0, 0 );
1340  ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1341 
1342  map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY, 0, 4096, NULL );
1343  ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1344  ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
1345  ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1346  status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1347  ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1348  UnmapViewOfFile( ptr2 );
1349 
1350  ptr2 = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1351  ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1352  status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1353  ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1354  UnmapViewOfFile( ptr2 );
1355  CloseHandle( map2 );
1356 
1357  map2 = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
1358  ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1359  ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
1360  ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1361  status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1362  ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1363  UnmapViewOfFile( ptr2 );
1364  CloseHandle( map2 );
1365  CloseHandle( file2 );
1366 
1367  status = pNtAreMappedFilesTheSame( ptr, ptr );
1369  "NtAreMappedFilesTheSame returned %x\n", status );
1370 
1371  status = pNtAreMappedFilesTheSame( ptr, (char *)ptr + 30 );
1373  "NtAreMappedFilesTheSame returned %x\n", status );
1374 
1375  status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1376  ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1377 
1378  status = pNtAreMappedFilesTheSame( ptr, (void *)0xdeadbeef );
1380  "NtAreMappedFilesTheSame returned %x\n", status );
1381 
1382  status = pNtAreMappedFilesTheSame( ptr, NULL );
1383  ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
1384 
1385  status = pNtAreMappedFilesTheSame( ptr, (void *)GetProcessHeap() );
1386  ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
1387 
1388  status = pNtAreMappedFilesTheSame( NULL, NULL );
1389  ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
1390 
1391  ptr2 = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE );
1392  ok( ptr2 != NULL, "VirtualAlloc error %u\n", GetLastError() );
1393  status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1394  ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
1395  VirtualFree( ptr2, 0, MEM_RELEASE );
1396 
1397  UnmapViewOfFile( ptr );
1398  CloseHandle( mapping );
1399  CloseHandle( file );
1400 
1401  status = pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
1402  GetModuleHandleA("kernel32.dll") );
1403  ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1404  status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1405  GetModuleHandleA("kernel32.dll") );
1406  ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1407  status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1408  (char *)GetModuleHandleA("kernel32.dll") + 4096 );
1409  ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1410 
1412  strcat( path, "\\kernel32.dll" );
1414  ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1415 
1417  ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1418  ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1419  ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1420  status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1421  ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
1422  UnmapViewOfFile( ptr );
1423  CloseHandle( mapping );
1424 
1426  ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
1427  ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
1428  ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1429  status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
1430  todo_wine
1431  ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1432 
1434  ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
1435  map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
1436  ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
1437  ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 0 );
1438  ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1439  status = pNtAreMappedFilesTheSame( ptr, ptr2 );
1440  ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
1441  UnmapViewOfFile( ptr2 );
1442  CloseHandle( map2 );
1443  CloseHandle( file2 );
1444 
1445  UnmapViewOfFile( ptr );
1446  CloseHandle( mapping );
1447 
1448  CloseHandle( file );
1449  DeleteFileA( testfile );
1450 }
1451 
1452 static void test_CreateFileMapping(void)
1453 {
1454  HANDLE handle, handle2;
1455 
1456  /* test case sensitivity */
1457 
1458  SetLastError(0xdeadbeef);
1460  "Wine Test Mapping");
1461  ok( handle != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
1462  ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1463 
1464  SetLastError(0xdeadbeef);
1466  "Wine Test Mapping");
1467  ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
1468  ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
1469  CloseHandle( handle2 );
1470 
1471  SetLastError(0xdeadbeef);
1473  "WINE TEST MAPPING");
1474  ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
1475  ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1476  CloseHandle( handle2 );
1477 
1478  SetLastError(0xdeadbeef);
1479  handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "Wine Test Mapping");
1480  ok( handle2 != NULL, "OpenFileMapping failed with error %d\n", GetLastError());
1481  CloseHandle( handle2 );
1482 
1483  SetLastError(0xdeadbeef);
1484  handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "WINE TEST MAPPING");
1485  ok( !handle2, "OpenFileMapping succeeded\n");
1486  ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
1487 
1488  CloseHandle( handle );
1489 }
1490 
1491 static void test_IsBadReadPtr(void)
1492 {
1493  BOOL ret;
1494  void *ptr = (void *)0xdeadbeef;
1495  char stackvar;
1496 
1497  ret = IsBadReadPtr(NULL, 0);
1498  ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1499 
1500  ret = IsBadReadPtr(NULL, 1);
1501  ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1502 
1503  ret = IsBadReadPtr(ptr, 0);
1504  ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1505 
1506  ret = IsBadReadPtr(ptr, 1);
1507  ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1508 
1509  ret = IsBadReadPtr(&stackvar, 0);
1510  ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1511 
1512  ret = IsBadReadPtr(&stackvar, sizeof(char));
1513  ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1514 }
1515 
1516 static void test_IsBadWritePtr(void)
1517 {
1518  BOOL ret;
1519  void *ptr = (void *)0xdeadbeef;
1520  char stackval;
1521 
1522  ret = IsBadWritePtr(NULL, 0);
1523  ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1524 
1525  ret = IsBadWritePtr(NULL, 1);
1526  ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1527 
1528  ret = IsBadWritePtr(ptr, 0);
1529  ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1530 
1531  ret = IsBadWritePtr(ptr, 1);
1532  ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1533 
1534  ret = IsBadWritePtr(&stackval, 0);
1535  ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1536 
1537  ret = IsBadWritePtr(&stackval, sizeof(char));
1538  ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1539 }
1540 
1541 static void test_IsBadCodePtr(void)
1542 {
1543  BOOL ret;
1544  void *ptr = (void *)0xdeadbeef;
1545  char stackval;
1546 
1547  ret = IsBadCodePtr(NULL);
1548  ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1549 
1550  ret = IsBadCodePtr(ptr);
1551  ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1552 
1553  ret = IsBadCodePtr((void *)&stackval);
1554  ok(ret == FALSE, "Expected IsBadCodePtr to return FALSE, got %d\n", ret);
1555 }
1556 
1557 static void test_write_watch(void)
1558 {
1559  static const char pipename[] = "\\\\.\\pipe\\test_write_watch_pipe";
1560  static const char testdata[] = "Hello World";
1561  DWORD ret, size, old_prot, num_bytes;
1563  HANDLE readpipe, writepipe;
1565  void *results[64];
1566  ULONG_PTR count;
1567  ULONG pagesize;
1568  BOOL success;
1569  char *base;
1570 
1571  if (!pGetWriteWatch || !pResetWriteWatch)
1572  {
1573  win_skip( "GetWriteWatch not supported\n" );
1574  return;
1575  }
1576 
1577  size = 0x10000;
1579  if (!base &&
1581  {
1582  win_skip( "MEM_WRITE_WATCH not supported\n" );
1583  return;
1584  }
1585  ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1586  ret = VirtualQuery( base, &info, sizeof(info) );
1587  ok(ret, "VirtualQuery failed %u\n", GetLastError());
1588  ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1589  ok( info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect %x\n", info.AllocationProtect );
1590  ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1591  ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1592  ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1593  ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
1594 
1595  count = 64;
1596  SetLastError( 0xdeadbeef );
1597  ret = pGetWriteWatch( 0, NULL, size, results, &count, &pagesize );
1598  ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1600  broken( GetLastError() == 0xdeadbeef ), /* win98 */
1601  "wrong error %u\n", GetLastError() );
1602 
1603  SetLastError( 0xdeadbeef );
1604  ret = pGetWriteWatch( 0, GetModuleHandleW(NULL), size, results, &count, &pagesize );
1605  if (ret)
1606  {
1607  ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1608  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1609  }
1610  else /* win98 */
1611  {
1612  ok( count == 0, "wrong count %lu\n", count );
1613  }
1614 
1615  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1616  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1617  ok( count == 0, "wrong count %lu\n", count );
1618 
1619  base[pagesize + 1] = 0x44;
1620 
1621  count = 64;
1622  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1623  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1624  ok( count == 1, "wrong count %lu\n", count );
1625  ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1626 
1627  count = 64;
1628  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1629  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1630  ok( count == 1, "wrong count %lu\n", count );
1631  ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1632 
1633  count = 64;
1634  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1635  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1636  ok( count == 0, "wrong count %lu\n", count );
1637 
1638  base[2*pagesize + 3] = 0x11;
1639  base[4*pagesize + 8] = 0x11;
1640 
1641  count = 64;
1642  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1643  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1644  ok( count == 2, "wrong count %lu\n", count );
1645  ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1646  ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1647 
1648  count = 64;
1649  ret = pGetWriteWatch( 0, base + 3*pagesize, 2*pagesize, results, &count, &pagesize );
1650  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1651  ok( count == 1, "wrong count %lu\n", count );
1652  ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1653 
1654  ret = pResetWriteWatch( base, 3*pagesize );
1655  ok( !ret, "pResetWriteWatch failed %u\n", GetLastError() );
1656 
1657  count = 64;
1658  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1659  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1660  ok( count == 1, "wrong count %lu\n", count );
1661  ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1662 
1663  *(DWORD *)(base + 2*pagesize - 2) = 0xdeadbeef;
1664 
1665  count = 64;
1666  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1667  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1668  ok( count == 3, "wrong count %lu\n", count );
1669  ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1670  ok( results[1] == base + 2*pagesize, "wrong result %p\n", results[1] );
1671  ok( results[2] == base + 4*pagesize, "wrong result %p\n", results[2] );
1672 
1673  count = 1;
1674  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1675  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1676  ok( count == 1, "wrong count %lu\n", count );
1677  ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1678 
1679  count = 64;
1680  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1681  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1682  ok( count == 2, "wrong count %lu\n", count );
1683  ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1684  ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1685 
1686  /* changing protections doesn't affect watches */
1687 
1688  ret = VirtualProtect( base, 3*pagesize, PAGE_READONLY, &old_prot );
1689  ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1690  ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1691 
1692  ret = VirtualQuery( base, &info, sizeof(info) );
1693  ok(ret, "VirtualQuery failed %u\n", GetLastError());
1694  ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1695  ok( info.RegionSize == 3*pagesize, "wrong RegionSize 0x%lx\n", info.RegionSize );
1696  ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1697  ok( info.Protect == PAGE_READONLY, "wrong Protect 0x%x\n", info.Protect );
1698 
1699  ret = VirtualProtect( base, 3*pagesize, PAGE_READWRITE, &old_prot );
1700  ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1701  ok( old_prot == PAGE_READONLY, "wrong old prot %x\n", old_prot );
1702 
1703  count = 64;
1704  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1705  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1706  ok( count == 2, "wrong count %lu\n", count );
1707  ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1708  ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1709 
1710  ret = VirtualQuery( base, &info, sizeof(info) );
1711  ok(ret, "VirtualQuery failed %u\n", GetLastError());
1712  ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1713  ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1714  ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1715  ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1716 
1717  /* ReadFile should trigger write watches */
1718 
1719  memset( &overlapped, 0, sizeof(overlapped) );
1720  overlapped.hEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
1721 
1723  PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024,
1725  ok( readpipe != INVALID_HANDLE_VALUE, "CreateNamedPipeA failed %u\n", GetLastError() );
1726 
1727  success = ConnectNamedPipe( readpipe, &overlapped );
1728  ok( !success, "ConnectNamedPipe unexpectedly succeeded\n" );
1729  ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1730 
1731  writepipe = CreateFileA( pipename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
1732  ok( writepipe != INVALID_HANDLE_VALUE, "CreateFileA failed %u\n", GetLastError() );
1733 
1734  ret = WaitForSingleObject( overlapped.hEvent, 1000 );
1735  ok( ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret );
1736 
1737  memset( base, 0, size );
1738 
1739  count = 64;
1740  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1741  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1742  ok( count == 16, "wrong count %lu\n", count );
1743 
1744  success = ReadFile( readpipe, base, size, NULL, &overlapped );
1745  ok( !success, "ReadFile unexpectedly succeeded\n" );
1746  ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1747 
1748  count = 64;
1749  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1750  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1751  ok( count == 16, "wrong count %lu\n", count );
1752 
1753  num_bytes = 0;
1754  success = WriteFile( writepipe, testdata, sizeof(testdata), &num_bytes, NULL );
1755  ok( success, "WriteFile failed %u\n", GetLastError() );
1756  ok( num_bytes == sizeof(testdata), "wrong number of bytes written\n" );
1757 
1758  num_bytes = 0;
1760  ok( success, "GetOverlappedResult failed %u\n", GetLastError() );
1761  ok( num_bytes == sizeof(testdata), "wrong number of bytes read\n" );
1762  ok( !memcmp( base, testdata, sizeof(testdata)), "didn't receive expected data\n" );
1763 
1764  count = 64;
1765  memset( results, 0, sizeof(results) );
1766  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1767  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1768  todo_wine ok( count == 1, "wrong count %lu\n", count );
1769  ok( results[0] == base, "wrong result %p\n", results[0] );
1770 
1771  CloseHandle( readpipe );
1772  CloseHandle( writepipe );
1773  CloseHandle( overlapped.hEvent );
1774 
1775  /* some invalid parameter tests */
1776 
1777  SetLastError( 0xdeadbeef );
1778  count = 0;
1779  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1780  if (ret)
1781  {
1782  ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1783  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1784 
1785  SetLastError( 0xdeadbeef );
1786  ret = pGetWriteWatch( 0, base, size, results, NULL, &pagesize );
1787  ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1788  ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1789 
1790  SetLastError( 0xdeadbeef );
1791  count = 64;
1792  ret = pGetWriteWatch( 0, base, size, results, &count, NULL );
1793  ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1794  ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1795 
1796  SetLastError( 0xdeadbeef );
1797  count = 64;
1798  ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1799  ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1800  ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1801 
1802  SetLastError( 0xdeadbeef );
1803  count = 0;
1804  ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1805  ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1806  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1807 
1808  SetLastError( 0xdeadbeef );
1809  count = 64;
1810  ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
1811  ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1812  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1813 
1814  SetLastError( 0xdeadbeef );
1815  count = 64;
1816  ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
1817  ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1818  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1819 
1820  SetLastError( 0xdeadbeef );
1821  count = 64;
1822  ret = pGetWriteWatch( 0, base, size * 2, results, &count, &pagesize );
1823  ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1824  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1825 
1826  SetLastError( 0xdeadbeef );
1827  count = 64;
1828  ret = pGetWriteWatch( 0, base + size - pagesize, pagesize + 1, results, &count, &pagesize );
1829  ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1830  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1831 
1832  SetLastError( 0xdeadbeef );
1833  ret = pResetWriteWatch( base, 0 );
1834  ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
1835  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1836 
1837  SetLastError( 0xdeadbeef );
1838  ret = pResetWriteWatch( GetModuleHandleW(NULL), size );
1839  ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
1840  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1841  }
1842  else /* win98 is completely different */
1843  {
1844  SetLastError( 0xdeadbeef );
1845  count = 64;
1846  ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1847  ok( ret == ERROR_INVALID_PARAMETER, "GetWriteWatch succeeded %u\n", ret );
1848  ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
1849 
1850  count = 0;
1851  ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1852  ok( !ret, "GetWriteWatch failed %u\n", ret );
1853 
1854  count = 64;
1855  ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
1856  ok( !ret, "GetWriteWatch failed %u\n", ret );
1857 
1858  count = 64;
1859  ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
1860  ok( !ret, "GetWriteWatch failed %u\n", ret );
1861 
1862  ret = pResetWriteWatch( base, 0 );
1863  ok( !ret, "ResetWriteWatch failed %u\n", ret );
1864 
1865  ret = pResetWriteWatch( GetModuleHandleW(NULL), size );
1866  ok( !ret, "ResetWriteWatch failed %u\n", ret );
1867  }
1868 
1869  VirtualFree( base, 0, MEM_RELEASE );
1870 
1872  ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1873  VirtualFree( base, 0, MEM_RELEASE );
1874 
1876  ok( !base, "VirtualAlloc succeeded\n" );
1877  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1878 
1879  /* initial protect doesn't matter */
1880 
1882  ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1884  ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1885 
1886  count = 64;
1887  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1888  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1889  ok( count == 0, "wrong count %lu\n", count );
1890 
1891  ret = VirtualProtect( base, 6*pagesize, PAGE_READWRITE, &old_prot );
1892  ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1893  ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
1894 
1895  base[5*pagesize + 200] = 3;
1896 
1897  ret = VirtualProtect( base, 6*pagesize, PAGE_NOACCESS, &old_prot );
1898  ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1899  ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1900 
1901  count = 64;
1902  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1903  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1904  ok( count == 1, "wrong count %lu\n", count );
1905  ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
1906 
1908  ok( ret, "VirtualFree failed %u\n", GetLastError() );
1909 
1910  count = 64;
1911  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1912  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1913  ok( count == 1 || broken(count == 0), /* win98 */
1914  "wrong count %lu\n", count );
1915  if (count) ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
1916 
1917  VirtualFree( base, 0, MEM_RELEASE );
1918 }
1919 
1920 #if defined(__i386__) || defined(__x86_64__)
1921 
1922 static DWORD WINAPI stack_commit_func( void *arg )
1923 {
1924  volatile char *p = (char *)&p;
1925 
1926  /* trigger all guard pages, to ensure that the pages are committed */
1927  while (p >= (char *)NtCurrentTeb()->DeallocationStack + 4 * 0x1000)
1928  {
1929  p[0] |= 0;
1930  p -= 0x1000;
1931  }
1932 
1933  ok( arg == (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg );
1934  return 42;
1935 }
1936 
1937 static void test_stack_commit(void)
1938 {
1939 #ifdef __i386__
1940  static const char code_call_on_stack[] = {
1941  0x55, /* pushl %ebp */
1942  0x56, /* pushl %esi */
1943  0x89, 0xe6, /* movl %esp,%esi */
1944  0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */
1945  0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */
1946  0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */
1947  0x83, 0xe0, 0xf0, /* andl $~15,%eax */
1948  0x83, 0xe8, 0x0c, /* subl $12,%eax */
1949  0x89, 0xc4, /* movl %eax,%esp */
1950  0x52, /* pushl %edx */
1951  0x31, 0xed, /* xorl %ebp,%ebp */
1952  0xff, 0xd1, /* call *%ecx */
1953  0x89, 0xf4, /* movl %esi,%esp */
1954  0x5e, /* popl %esi */
1955  0x5d, /* popl %ebp */
1956  0xc2, 0x0c, 0x00 }; /* ret $12 */
1957 #else
1958  static const char code_call_on_stack[] = {
1959  0x55, /* pushq %rbp */
1960  0x48, 0x89, 0xe5, /* movq %rsp,%rbp */
1961  /* %rcx - func, %rdx - arg, %r8 - stack */
1962  0x48, 0x87, 0xca, /* xchgq %rcx,%rdx */
1963  0x49, 0x83, 0xe0, 0xf0, /* andq $~15,%r8 */
1964  0x49, 0x83, 0xe8, 0x20, /* subq $0x20,%r8 */
1965  0x4c, 0x89, 0xc4, /* movq %r8,%rsp */
1966  0xff, 0xd2, /* callq *%rdx */
1967  0x48, 0x89, 0xec, /* movq %rbp,%rsp */
1968  0x5d, /* popq %rbp */
1969  0xc3 }; /* ret */
1970 #endif
1971  DWORD (WINAPI *call_on_stack)( DWORD (WINAPI *func)(void *), void *arg, void *stack );
1972  void *old_stack, *old_stack_base, *old_stack_limit;
1973  void *new_stack, *new_stack_base;
1974  DWORD result;
1975 
1976  call_on_stack = VirtualAlloc( 0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE );
1977  ok( call_on_stack != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1978  memcpy( call_on_stack, code_call_on_stack, sizeof(code_call_on_stack) );
1979 
1980  /* allocate a new stack, only the first guard page is committed */
1981  new_stack = VirtualAlloc( 0, 0x400000, MEM_RESERVE, PAGE_READWRITE );
1982  ok( new_stack != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1983  new_stack_base = (char *)new_stack + 0x400000;
1984  VirtualAlloc( (char *)new_stack_base - 0x1000, 0x1000, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
1985 
1986  old_stack = NtCurrentTeb()->DeallocationStack;
1987  old_stack_base = NtCurrentTeb()->Tib.StackBase;
1988  old_stack_limit = NtCurrentTeb()->Tib.StackLimit;
1989 
1990  NtCurrentTeb()->DeallocationStack = new_stack;
1991  NtCurrentTeb()->Tib.StackBase = new_stack_base;
1992  NtCurrentTeb()->Tib.StackLimit = new_stack_base;
1993 
1994  result = call_on_stack( stack_commit_func, (void *)0xdeadbeef, new_stack_base );
1995 
1996  NtCurrentTeb()->DeallocationStack = old_stack;
1997  NtCurrentTeb()->Tib.StackBase = old_stack_base;
1998  NtCurrentTeb()->Tib.StackLimit = old_stack_limit;
1999 
2000  ok( result == 42, "expected 42, got %u\n", result );
2001 
2002  VirtualFree( new_stack, 0, MEM_RELEASE );
2003  VirtualFree( call_on_stack, 0, MEM_RELEASE );
2004 }
2005 
2006 #endif /* defined(__i386__) || defined(__x86_64__) */
2007 #ifdef __i386__
2008 
2009 static LONG num_guard_page_calls;
2010 
2011 static DWORD guard_page_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
2013 {
2014  trace( "exception: %08x flags:%x addr:%p\n",
2015  rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
2016 
2017  ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
2018  ok( rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION, "ExceptionCode is %08x instead of %08x\n",
2020 
2021  InterlockedIncrement( &num_guard_page_calls );
2022  *(int *)rec->ExceptionInformation[1] += 0x100;
2023 
2025 }
2026 
2027 static void test_guard_page(void)
2028 {
2031  DWORD ret, size, old_prot;
2032  int *value, old_value;
2033  void *results[64];
2034  ULONG_PTR count;
2035  ULONG pagesize;
2036  BOOL success;
2037  char *base;
2038 
2039  size = 0x1000;
2041  ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2042  value = (int *)base;
2043 
2044  /* verify info structure */
2045  ret = VirtualQuery( base, &info, sizeof(info) );
2046  ok( ret, "VirtualQuery failed %u\n", GetLastError());
2047  ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
2048  ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
2049  ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
2050  ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
2051  ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%x\n", info.Protect );
2052  ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
2053 
2054  /* put some initial value into the memory */
2055  success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2056  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2057  ok( old_prot == (PAGE_READWRITE | PAGE_GUARD), "wrong old prot %x\n", old_prot );
2058 
2059  *value = 1;
2060  *(value + 1) = 2;
2061 
2063  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2064  ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2065 
2066  /* test behaviour of VirtualLock - first attempt should fail */
2067  SetLastError( 0xdeadbeef );
2068  success = VirtualLock( base, size );
2069  ok( !success, "VirtualLock unexpectedly succeeded\n" );
2070  todo_wine
2071  ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %u\n", GetLastError() );
2072 
2073  success = VirtualLock( base, size );
2074  todo_wine
2075  ok( success, "VirtualLock failed %u\n", GetLastError() );
2076  if (success)
2077  {
2078  ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2080  ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2081  }
2082 
2083  /* check info structure again, PAGE_GUARD should be removed now */
2084  ret = VirtualQuery( base, &info, sizeof(info) );
2085  ok( ret, "VirtualQuery failed %u\n", GetLastError());
2086  ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
2087  ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
2088  ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
2089  ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
2090  todo_wine
2091  ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
2092  ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
2093 
2095  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2096  todo_wine
2097  ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2098 
2099  /* test directly accessing the memory - we need to setup an exception handler first */
2100  frame.Handler = guard_page_handler;
2101  frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2102  NtCurrentTeb()->Tib.ExceptionList = &frame;
2103 
2104  InterlockedExchange( &num_guard_page_calls, 0 );
2105  InterlockedExchange( &old_value, *value ); /* exception handler increments value by 0x100 */
2106  *value = 2;
2107  ok( old_value == 0x101, "memory block contains wrong value, expected 0x101, got 0x%x\n", old_value );
2108  ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2109 
2110  NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2111 
2112  /* check info structure again, PAGE_GUARD should be removed now */
2113  ret = VirtualQuery( base, &info, sizeof(info) );
2114  ok( ret, "VirtualQuery failed %u\n", GetLastError());
2115  ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
2116 
2118  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2119  ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2120 
2121  /* test accessing second integer in memory */
2122  frame.Handler = guard_page_handler;
2123  frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2124  NtCurrentTeb()->Tib.ExceptionList = &frame;
2125 
2126  InterlockedExchange( &num_guard_page_calls, 0 );
2127  old_value = *(value + 1);
2128  ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value );
2129  ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value );
2130  ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2131 
2132  NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2133 
2134  success = VirtualLock( base, size );
2135  ok( success, "VirtualLock failed %u\n", GetLastError() );
2136  if (success)
2137  {
2138  ok( *value == 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value );
2140  ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2141  }
2142 
2143  VirtualFree( base, 0, MEM_RELEASE );
2144 
2145  /* combined guard page / write watch tests */
2146  if (!pGetWriteWatch || !pResetWriteWatch)
2147  {
2148  win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" );
2149  return;
2150  }
2151 
2154  {
2155  win_skip( "MEM_WRITE_WATCH not supported\n" );
2156  return;
2157  }
2158  ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2159  value = (int *)base;
2160 
2161  ret = VirtualQuery( base, &info, sizeof(info) );
2162  ok( ret, "VirtualQuery failed %u\n", GetLastError() );
2163  ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
2164  ok( info.AllocationProtect == (PAGE_READWRITE | PAGE_GUARD), "wrong AllocationProtect %x\n", info.AllocationProtect );
2165  ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
2166  ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
2167  ok( info.Protect == (PAGE_READWRITE | PAGE_GUARD), "wrong Protect 0x%x\n", info.Protect );
2168  ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
2169 
2170  count = 64;
2171  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
2172  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2173  ok( count == 0, "wrong count %lu\n", count );
2174 
2175  /* writing to a page should trigger should trigger guard page, even if write watch is set */
2176  frame.Handler = guard_page_handler;
2177  frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2178  NtCurrentTeb()->Tib.ExceptionList = &frame;
2179 
2180  InterlockedExchange( &num_guard_page_calls, 0 );
2181  *value = 1;
2182  *(value + 1) = 2;
2183  ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2184 
2185  NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2186 
2187  count = 64;
2188  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2189  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2190  ok( count == 1, "wrong count %lu\n", count );
2191  ok( results[0] == base, "wrong result %p\n", results[0] );
2192 
2194  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2195 
2196  /* write watch is triggered from inside of the guard page handler */
2197  frame.Handler = guard_page_handler;
2198  frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2199  NtCurrentTeb()->Tib.ExceptionList = &frame;
2200 
2201  InterlockedExchange( &num_guard_page_calls, 0 );
2202  old_value = *(value + 1); /* doesn't trigger write watch */
2203  ok( old_value == 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value );
2204  ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2205  ok( num_guard_page_calls == 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls );
2206 
2207  NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2208 
2209  count = 64;
2210  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2211  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2212  ok( count == 1, "wrong count %lu\n", count );
2213  ok( results[0] == base, "wrong result %p\n", results[0] );
2214 
2216  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2217 
2218  /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */
2219  SetLastError( 0xdeadbeef );
2220  success = VirtualLock( base, size );
2221  ok( !success, "VirtualLock unexpectedly succeeded\n" );
2222  todo_wine
2223  ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION, "wrong error %u\n", GetLastError() );
2224 
2225  count = 64;
2226  ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
2227  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2228  ok( count == 0, "wrong count %lu\n", count );
2229 
2230  success = VirtualLock( base, size );
2231  todo_wine
2232  ok( success, "VirtualLock failed %u\n", GetLastError() );
2233  if (success)
2234  {
2235  ok( *value == 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value );
2237  ok( success, "VirtualUnlock failed %u\n", GetLastError() );
2238  }
2239 
2240  count = 64;
2241  results[0] = (void *)0xdeadbeef;
2242  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2243  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2244  todo_wine
2245  ok( count == 1 || broken(count == 0) /* Windows 8 */, "wrong count %lu\n", count );
2246  todo_wine
2247  ok( results[0] == base || broken(results[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results[0] );
2248 
2249  VirtualFree( base, 0, MEM_RELEASE );
2250 }
2251 
2252 static LONG num_execute_fault_calls;
2253 
2254 static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
2256 {
2258  DWORD err;
2259 
2260  trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2262  rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] );
2263 
2264  ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
2266  "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec->ExceptionCode );
2267 
2269 
2271  {
2272 
2274  ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %d instead of %d\n",
2275  (DWORD)rec->ExceptionInformation[0], err );
2276 
2277  InterlockedIncrement( &num_guard_page_calls );
2278  }
2279  else if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION)
2280  {
2281  DWORD old_prot;
2282  BOOL success;
2283 
2285  ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %d instead of %d\n",
2286  (DWORD)rec->ExceptionInformation[0], err );
2287 
2288  success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
2289  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2290  ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
2291 
2292  InterlockedIncrement( &num_execute_fault_calls );
2293  }
2294 
2296 }
2297 
2298 static LONG CALLBACK execute_fault_vec_handler( EXCEPTION_POINTERS *ExceptionInfo )
2299 {
2300  PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
2301  DWORD old_prot;
2302  BOOL success;
2303 
2304  trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2306  rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] );
2307 
2308  ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
2310  "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec->ExceptionCode );
2311 
2313  InterlockedIncrement( &num_execute_fault_calls );
2314 
2317 
2318  success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
2319  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2320  ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
2321 
2323 }
2324 
2325 static inline DWORD send_message_excpt( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2326 {
2328  DWORD ret;
2329 
2330  frame.Handler = execute_fault_seh_handler;
2331  frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2332  NtCurrentTeb()->Tib.ExceptionList = &frame;
2333 
2334  InterlockedExchange( &num_guard_page_calls, 0 );
2335  InterlockedExchange( &num_execute_fault_calls, 0 );
2336  ret = SendMessageA( hWnd, uMsg, wParam, lParam );
2337 
2338  NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2339 
2340  return ret;
2341 }
2342 
2343 static inline DWORD call_proc_excpt( DWORD (CALLBACK *code)(void *), void *arg )
2344 {
2346  DWORD ret;
2347 
2348  frame.Handler = execute_fault_seh_handler;
2349  frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
2350  NtCurrentTeb()->Tib.ExceptionList = &frame;
2351 
2352  InterlockedExchange( &num_guard_page_calls, 0 );
2353  InterlockedExchange( &num_execute_fault_calls, 0 );
2354  ret = code( arg );
2355 
2356  NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
2357 
2358  return ret;
2359 }
2360 
2361 static LRESULT CALLBACK jmp_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2362 {
2363  if (uMsg == WM_USER)
2364  return 42;
2365 
2366  return DefWindowProcA( hWnd, uMsg, wParam, lParam );
2367 }
2368 
2369 static LRESULT CALLBACK atl_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2370 {
2371  DWORD arg = (DWORD)hWnd;
2372  if (uMsg == WM_USER)
2373  ok( arg == 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg );
2374  else
2375  ok( arg != 0x11223344, "arg is unexpectedly 0x11223344\n" );
2376  return 43;
2377 }
2378 
2379 static DWORD CALLBACK atl5_test_func( void )
2380 {
2381  return 44;
2382 }
2383 
2384 static void test_atl_thunk_emulation( ULONG dep_flags )
2385 {
2386  static const char code_jmp[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
2387  static const char code_atl1[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2388  static const char code_atl2[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2389  static const char code_atl3[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1};
2390  static const char code_atl4[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
2391  static const char code_atl5[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04};
2392  static const char cls_name[] = "atl_thunk_class";
2393  DWORD ret, size, old_prot;
2394  ULONG old_flags = MEM_EXECUTE_OPTION_ENABLE;
2396  void *results[64];
2397  ULONG_PTR count;
2398  ULONG pagesize;
2399  WNDCLASSEXA wc;
2400  char *base;
2401  HWND hWnd;
2402 
2403  trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
2404 
2405  NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags), NULL );
2406  if (old_flags != dep_flags)
2407  {
2408  ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &dep_flags, sizeof(dep_flags) );
2409  if (ret == STATUS_INVALID_INFO_CLASS) /* Windows 2000 */
2410  {
2411  win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
2412  return;
2413  }
2414  ok( !ret, "NtSetInformationProcess failed with status %08x\n", ret );
2415  restore_flags = TRUE;
2416  }
2417 
2418  size = 0x1000;
2420  ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2421 
2422  /* Check result of GetProcessDEPPolicy */
2423  if (!pGetProcessDEPPolicy)
2424  win_skip( "GetProcessDEPPolicy not supported\n" );
2425  else
2426  {
2427  BOOL (WINAPI *get_dep_policy)(HANDLE, LPDWORD, PBOOL) = (void *)base;
2428  BOOL policy_permanent = 0xdeadbeef;
2429  DWORD policy_flags = 0xdeadbeef;
2430 
2431  /* GetProcessDEPPolicy crashes on Windows when a NULL pointer is passed.
2432  * Moreover this function has a bug on Windows 8, which has the effect that
2433  * policy_permanent is set to the content of the CL register instead of 0,
2434  * when the policy is not permanent. To detect that we use an assembler
2435  * wrapper to call the function. */
2436 
2437  memcpy( base, code_atl2, sizeof(code_atl2) );
2438  *(DWORD *)(base + 6) = (DWORD_PTR)pGetProcessDEPPolicy - (DWORD_PTR)(base + 10);
2439 
2441  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2442 
2443  success = get_dep_policy( GetCurrentProcess(), &policy_flags, &policy_permanent );
2444  ok( success, "GetProcessDEPPolicy failed %u\n", GetLastError() );
2445 
2446  ret = 0;
2447  if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2448  ret |= PROCESS_DEP_ENABLE;
2450  ret |= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION;
2451 
2452  ok( policy_flags == ret, "expected policy flags %d, got %d\n", ret, policy_flags );
2453  ok( !policy_permanent || broken(policy_permanent == 0x44),
2454  "expected policy permanent FALSE, got %d\n", policy_permanent );
2455  }
2456 
2457  memcpy( base, code_jmp, sizeof(code_jmp) );
2458  *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2459 
2460  /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
2461  * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
2462  * where it is active, so that application which depend on that still work properly.
2463  * We have no exception handler enabled yet, so give proper EXECUTE permissions to
2464  * prevent crashes while creating the window. */
2465 
2467  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2468 
2469  memset( &wc, 0, sizeof(wc) );
2470  wc.cbSize = sizeof(wc);
2471  wc.style = CS_VREDRAW | CS_HREDRAW;
2472  wc.hInstance = GetModuleHandleA( 0 );
2474  wc.hbrBackground = NULL;
2475  wc.lpszClassName = cls_name;
2476  wc.lpfnWndProc = (WNDPROC)base;
2477  success = RegisterClassExA(&wc) != 0;
2478  ok( success, "RegisterClassExA failed %u\n", GetLastError() );
2479 
2480  hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2481  ok( hWnd != 0, "CreateWindowExA failed %u\n", GetLastError() );
2482 
2483  ret = SendMessageA(hWnd, WM_USER, 0, 0);
2484  ok( ret == 42, "SendMessage returned unexpected result %d\n", ret );
2485 
2486  /* At first try with an instruction which is not recognized as proper ATL thunk
2487  * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2488  * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2489 
2490  success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2491  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2492 
2493  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2494  ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2495  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2497  {
2498  trace( "DEP hardware support is not available\n" );
2499  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2500  dep_flags = MEM_EXECUTE_OPTION_ENABLE;
2501  }
2502  else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2503  {
2504  trace( "DEP hardware support is available\n" );
2505  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2506  }
2507  else
2508  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2509 
2510  /* Now a bit more complicated, the page containing the code is protected with
2511  * PAGE_GUARD memory protection. */
2512 
2514  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2515 
2516  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2517  ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2518  ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2519  if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2520  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2521  else
2522  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2523 
2524  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2525  ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2526  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2527  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2528 
2529  /* Now test with a proper ATL thunk instruction. */
2530 
2531  memcpy( base, code_atl1, sizeof(code_atl1) );
2532  *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
2533 
2535  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2536 
2537  ret = SendMessageA(hWnd, WM_USER, 0, 0);
2538  ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
2539 
2540  /* Try executing with PAGE_READWRITE protection. */
2541 
2542  success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2543  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2544 
2545  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2546  ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2547  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2549  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2550  else
2551  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2552 
2553  /* Now a bit more complicated, the page containing the code is protected with
2554  * PAGE_GUARD memory protection. */
2555 
2557  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2558 
2559  /* the same, but with PAGE_GUARD set */
2560  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2561  ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2562  ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2564  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2565  else
2566  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2567 
2568  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2569  ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2570  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2571  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2572 
2573  /* The following test shows that on Windows, even a vectored exception handler
2574  * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */
2575 
2576  if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && !(dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
2577  {
2578  if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
2579  {
2580  PVOID vectored_handler;
2581 
2582  success = VirtualProtect( base, size, PAGE_NOACCESS, &old_prot );
2583  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2584 
2585  vectored_handler = pRtlAddVectoredExceptionHandler( TRUE, &execute_fault_vec_handler );
2586  ok( vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n" );
2587 
2588  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2589 
2590  pRtlRemoveVectoredExceptionHandler( vectored_handler );
2591 
2592  ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2593  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2594  }
2595  else
2596  win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" );
2597  }
2598 
2599  /* Test alternative ATL thunk instructions. */
2600 
2601  memcpy( base, code_atl2, sizeof(code_atl2) );
2602  *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 10);
2603 
2604  success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2605  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2606 
2607  ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2608  /* FIXME: we don't check the content of the register ECX yet */
2609  ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2610  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2612  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2613  else
2614  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2615 
2616  memcpy( base, code_atl3, sizeof(code_atl3) );
2617  *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func;
2618 
2619  success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2620  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2621 
2622  ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2623  /* FIXME: we don't check the content of the registers ECX/EDX yet */
2624  ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2625  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2627  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2628  else
2629  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2630 
2631  memcpy( base, code_atl4, sizeof(code_atl4) );
2632  *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func;
2633 
2634  success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2635  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2636 
2637  ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 );
2638  /* FIXME: We don't check the content of the registers EAX/ECX yet */
2639  ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2640  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2642  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2643  else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2644  ok( num_execute_fault_calls == 0 || broken(num_execute_fault_calls == 1) /* Windows XP */,
2645  "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2646  else
2647  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2648 
2649  memcpy( base, code_atl5, sizeof(code_atl5) );
2650 
2651  success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2652  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2653 
2654  ret = (DWORD_PTR)atl5_test_func;
2655  ret = call_proc_excpt( (void *)base, &ret - 1 );
2656  /* FIXME: We don't check the content of the registers EAX/ECX yet */
2657  ok( ret == 44, "call returned wrong result, expected 44, got %d\n", ret );
2658  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2660  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2661  else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2662  ok( num_execute_fault_calls == 0 || broken(num_execute_fault_calls == 1) /* Windows XP */,
2663  "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2664  else
2665  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2666 
2667  /* Restore the JMP instruction, set to executable, and then destroy the Window */
2668 
2669  memcpy( base, code_jmp, sizeof(code_jmp) );
2670  *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2671 
2673  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2674 
2675  DestroyWindow( hWnd );
2676 
2678  ok( success, "UnregisterClass failed %u\n", GetLastError() );
2679 
2680  VirtualFree( base, 0, MEM_RELEASE );
2681 
2682  /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */
2683 
2686  {
2687  win_skip( "MEM_WRITE_WATCH not supported\n" );
2688  goto out;
2689  }
2690  ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
2691 
2692  count = 64;
2693  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2694  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2695  ok( count == 0, "wrong count %lu\n", count );
2696 
2697  memcpy( base, code_jmp, sizeof(code_jmp) );
2698  *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2699 
2700  count = 64;
2701  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2702  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2703  ok( count == 1, "wrong count %lu\n", count );
2704  ok( results[0] == base, "wrong result %p\n", results[0] );
2705 
2706  /* Create a new window class and associated Window (see above) */
2707 
2709  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2710 
2711  memset( &wc, 0, sizeof(wc) );
2712  wc.cbSize = sizeof(wc);
2713  wc.style = CS_VREDRAW | CS_HREDRAW;
2714  wc.hInstance = GetModuleHandleA( 0 );
2716  wc.hbrBackground = NULL;
2717  wc.lpszClassName = cls_name;
2718  wc.lpfnWndProc = (WNDPROC)base;
2719  success = RegisterClassExA(&wc) != 0;
2720  ok( success, "RegisterClassExA failed %u\n", GetLastError() );
2721 
2722  hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2723  ok( hWnd != 0, "CreateWindowExA failed %u\n", GetLastError() );
2724 
2725  ret = SendMessageA(hWnd, WM_USER, 0, 0);
2726  ok( ret == 42, "SendMessage returned unexpected result %d\n", ret );
2727 
2728  count = 64;
2729  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2730  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2731  ok( count == 0, "wrong count %lu\n", count );
2732 
2733  /* At first try with an instruction which is not recognized as proper ATL thunk
2734  * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2735  * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2736 
2737  success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2738  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2739 
2740  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2741  ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2742  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2743  if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2744  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2745  else
2746  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2747 
2748  count = 64;
2749  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2750  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2751  ok( count == 0, "wrong count %lu\n", count );
2752 
2753  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2754  ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2755  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2756  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2757 
2758  /* Now a bit more complicated, the page containing the code is protected with
2759  * PAGE_GUARD memory protection. */
2760 
2762  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2763 
2764  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2765  ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2766  ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2767  if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
2768  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2769  else
2770  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2771 
2772  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2773  ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
2774  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2775  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2776 
2777  count = 64;
2778  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2779  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2780  ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
2781 
2782  /* Now test with a proper ATL thunk instruction. */
2783 
2784  memcpy( base, code_atl1, sizeof(code_atl1) );
2785  *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
2786 
2787  count = 64;
2788  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2789  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2790  ok( count == 1, "wrong count %lu\n", count );
2791  ok( results[0] == base, "wrong result %p\n", results[0] );
2792 
2794  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2795 
2796  ret = SendMessageA(hWnd, WM_USER, 0, 0);
2797  ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
2798 
2799  /* Try executing with PAGE_READWRITE protection. */
2800 
2801  success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
2802  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2803 
2804  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2805  ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2806  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2808  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2809  else
2810  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2811 
2812  count = 64;
2813  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2814  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2815  ok( count == 0, "wrong count %lu\n", count );
2816 
2817  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2818  ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2819  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2820  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2821 
2822  /* Now a bit more complicated, the page containing the code is protected with
2823  * PAGE_GUARD memory protection. */
2824 
2826  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2827 
2828  /* the same, but with PAGE_GUARD set */
2829  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2830  ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2831  ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2833  ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2834  else
2835  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2836 
2837  ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
2838  ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
2839  ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
2840  ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
2841 
2842  count = 64;
2843  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2844  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2845  ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
2846 
2847  /* Restore the JMP instruction, set to executable, and then destroy the Window */
2848 
2849  memcpy( base, code_jmp, sizeof(code_jmp) );
2850  *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
2851 
2852  count = 64;
2853  ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
2854  ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
2855  ok( count == 1, "wrong count %lu\n", count );
2856  ok( results[0] == base, "wrong result %p\n", results[0] );
2857 
2859  ok( success, "VirtualProtect failed %u\n", GetLastError() );
2860 
2861  DestroyWindow( hWnd );
2862 
2864  ok( success, "UnregisterClass failed %u\n", GetLastError() );
2865 
2866  VirtualFree( base, 0, MEM_RELEASE );
2867 
2868 out:
2869  if (restore_flags)
2870  {
2871  ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags) );
2872  ok( !ret, "NtSetInformationProcess failed with status %08x\n", ret );
2873  }
2874 }
2875 
2876 #endif /* __i386__ */
2877 
2878 static void test_VirtualProtect(void)
2879 {
2880  static const struct test_data
2881  {
2882  DWORD prot_set, prot_get;
2883  } td[] =
2884  {
2885  { 0, 0 }, /* 0x00 */
2886  { PAGE_NOACCESS, PAGE_NOACCESS }, /* 0x01 */
2887  { PAGE_READONLY, PAGE_READONLY }, /* 0x02 */
2888  { PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x03 */
2889  { PAGE_READWRITE, PAGE_READWRITE }, /* 0x04 */
2890  { PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x05 */
2891  { PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x06 */
2892  { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x07 */
2893  { PAGE_WRITECOPY, 0 }, /* 0x08 */
2894  { PAGE_WRITECOPY | PAGE_NOACCESS, 0 }, /* 0x09 */
2895  { PAGE_WRITECOPY | PAGE_READONLY, 0 }, /* 0x0a */
2896  { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, 0 }, /* 0x0b */
2897  { PAGE_WRITECOPY | PAGE_READWRITE, 0 }, /* 0x0c */
2898  { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x0d */
2899  { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x0e */
2900  { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x0f */
2901 
2902  { PAGE_EXECUTE, PAGE_EXECUTE }, /* 0x10 */
2903  { PAGE_EXECUTE_READ, PAGE_EXECUTE_READ }, /* 0x20 */
2904  { PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x30 */
2906  { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0x50 */
2907  { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0x60 */
2909  { PAGE_EXECUTE_WRITECOPY, 0 }, /* 0x80 */
2910  { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, 0 }, /* 0x90 */
2911  { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, 0 }, /* 0xa0 */
2913  { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, 0 }, /* 0xc0 */
2917  };
2918  char *base, *ptr;
2919  DWORD ret, old_prot, rw_prot, exec_prot, i, j;
2921  SYSTEM_INFO si;
2922  void *addr;
2923  SIZE_T size;
2924  NTSTATUS status;
2925 
2926  GetSystemInfo(&si);
2927  trace("system page size %#x\n", si.dwPageSize);
2928 
2929  SetLastError(0xdeadbeef);
2931  ok(base != NULL, "VirtualAlloc failed %d\n", GetLastError());
2932 
2933  SetLastError(0xdeadbeef);
2935  ok(!ret, "VirtualProtect should fail\n");
2936  ok(GetLastError() == ERROR_NOACCESS, "expected ERROR_NOACCESS, got %d\n", GetLastError());
2937  old_prot = 0xdeadbeef;
2938  ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
2939  ok(ret, "VirtualProtect failed %d\n", GetLastError());
2940  ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
2941 
2942  addr = base;
2943  size = si.dwPageSize;
2944  status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_READONLY, NULL);
2945  ok(status == STATUS_ACCESS_VIOLATION, "NtProtectVirtualMemory should fail, got %08x\n", status);
2946  addr = base;
2947  size = si.dwPageSize;
2948  old_prot = 0xdeadbeef;
2949  status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_NOACCESS, &old_prot);
2950  ok(status == STATUS_SUCCESS, "NtProtectVirtualMemory should succeed, got %08x\n", status);
2951  ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
2952 
2953  for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2954  {
2955  SetLastError(0xdeadbeef);
2956  ret = VirtualQuery(base, &info, sizeof(info));
2957  ok(ret, "VirtualQuery failed %d\n", GetLastError());
2958  ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
2959  ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
2960  ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect);
2961  ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
2962  ok(info.AllocationProtect == PAGE_NOACCESS, "%d: %#x != PAGE_NOACCESS\n", i, info.AllocationProtect);
2963  ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
2964  ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
2965 
2966  old_prot = 0xdeadbeef;
2967  SetLastError(0xdeadbeef);
2968  ret = VirtualProtect(base, si.dwPageSize, td[i].prot_set, &old_prot);
2969  if (td[i].prot_get)
2970  {
2971  ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
2972  ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
2973 
2974  SetLastError(0xdeadbeef);
2975  ret = VirtualQuery(base, &info, sizeof(info));
2976  ok(ret, "VirtualQuery failed %d\n", GetLastError());
2977  ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
2978  ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
2979  ok(info.Protect == td[i].prot_get, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_get);
2980  ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
2981  ok(info.AllocationProtect == PAGE_NOACCESS, "%d: %#x != PAGE_NOACCESS\n", i, info.AllocationProtect);
2982  ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
2983  ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
2984  }
2985  else
2986  {
2987  ok(!ret, "%d: VirtualProtect should fail\n", i);
2988  ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
2989  }
2990 
2991  old_prot = 0xdeadbeef;
2992  SetLastError(0xdeadbeef);
2993  ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
2994  ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
2995  if (td[i].prot_get)
2996  ok(old_prot == td[i].prot_get, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_get);
2997  else
2998  ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
2999  }
3000 
3001  exec_prot = 0;
3002 
3003  for (i = 0; i <= 4; i++)
3004  {
3005  rw_prot = 0;
3006 
3007  for (j = 0; j <= 4; j++)
3008  {
3009  DWORD prot = exec_prot | rw_prot;
3010 
3011  SetLastError(0xdeadbeef);
3012  ptr = VirtualAlloc(base, si.dwPageSize, MEM_COMMIT, prot);
3013  if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
3014  {
3015  ok(!ptr, "VirtualAlloc(%02x) should fail\n", prot);
3016  ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3017  }
3018  else
3019  {
3020  if (prot & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))
3021  {
3022  ok(!ptr, "VirtualAlloc(%02x) should fail\n", prot);
3023  ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3024  }
3025  else
3026  {
3027  ok(ptr != NULL, "VirtualAlloc(%02x) error %d\n", prot, GetLastError());
3028  ok(ptr == base, "expected %p, got %p\n", base, ptr);
3029  }
3030  }
3031 
3032  SetLastError(0xdeadbeef);
3033  ret = VirtualProtect(base, si.dwPageSize, prot, &old_prot);
3034  if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
3035  {
3036  ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
3037  ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3038  }
3039  else
3040  {
3041  if (prot & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))
3042  {
3043  ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
3044  ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3045  }
3046  else
3047  ok(ret, "VirtualProtect(%02x) error %d\n", prot, GetLastError());
3048  }
3049 
3050  rw_prot = 1 << j;
3051  }
3052 
3053  exec_prot = 1 << (i + 4);
3054  }
3055 
3057 }
3058