2 * Unit test suite for Virtual* family of APIs.
4 * Copyright 2004 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WIN32_NO_STATUS
33 #include "wine/test.h"
36 #define MAPPING_SIZE 0x100000
38 static HINSTANCE hkernel32
, hntdll
;
39 static LPVOID (WINAPI
*pVirtualAllocEx
)(HANDLE
, LPVOID
, SIZE_T
, DWORD
, DWORD
);
40 static BOOL (WINAPI
*pVirtualFreeEx
)(HANDLE
, LPVOID
, SIZE_T
, DWORD
);
41 static UINT (WINAPI
*pGetWriteWatch
)(DWORD
,LPVOID
,SIZE_T
,LPVOID
*,ULONG_PTR
*,ULONG
*);
42 static UINT (WINAPI
*pResetWriteWatch
)(LPVOID
,SIZE_T
);
43 static NTSTATUS (WINAPI
*pNtAreMappedFilesTheSame
)(PVOID
,PVOID
);
44 static NTSTATUS (WINAPI
*pNtMapViewOfSection
)(HANDLE
, HANDLE
, PVOID
*, ULONG
, SIZE_T
, const LARGE_INTEGER
*, SIZE_T
*, ULONG
, ULONG
, ULONG
);
45 static DWORD (WINAPI
*pNtUnmapViewOfSection
)(HANDLE
, PVOID
);
46 static PVOID (WINAPI
*pRtlAddVectoredExceptionHandler
)(ULONG
, PVECTORED_EXCEPTION_HANDLER
);
47 static ULONG (WINAPI
*pRtlRemoveVectoredExceptionHandler
)(PVOID
);
48 static BOOL (WINAPI
*pGetProcessDEPPolicy
)(HANDLE
, LPDWORD
, PBOOL
);
49 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
50 static NTSTATUS (WINAPI
*pNtProtectVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
, ULONG
*);
51 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG
, SIZE_T
*, ULONG
, ULONG
);
52 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
54 /* ############################### */
56 static HANDLE
create_target_process(const char *arg
)
59 char cmdline
[MAX_PATH
];
60 PROCESS_INFORMATION pi
;
62 STARTUPINFOA si
= { 0 };
65 winetest_get_mainargs( &argv
);
66 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], arg
);
67 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
68 ok(ret
, "error: %u\n", GetLastError());
69 ret
= CloseHandle(pi
.hThread
);
70 ok(ret
, "error %u\n", GetLastError());
74 static void test_VirtualAllocEx(void)
76 const unsigned int alloc_size
= 1<<15;
78 SIZE_T bytes_written
= 0, bytes_read
= 0, i
;
82 MEMORY_BASIC_INFORMATION info
;
85 /* not exported in all windows-versions */
86 if ((!pVirtualAllocEx
) || (!pVirtualFreeEx
)) {
87 win_skip("Virtual{Alloc,Free}Ex not available\n");
91 hProcess
= create_target_process("sleep");
92 ok(hProcess
!= NULL
, "Can't start process\n");
94 SetLastError(0xdeadbeef);
95 addr1
= pVirtualAllocEx(hProcess
, NULL
, alloc_size
, MEM_COMMIT
,
96 PAGE_EXECUTE_READWRITE
);
97 if (!addr1
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
99 win_skip("VirtualAllocEx not implemented\n");
100 TerminateProcess(hProcess
, 0);
101 CloseHandle(hProcess
);
105 src
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
106 dst
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
107 for (i
= 0; i
< alloc_size
; i
++)
110 ok(addr1
!= NULL
, "VirtualAllocEx error %u\n", GetLastError());
111 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
112 ok(b
&& (bytes_written
== alloc_size
), "%lu bytes written\n",
114 b
= ReadProcessMemory(hProcess
, addr1
, dst
, alloc_size
, &bytes_read
);
115 ok(b
&& (bytes_read
== alloc_size
), "%lu bytes read\n", bytes_read
);
116 ok(!memcmp(src
, dst
, alloc_size
), "Data from remote process differs\n");
118 /* test invalid source buffers */
120 b
= VirtualProtect( src
+ 0x2000, 0x2000, PAGE_NOACCESS
, &old_prot
);
121 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
122 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
123 ok( !b
, "WriteProcessMemory succeeded\n" );
124 ok( GetLastError() == ERROR_NOACCESS
||
125 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
126 "wrong error %u\n", GetLastError() );
127 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
128 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
129 ok( !b
, "ReadProcessMemory succeeded\n" );
130 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
131 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
133 b
= VirtualProtect( src
, 0x2000, PAGE_NOACCESS
, &old_prot
);
134 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
135 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
136 ok( !b
, "WriteProcessMemory succeeded\n" );
137 ok( GetLastError() == ERROR_NOACCESS
||
138 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
139 "wrong error %u\n", GetLastError() );
140 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
141 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
142 ok( !b
, "ReadProcessMemory succeeded\n" );
143 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
144 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
146 b
= pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
);
147 ok(b
!= 0, "VirtualFreeEx, error %u\n", GetLastError());
149 VirtualFree( src
, 0, MEM_RELEASE
);
150 VirtualFree( dst
, 0, MEM_RELEASE
);
153 * The following tests parallel those in test_VirtualAlloc()
156 SetLastError(0xdeadbeef);
157 addr1
= pVirtualAllocEx(hProcess
, 0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
158 ok(addr1
== NULL
, "VirtualAllocEx should fail on zero-sized allocation\n");
159 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* NT */ ||
160 GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, /* Win9x */
161 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
163 addr1
= pVirtualAllocEx(hProcess
, 0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
164 ok(addr1
!= NULL
, "VirtualAllocEx failed\n");
166 /* test a not committed memory */
167 memset(&info
, 'q', sizeof(info
));
168 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
), "VirtualQueryEx failed\n");
169 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
170 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
171 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
172 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
173 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
174 /* NT reports Protect == 0 for a not committed memory block */
175 ok(info
.Protect
== 0 /* NT */ ||
176 info
.Protect
== PAGE_NOACCESS
, /* Win9x */
177 "%x != PAGE_NOACCESS\n", info
.Protect
);
178 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
180 SetLastError(0xdeadbeef);
181 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
182 "VirtualProtectEx should fail on a not committed memory\n");
183 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
184 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
185 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
187 addr2
= pVirtualAllocEx(hProcess
, addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
188 ok(addr1
== addr2
, "VirtualAllocEx failed\n");
190 /* test a committed memory */
191 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
),
192 "VirtualQueryEx failed\n");
193 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
194 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
195 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
196 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
197 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
198 /* this time NT reports PAGE_NOACCESS as well */
199 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
200 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
202 /* this should fail, since not the whole range is committed yet */
203 SetLastError(0xdeadbeef);
204 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
205 "VirtualProtectEx should fail on a not committed memory\n");
206 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
207 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
208 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
211 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtectEx failed\n");
212 ok(old_prot
== PAGE_NOACCESS
, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
215 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtectEx failed\n");
216 ok(old_prot
== PAGE_READONLY
, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
218 ok(!pVirtualFreeEx(hProcess
, addr1
, 0x10000, 0),
219 "VirtualFreeEx should fail with type 0\n");
220 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
221 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
223 ok(pVirtualFreeEx(hProcess
, addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFreeEx failed\n");
225 /* if the type is MEM_RELEASE, size must be 0 */
226 ok(!pVirtualFreeEx(hProcess
, addr1
, 1, MEM_RELEASE
),
227 "VirtualFreeEx should fail\n");
228 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
229 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
231 ok(pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
), "VirtualFreeEx failed\n");
233 TerminateProcess(hProcess
, 0);
234 CloseHandle(hProcess
);
237 static void test_VirtualAlloc(void)
241 MEMORY_BASIC_INFORMATION info
;
245 SetLastError(0xdeadbeef);
246 addr1
= VirtualAlloc(0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
247 ok(addr1
== NULL
, "VirtualAlloc should fail on zero-sized allocation\n");
248 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* NT */ ||
249 GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, /* Win9x */
250 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
252 addr1
= VirtualAlloc(0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
253 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
255 /* test a not committed memory */
256 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
257 "VirtualQuery failed\n");
258 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
259 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
260 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
261 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
262 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
263 /* NT reports Protect == 0 for a not committed memory block */
264 ok(info
.Protect
== 0 /* NT */ ||
265 info
.Protect
== PAGE_NOACCESS
, /* Win9x */
266 "%x != PAGE_NOACCESS\n", info
.Protect
);
267 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
269 SetLastError(0xdeadbeef);
270 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
271 "VirtualProtect should fail on a not committed memory\n");
272 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
273 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
274 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
276 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
277 ok(addr1
== addr2
, "VirtualAlloc failed\n");
279 /* test a committed memory */
280 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
281 "VirtualQuery failed\n");
282 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
283 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
284 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
285 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
286 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
287 /* this time NT reports PAGE_NOACCESS as well */
288 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
289 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
291 /* this should fail, since not the whole range is committed yet */
292 SetLastError(0xdeadbeef);
293 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
294 "VirtualProtect should fail on a not committed memory\n");
295 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
296 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
297 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
299 ok(VirtualProtect(addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtect failed\n");
300 ok(old_prot
== PAGE_NOACCESS
,
301 "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
303 ok(VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtect failed\n");
304 ok(old_prot
== PAGE_READONLY
,
305 "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
307 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
308 "VirtualQuery failed\n");
309 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
310 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
311 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
312 memset( addr1
, 0x55, 20 );
313 ok( *(DWORD
*)addr1
== 0x55555555, "wrong data %x\n", *(DWORD
*)addr1
);
315 addr2
= VirtualAlloc( addr1
, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
316 ok( addr2
== addr1
|| broken( !addr2
&& GetLastError() == ERROR_INVALID_PARAMETER
), /* win9x */
317 "VirtualAlloc failed err %u\n", GetLastError() );
318 ok( *(DWORD
*)addr1
== 0x55555555 || *(DWORD
*)addr1
== 0, "wrong data %x\n", *(DWORD
*)addr1
);
321 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
322 "VirtualQuery failed\n");
323 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
324 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
325 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
327 addr2
= VirtualAlloc( (char *)addr1
+ 0x1000, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
328 ok( (char *)addr2
== (char *)addr1
+ 0x1000, "VirtualAlloc failed\n" );
330 ok(VirtualQuery(addr2
, &info
, sizeof(info
)) == sizeof(info
),
331 "VirtualQuery failed\n");
332 ok(info
.RegionSize
== 0xf000, "%lx != 0xf000\n", info
.RegionSize
);
333 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
334 ok(info
.Protect
== 0, "%x != 0\n", info
.Protect
);
336 addr2
= VirtualAlloc( (char *)addr1
+ 0xf000, 0x2000, MEM_RESET
, PAGE_NOACCESS
);
337 ok( !addr2
, "VirtualAlloc failed\n" );
338 ok( GetLastError() == ERROR_INVALID_ADDRESS
, "wrong error %u\n", GetLastError() );
341 /* invalid protection values */
342 SetLastError(0xdeadbeef);
343 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_RESERVE
, 0);
344 ok(!addr2
, "VirtualAlloc succeeded\n");
345 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
347 SetLastError(0xdeadbeef);
348 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_COMMIT
, 0);
349 ok(!addr2
, "VirtualAlloc succeeded\n");
350 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
352 SetLastError(0xdeadbeef);
353 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_READONLY
| PAGE_EXECUTE
);
354 ok(!addr2
, "VirtualAlloc succeeded\n");
355 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
357 SetLastError(0xdeadbeef);
358 ok(!VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
| PAGE_EXECUTE_WRITECOPY
, &old_prot
),
359 "VirtualProtect succeeded\n");
360 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
362 SetLastError(0xdeadbeef);
363 ok(!VirtualProtect(addr1
, 0x1000, 0, &old_prot
), "VirtualProtect succeeded\n");
364 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
366 SetLastError(0xdeadbeef);
367 ok(!VirtualFree(addr1
, 0x10000, 0), "VirtualFree should fail with type 0\n");
368 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
369 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
371 SetLastError(0xdeadbeef);
372 ok(!VirtualFree(addr1
, 0, MEM_FREE
), "VirtualFree should fail with type MEM_FREE\n");
373 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
374 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
376 ok(VirtualFree(addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFree failed\n");
378 /* if the type is MEM_RELEASE, size must be 0 */
379 ok(!VirtualFree(addr1
, 1, MEM_RELEASE
), "VirtualFree should fail\n");
380 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
381 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
383 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
385 /* memory returned by VirtualAlloc should be aligned to 64k */
386 addr1
= VirtualAlloc(0, 0x2000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
387 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
388 ok(!((ULONG_PTR
)addr1
& 0xffff), "returned memory %p is not aligned to 64k\n", addr1
);
389 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
390 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
391 ok(addr2
== addr1
, "VirtualAlloc returned %p, expected %p\n", addr2
, addr1
);
393 /* allocation conflicts because of 64k align */
395 addr2
= (char *)addr1
+ 0x1000;
396 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
,
397 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
398 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
400 /* it should conflict, even when zero_bits is explicitly set */
402 addr2
= (char *)addr1
+ 0x1000;
403 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 12, &size
,
404 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
406 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
407 if (status
== STATUS_SUCCESS
) ok(VirtualFree(addr2
, 0, MEM_RELEASE
), "VirtualFree failed\n");
409 /* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
410 SetLastError(0xdeadbeef);
411 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_RESERVE
| MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
412 ok(!addr2
, "VirtualAlloc unexpectedly succeeded\n");
413 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
415 /* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
417 addr2
= (char *)addr1
+ 0x1000;
418 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
, MEM_RESERVE
|
419 MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
421 ok(status
== STATUS_INVALID_PARAMETER_5
, "NtAllocateVirtualMemory returned %08x\n", status
);
423 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
426 static void test_MapViewOfFile(void)
428 static const char testfile
[] = "testfile.xxx";
430 HANDLE file
, mapping
, map2
;
431 void *ptr
, *ptr2
, *addr
;
432 MEMORY_BASIC_INFORMATION info
;
435 SetLastError(0xdeadbeef);
436 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
437 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
438 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
439 SetEndOfFile( file
);
441 /* read/write mapping */
443 SetLastError(0xdeadbeef);
444 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
445 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
447 SetLastError(0xdeadbeef);
448 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
449 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAPE_READ error %u\n", GetLastError() );
450 UnmapViewOfFile( ptr
);
452 /* this fails on win9x but succeeds on NT */
453 SetLastError(0xdeadbeef);
454 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
455 if (ptr
) UnmapViewOfFile( ptr
);
456 else ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
458 SetLastError(0xdeadbeef);
459 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
460 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
461 UnmapViewOfFile( ptr
);
463 SetLastError(0xdeadbeef);
464 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
465 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
466 UnmapViewOfFile( ptr
);
468 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
469 FILE_MAP_READ
|FILE_MAP_WRITE
, FALSE
, 0 );
470 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
471 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
472 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
473 UnmapViewOfFile( ptr
);
476 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
477 FILE_MAP_READ
, FALSE
, 0 );
478 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
479 SetLastError(0xdeadbeef);
480 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
483 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
485 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
, 0, FALSE
, 0 );
486 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
487 SetLastError(0xdeadbeef);
488 ptr
= MapViewOfFile( map2
, 0, 0, 0, 4096 );
489 ok( !ptr
, "MapViewOfFile succeeded\n" );
490 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
492 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
493 FILE_MAP_READ
, FALSE
, 0 );
494 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
495 ptr
= MapViewOfFile( map2
, 0, 0, 0, 4096 );
496 ok( ptr
!= NULL
, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
498 else win_skip( "no access checks on win9x\n" );
500 UnmapViewOfFile( ptr
);
502 CloseHandle( mapping
);
504 /* read-only mapping */
506 SetLastError(0xdeadbeef);
507 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
508 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
510 SetLastError(0xdeadbeef);
511 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
512 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
513 UnmapViewOfFile( ptr
);
515 /* this fails on win9x but succeeds on NT */
516 SetLastError(0xdeadbeef);
517 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
518 if (ptr
) UnmapViewOfFile( ptr
);
519 else ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
521 SetLastError(0xdeadbeef);
522 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
523 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
524 UnmapViewOfFile( ptr
);
526 SetLastError(0xdeadbeef);
527 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
528 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
529 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
530 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
531 CloseHandle( mapping
);
533 /* copy-on-write mapping */
535 SetLastError(0xdeadbeef);
536 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
537 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
539 SetLastError(0xdeadbeef);
540 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
541 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
542 UnmapViewOfFile( ptr
);
544 SetLastError(0xdeadbeef);
545 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
546 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
547 UnmapViewOfFile( ptr
);
549 SetLastError(0xdeadbeef);
550 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
551 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
552 UnmapViewOfFile( ptr
);
554 SetLastError(0xdeadbeef);
555 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
556 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
557 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
558 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
559 CloseHandle( mapping
);
561 /* no access mapping */
563 SetLastError(0xdeadbeef);
564 mapping
= CreateFileMappingA( file
, NULL
, PAGE_NOACCESS
, 0, 4096, NULL
);
565 /* fails on NT but succeeds on win9x */
566 if (!mapping
) ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
569 SetLastError(0xdeadbeef);
570 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
571 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
572 UnmapViewOfFile( ptr
);
574 SetLastError(0xdeadbeef);
575 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
576 ok( !ptr
, "MapViewOfFile FILE_MAP_COPY succeeded\n" );
577 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
579 SetLastError(0xdeadbeef);
580 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
581 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
582 UnmapViewOfFile( ptr
);
584 SetLastError(0xdeadbeef);
585 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
586 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
587 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
589 CloseHandle( mapping
);
594 /* now try read-only file */
596 SetLastError(0xdeadbeef);
597 file
= CreateFileA( testfile
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0 );
598 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
600 SetLastError(0xdeadbeef);
601 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
602 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
603 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
604 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
606 SetLastError(0xdeadbeef);
607 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
608 ok( mapping
!= 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
609 CloseHandle( mapping
);
611 SetLastError(0xdeadbeef);
612 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
613 ok( mapping
!= 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
614 CloseHandle( mapping
);
617 /* now try no access file */
619 SetLastError(0xdeadbeef);
620 file
= CreateFileA( testfile
, 0, 0, NULL
, OPEN_EXISTING
, 0, 0 );
621 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
623 SetLastError(0xdeadbeef);
624 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
625 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
626 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
627 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
629 SetLastError(0xdeadbeef);
630 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
631 ok( !mapping
, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
632 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
633 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
635 SetLastError(0xdeadbeef);
636 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
637 ok( !mapping
, "CreateFileMapping PAGE_READONLY succeeded\n" );
638 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
639 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
642 DeleteFileA( testfile
);
644 SetLastError(0xdeadbeef);
646 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, name
);
647 /* nt4 doesn't have Local\\ */
648 if (!file
&& GetLastError() == ERROR_PATH_NOT_FOUND
)
651 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, name
);
653 ok( file
!= 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
655 SetLastError(0xdeadbeef);
656 mapping
= OpenFileMappingA( FILE_MAP_READ
, FALSE
, name
);
657 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
658 SetLastError(0xdeadbeef);
659 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
663 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
664 SetLastError(0xdeadbeef);
665 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
666 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
667 SetLastError(0xdeadbeef);
668 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
669 ok( size
== sizeof(info
),
670 "VirtualQuery error %u\n", GetLastError() );
671 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
672 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
673 ok( info
.AllocationProtect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.AllocationProtect
);
674 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
675 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
676 ok( info
.Protect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.Protect
);
678 else win_skip( "no access checks on win9x\n" );
679 UnmapViewOfFile( ptr
);
680 CloseHandle( mapping
);
682 SetLastError(0xdeadbeef);
683 mapping
= OpenFileMappingA( FILE_MAP_WRITE
, FALSE
, name
);
684 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
685 SetLastError(0xdeadbeef);
686 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
690 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
691 SetLastError(0xdeadbeef);
692 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
693 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
694 SetLastError(0xdeadbeef);
695 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
696 ok( size
== sizeof(info
),
697 "VirtualQuery error %u\n", GetLastError() );
698 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
699 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
700 ok( info
.AllocationProtect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.AllocationProtect
);
701 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
702 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
703 ok( info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
705 else win_skip( "no access checks on win9x\n" );
706 UnmapViewOfFile( ptr
);
707 CloseHandle( mapping
);
711 /* read/write mapping with SEC_RESERVE */
712 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
| SEC_RESERVE
, 0, MAPPING_SIZE
, NULL
);
713 ok(mapping
!= INVALID_HANDLE_VALUE
, "CreateFileMappingA failed with error %d\n", GetLastError());
715 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
716 ok(ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
718 ptr2
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
719 /* on NT ptr != ptr2 but on Win9x ptr == ptr2 */
720 ok(ptr2
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
721 trace("mapping same section resulted in views %p and %p\n", ptr
, ptr2
);
723 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
724 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
725 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
726 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
727 ok(info
.RegionSize
== MAPPING_SIZE
, "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
728 ok(info
.State
== MEM_RESERVE
, "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
729 if (info
.Type
== MEM_PRIVATE
) /* win9x is different for uncommitted mappings */
731 ok(info
.AllocationProtect
== PAGE_NOACCESS
,
732 "AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info
.AllocationProtect
);
733 ok(info
.Protect
== PAGE_NOACCESS
,
734 "Protect should have been PAGE_NOACCESS instead of 0x%x\n", info
.Protect
);
738 ok(info
.AllocationProtect
== PAGE_READWRITE
,
739 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
740 ok(info
.Protect
== 0, "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
741 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
746 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
747 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
748 ok(info
.BaseAddress
== ptr2
,
749 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
750 ok(info
.AllocationBase
== ptr2
,
751 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
752 ok(info
.AllocationProtect
== PAGE_READWRITE
,
753 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
754 ok(info
.RegionSize
== MAPPING_SIZE
,
755 "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
756 ok(info
.State
== MEM_RESERVE
,
757 "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
758 ok(info
.Protect
== 0,
759 "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
760 ok(info
.Type
== MEM_MAPPED
,
761 "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
764 ptr
= VirtualAlloc(ptr
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
765 ok(ptr
!= NULL
, "VirtualAlloc failed with error %d\n", GetLastError());
767 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
768 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
769 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
770 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
771 ok(info
.RegionSize
== 0x10000, "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
772 ok(info
.State
== MEM_COMMIT
, "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
773 ok(info
.Protect
== PAGE_READONLY
, "Protect should have been PAGE_READONLY instead of 0x%x\n", info
.Protect
);
774 if (info
.Type
== MEM_PRIVATE
) /* win9x is different for uncommitted mappings */
776 ok(info
.AllocationProtect
== PAGE_NOACCESS
,
777 "AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info
.AllocationProtect
);
781 ok(info
.AllocationProtect
== PAGE_READWRITE
,
782 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
783 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
786 /* shows that the VirtualAlloc above affects the mapping, not just the
787 * virtual memory in this process - it also affects all other processes
788 * with a view of the mapping, but that isn't tested here */
791 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
792 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
793 ok(info
.BaseAddress
== ptr2
,
794 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
795 ok(info
.AllocationBase
== ptr2
,
796 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
797 ok(info
.AllocationProtect
== PAGE_READWRITE
,
798 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
799 ok(info
.RegionSize
== 0x10000,
800 "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
801 ok(info
.State
== MEM_COMMIT
,
802 "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
803 ok(info
.Protect
== PAGE_READWRITE
,
804 "Protect should have been PAGE_READWRITE instead of 0x%x\n", info
.Protect
);
805 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
808 addr
= VirtualAlloc( ptr
, MAPPING_SIZE
, MEM_RESET
, PAGE_READONLY
);
809 ok( addr
== ptr
|| broken(!addr
&& GetLastError() == ERROR_INVALID_PARAMETER
), /* win9x */
810 "VirtualAlloc failed with error %u\n", GetLastError() );
812 ret
= VirtualFree( ptr
, 0x10000, MEM_DECOMMIT
);
813 ok( !ret
|| broken(ret
) /* win9x */, "VirtualFree succeeded\n" );
815 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "VirtualFree failed with %u\n", GetLastError() );
817 ret
= UnmapViewOfFile(ptr2
);
818 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
819 ret
= UnmapViewOfFile(ptr
);
820 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
821 CloseHandle(mapping
);
823 addr
= VirtualAlloc(NULL
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
824 ok( addr
!= NULL
, "VirtualAlloc failed with error %u\n", GetLastError() );
826 SetLastError(0xdeadbeef);
827 ok( !UnmapViewOfFile(addr
), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
828 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
829 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
830 SetLastError(0xdeadbeef);
831 ok( !UnmapViewOfFile((char *)addr
+ 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
832 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
833 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
834 SetLastError(0xdeadbeef);
835 ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
836 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
837 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
839 ok( VirtualFree(addr
, 0, MEM_RELEASE
), "VirtualFree failed\n" );
841 /* close named mapping handle without unmapping */
843 SetLastError(0xdeadbeef);
844 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
845 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
846 SetLastError(0xdeadbeef);
847 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
848 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
849 SetLastError(0xdeadbeef);
850 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
851 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
852 SetLastError(0xdeadbeef);
853 ret
= CloseHandle(map2
);
854 ok(ret
, "CloseHandle error %d\n", GetLastError());
855 SetLastError(0xdeadbeef);
856 ret
= CloseHandle(mapping
);
857 ok(ret
, "CloseHandle error %d\n", GetLastError());
859 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
860 ok( !ret
, "memory is not accessible\n" );
862 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
863 ok(ret
, "VirtualQuery error %d\n", GetLastError());
864 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
865 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
866 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
867 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
868 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
869 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
870 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
872 SetLastError(0xdeadbeef);
873 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
875 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
877 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
878 if (map2
) CloseHandle(map2
); /* FIXME: remove once Wine is fixed */
879 SetLastError(0xdeadbeef);
880 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
881 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
883 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set error %d\n", GetLastError() );
884 SetLastError(0xdeadbeef);
885 ret
= CloseHandle(mapping
);
886 ok(ret
, "CloseHandle error %d\n", GetLastError());
888 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
889 ok( !ret
, "memory is not accessible\n" );
891 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
892 ok(ret
, "VirtualQuery error %d\n", GetLastError());
893 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
894 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
895 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
896 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
897 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
898 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
899 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
901 SetLastError(0xdeadbeef);
902 ret
= UnmapViewOfFile(ptr
);
903 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
905 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
906 ok( ret
, "memory is accessible\n" );
908 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
909 ok(ret
, "VirtualQuery error %d\n", GetLastError());
910 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
911 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
912 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
913 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
914 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
915 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
917 SetLastError(0xdeadbeef);
918 file
= CreateFileA(testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
919 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
920 SetFilePointer(file
, 4096, NULL
, FILE_BEGIN
);
923 SetLastError(0xdeadbeef);
924 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
925 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
926 SetLastError(0xdeadbeef);
927 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
928 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
929 SetLastError(0xdeadbeef);
930 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
931 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
932 SetLastError(0xdeadbeef);
933 ret
= CloseHandle(map2
);
934 ok(ret
, "CloseHandle error %d\n", GetLastError());
935 SetLastError(0xdeadbeef);
936 ret
= CloseHandle(mapping
);
937 ok(ret
, "CloseHandle error %d\n", GetLastError());
939 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
940 ok( !ret
, "memory is not accessible\n" );
942 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
943 ok(ret
, "VirtualQuery error %d\n", GetLastError());
944 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
945 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
946 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
947 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
948 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
949 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
950 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
952 SetLastError(0xdeadbeef);
953 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
955 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
957 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
959 SetLastError(0xdeadbeef);
960 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
961 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
963 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set error %d\n", GetLastError() );
964 SetLastError(0xdeadbeef);
965 ret
= CloseHandle(mapping
);
966 ok(ret
, "CloseHandle error %d\n", GetLastError());
968 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
969 ok( !ret
, "memory is not accessible\n" );
971 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
972 ok(ret
, "VirtualQuery error %d\n", GetLastError());
973 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
974 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
975 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
976 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
977 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
978 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
979 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
981 SetLastError(0xdeadbeef);
982 ret
= UnmapViewOfFile(ptr
);
983 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
985 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
986 ok( ret
, "memory is accessible\n" );
988 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
989 ok(ret
, "VirtualQuery error %d\n", GetLastError());
990 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
991 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
992 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
993 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
994 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
995 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
998 DeleteFileA(testfile
);
1001 static void test_NtMapViewOfSection(void)
1005 static const char testfile
[] = "testfile.xxx";
1006 static const char data
[] = "test data for NtMapViewOfSection";
1007 char buffer
[sizeof(data
)];
1008 HANDLE file
, mapping
;
1011 DWORD status
, written
;
1012 SIZE_T size
, result
;
1013 LARGE_INTEGER offset
;
1015 if (!pNtMapViewOfSection
|| !pNtUnmapViewOfSection
)
1017 win_skip( "NtMapViewOfSection not available\n" );
1021 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1022 ok( file
!= INVALID_HANDLE_VALUE
, "Failed to create test file\n" );
1023 WriteFile( file
, data
, sizeof(data
), &written
, NULL
);
1024 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1025 SetEndOfFile( file
);
1027 /* read/write mapping */
1029 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1030 ok( mapping
!= 0, "CreateFileMapping failed\n" );
1032 hProcess
= create_target_process("sleep");
1033 ok(hProcess
!= NULL
, "Can't start process\n");
1037 offset
.QuadPart
= 0;
1038 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1039 ok( !status
, "NtMapViewOfSection failed status %x\n", status
);
1040 ok( !((ULONG_PTR
)ptr
& 0xffff), "returned memory %p is not aligned to 64k\n", ptr
);
1042 ret
= ReadProcessMemory( hProcess
, ptr
, buffer
, sizeof(buffer
), &result
);
1043 ok( ret
, "ReadProcessMemory failed\n" );
1044 ok( result
== sizeof(buffer
), "ReadProcessMemory didn't read all data (%lx)\n", result
);
1045 ok( !memcmp( buffer
, data
, sizeof(buffer
) ), "Wrong data read\n" );
1047 /* for some unknown reason NtMapViewOfSection fails with STATUS_NO_MEMORY when zero_bits != 0 ? */
1050 offset
.QuadPart
= 0;
1051 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1053 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1054 if (status
== STATUS_SUCCESS
)
1056 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1057 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1062 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1064 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1065 if (status
== STATUS_SUCCESS
)
1067 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1068 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1071 /* mapping at the same page conflicts */
1074 offset
.QuadPart
= 0;
1075 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1076 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1078 /* offset has to be aligned */
1081 offset
.QuadPart
= 1;
1082 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1083 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1085 /* ptr has to be aligned */
1086 ptr2
= (char *)ptr
+ 42;
1088 offset
.QuadPart
= 0;
1089 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1090 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1092 /* still not 64k aligned */
1093 ptr2
= (char *)ptr
+ 0x1000;
1095 offset
.QuadPart
= 0;
1096 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1097 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1099 /* zero_bits != 0 is not allowed when an address is set */
1100 ptr2
= (char *)ptr
+ 0x1000;
1102 offset
.QuadPart
= 0;
1103 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1104 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1106 ptr2
= (char *)ptr
+ 0x1000;
1108 offset
.QuadPart
= 0;
1109 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1110 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1112 ptr2
= (char *)ptr
+ 0x1001;
1114 offset
.QuadPart
= 0;
1115 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1116 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1118 ptr2
= (char *)ptr
+ 0x1000;
1120 offset
.QuadPart
= 1;
1121 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1122 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1124 if (sizeof(void *) == sizeof(int) && (!pIsWow64Process
||
1125 !pIsWow64Process( GetCurrentProcess(), &is_wow64
) || !is_wow64
))
1127 /* new memory region conflicts with previous mapping */
1130 offset
.QuadPart
= 0;
1131 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1132 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1133 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1135 ptr2
= (char *)ptr
+ 42;
1137 offset
.QuadPart
= 0;
1138 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1139 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1140 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1142 /* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
1143 ptr2
= (char *)ptr
+ 0x1000;
1145 offset
.QuadPart
= 0;
1146 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1147 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1148 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1149 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1150 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1151 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1152 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1154 /* the address is rounded down if not on a page boundary */
1155 ptr2
= (char *)ptr
+ 0x1001;
1157 offset
.QuadPart
= 0;
1158 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1159 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1160 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1161 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1162 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1163 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1164 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1166 ptr2
= (char *)ptr
+ 0x2000;
1168 offset
.QuadPart
= 0;
1169 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1170 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1171 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1172 ok( (char *)ptr2
== (char *)ptr
+ 0x2000,
1173 "expected address %p, got %p\n", (char *)ptr
+ 0x2000, ptr2
);
1174 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1175 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1179 ptr2
= (char *)ptr
+ 0x1000;
1181 offset
.QuadPart
= 0;
1182 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1183 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1185 ok( status
== STATUS_INVALID_PARAMETER_9
, "NtMapViewOfSection returned %x\n", status
);
1188 status
= pNtUnmapViewOfSection( hProcess
, ptr
);
1189 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1191 CloseHandle( mapping
);
1192 CloseHandle( file
);
1193 DeleteFileA( testfile
);
1195 TerminateProcess(hProcess
, 0);
1196 CloseHandle(hProcess
);
1199 static void test_NtAreMappedFilesTheSame(void)
1201 static const char testfile
[] = "testfile.xxx";
1202 HANDLE file
, file2
, mapping
, map2
;
1205 char path
[MAX_PATH
];
1207 if (!pNtAreMappedFilesTheSame
)
1209 win_skip( "NtAreMappedFilesTheSame not available\n" );
1213 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1214 NULL
, CREATE_ALWAYS
, 0, 0 );
1215 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1216 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1217 SetEndOfFile( file
);
1219 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1220 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1222 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1223 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1225 file2
= CreateFileA( testfile
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1226 NULL
, OPEN_EXISTING
, 0, 0 );
1227 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1229 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1230 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1231 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1232 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1233 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1234 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1235 UnmapViewOfFile( ptr2
);
1237 ptr2
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1238 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1239 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1240 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1241 UnmapViewOfFile( ptr2
);
1242 CloseHandle( map2
);
1244 map2
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1245 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1246 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1247 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1248 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1249 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1250 UnmapViewOfFile( ptr2
);
1251 CloseHandle( map2
);
1252 CloseHandle( file2
);
1254 status
= pNtAreMappedFilesTheSame( ptr
, ptr
);
1255 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1256 "NtAreMappedFilesTheSame returned %x\n", status
);
1258 status
= pNtAreMappedFilesTheSame( ptr
, (char *)ptr
+ 30 );
1259 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1260 "NtAreMappedFilesTheSame returned %x\n", status
);
1262 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1263 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1265 status
= pNtAreMappedFilesTheSame( ptr
, (void *)0xdeadbeef );
1266 ok( status
== STATUS_CONFLICTING_ADDRESSES
|| status
== STATUS_INVALID_ADDRESS
,
1267 "NtAreMappedFilesTheSame returned %x\n", status
);
1269 status
= pNtAreMappedFilesTheSame( ptr
, NULL
);
1270 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1272 status
= pNtAreMappedFilesTheSame( ptr
, (void *)GetProcessHeap() );
1273 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1275 status
= pNtAreMappedFilesTheSame( NULL
, NULL
);
1276 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1278 ptr2
= VirtualAlloc( NULL
, 0x10000, MEM_COMMIT
, PAGE_READWRITE
);
1279 ok( ptr2
!= NULL
, "VirtualAlloc error %u\n", GetLastError() );
1280 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1281 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1282 VirtualFree( ptr2
, 0, MEM_RELEASE
);
1284 UnmapViewOfFile( ptr
);
1285 CloseHandle( mapping
);
1286 CloseHandle( file
);
1288 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
1289 GetModuleHandleA("kernel32.dll") );
1290 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1291 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1292 GetModuleHandleA("kernel32.dll") );
1293 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1294 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1295 (char *)GetModuleHandleA("kernel32.dll") + 4096 );
1296 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1298 GetSystemDirectoryA( path
, MAX_PATH
);
1299 strcat( path
, "\\kernel32.dll" );
1300 file
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1301 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1303 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1304 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1305 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1306 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1307 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1308 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1309 UnmapViewOfFile( ptr
);
1310 CloseHandle( mapping
);
1312 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1313 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1314 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
1315 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1316 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1318 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1320 file2
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1321 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1322 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1323 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1324 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 0 );
1325 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1326 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1327 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1328 UnmapViewOfFile( ptr2
);
1329 CloseHandle( map2
);
1330 CloseHandle( file2
);
1332 UnmapViewOfFile( ptr
);
1333 CloseHandle( mapping
);
1335 CloseHandle( file
);
1336 DeleteFileA( testfile
);
1339 static void test_CreateFileMapping(void)
1341 HANDLE handle
, handle2
;
1343 /* test case sensitivity */
1345 SetLastError(0xdeadbeef);
1346 handle
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1347 "Wine Test Mapping");
1348 ok( handle
!= NULL
, "CreateFileMapping failed with error %u\n", GetLastError());
1349 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1351 SetLastError(0xdeadbeef);
1352 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1353 "Wine Test Mapping");
1354 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1355 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
1356 CloseHandle( handle2
);
1358 SetLastError(0xdeadbeef);
1359 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1360 "WINE TEST MAPPING");
1361 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1362 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1363 CloseHandle( handle2
);
1365 SetLastError(0xdeadbeef);
1366 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "Wine Test Mapping");
1367 ok( handle2
!= NULL
, "OpenFileMapping failed with error %d\n", GetLastError());
1368 CloseHandle( handle2
);
1370 SetLastError(0xdeadbeef);
1371 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "WINE TEST MAPPING");
1372 ok( !handle2
, "OpenFileMapping succeeded\n");
1373 ok( GetLastError() == ERROR_FILE_NOT_FOUND
|| GetLastError() == ERROR_INVALID_NAME
/* win9x */,
1374 "wrong error %u\n", GetLastError());
1376 CloseHandle( handle
);
1379 static void test_IsBadReadPtr(void)
1382 void *ptr
= (void *)0xdeadbeef;
1385 ret
= IsBadReadPtr(NULL
, 0);
1386 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1388 ret
= IsBadReadPtr(NULL
, 1);
1389 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1391 ret
= IsBadReadPtr(ptr
, 0);
1392 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1394 ret
= IsBadReadPtr(ptr
, 1);
1395 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1397 ret
= IsBadReadPtr(&stackvar
, 0);
1398 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1400 ret
= IsBadReadPtr(&stackvar
, sizeof(char));
1401 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1404 static void test_IsBadWritePtr(void)
1407 void *ptr
= (void *)0xdeadbeef;
1410 ret
= IsBadWritePtr(NULL
, 0);
1411 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1413 ret
= IsBadWritePtr(NULL
, 1);
1414 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1416 ret
= IsBadWritePtr(ptr
, 0);
1417 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1419 ret
= IsBadWritePtr(ptr
, 1);
1420 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1422 ret
= IsBadWritePtr(&stackval
, 0);
1423 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1425 ret
= IsBadWritePtr(&stackval
, sizeof(char));
1426 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1429 static void test_IsBadCodePtr(void)
1432 void *ptr
= (void *)0xdeadbeef;
1435 ret
= IsBadCodePtr(NULL
);
1436 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1438 ret
= IsBadCodePtr(ptr
);
1439 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1441 ret
= IsBadCodePtr((void *)&stackval
);
1442 ok(ret
== FALSE
, "Expected IsBadCodePtr to return FALSE, got %d\n", ret
);
1445 static void test_write_watch(void)
1447 static const char pipename
[] = "\\\\.\\pipe\\test_write_watch_pipe";
1448 static const char testdata
[] = "Hello World";
1449 DWORD ret
, size
, old_prot
, num_bytes
;
1450 MEMORY_BASIC_INFORMATION info
;
1451 HANDLE readpipe
, writepipe
;
1452 OVERLAPPED overlapped
;
1459 if (!pGetWriteWatch
|| !pResetWriteWatch
)
1461 win_skip( "GetWriteWatch not supported\n" );
1466 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1468 (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
1470 win_skip( "MEM_WRITE_WATCH not supported\n" );
1473 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1474 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1475 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1476 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1477 ok( info
.AllocationProtect
== PAGE_READWRITE
, "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1478 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1479 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1480 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1481 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1484 SetLastError( 0xdeadbeef );
1485 ret
= pGetWriteWatch( 0, NULL
, size
, results
, &count
, &pagesize
);
1486 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1487 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
1488 broken( GetLastError() == 0xdeadbeef ), /* win98 */
1489 "wrong error %u\n", GetLastError() );
1491 SetLastError( 0xdeadbeef );
1492 ret
= pGetWriteWatch( 0, GetModuleHandleW(NULL
), size
, results
, &count
, &pagesize
);
1495 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1496 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1500 ok( count
== 0, "wrong count %lu\n", count
);
1503 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1504 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1505 ok( count
== 0, "wrong count %lu\n", count
);
1507 base
[pagesize
+ 1] = 0x44;
1510 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1511 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1512 ok( count
== 1, "wrong count %lu\n", count
);
1513 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1516 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1517 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1518 ok( count
== 1, "wrong count %lu\n", count
);
1519 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1522 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1523 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1524 ok( count
== 0, "wrong count %lu\n", count
);
1526 base
[2*pagesize
+ 3] = 0x11;
1527 base
[4*pagesize
+ 8] = 0x11;
1530 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1531 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1532 ok( count
== 2, "wrong count %lu\n", count
);
1533 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1534 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1537 ret
= pGetWriteWatch( 0, base
+ 3*pagesize
, 2*pagesize
, results
, &count
, &pagesize
);
1538 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1539 ok( count
== 1, "wrong count %lu\n", count
);
1540 ok( results
[0] == base
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1542 ret
= pResetWriteWatch( base
, 3*pagesize
);
1543 ok( !ret
, "pResetWriteWatch failed %u\n", GetLastError() );
1546 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1547 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1548 ok( count
== 1, "wrong count %lu\n", count
);
1549 ok( results
[0] == base
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1551 *(DWORD
*)(base
+ 2*pagesize
- 2) = 0xdeadbeef;
1554 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1555 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1556 ok( count
== 3, "wrong count %lu\n", count
);
1557 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1558 ok( results
[1] == base
+ 2*pagesize
, "wrong result %p\n", results
[1] );
1559 ok( results
[2] == base
+ 4*pagesize
, "wrong result %p\n", results
[2] );
1562 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1563 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1564 ok( count
== 1, "wrong count %lu\n", count
);
1565 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1568 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1569 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1570 ok( count
== 2, "wrong count %lu\n", count
);
1571 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1572 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1574 /* changing protections doesn't affect watches */
1576 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READONLY
, &old_prot
);
1577 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1578 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1580 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1581 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1582 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1583 ok( info
.RegionSize
== 3*pagesize
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1584 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1585 ok( info
.Protect
== PAGE_READONLY
, "wrong Protect 0x%x\n", info
.Protect
);
1587 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READWRITE
, &old_prot
);
1588 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1589 ok( old_prot
== PAGE_READONLY
, "wrong old prot %x\n", old_prot
);
1592 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1593 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1594 ok( count
== 2, "wrong count %lu\n", count
);
1595 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1596 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1598 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1599 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1600 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1601 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1602 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1603 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1605 /* ReadFile should trigger write watches */
1607 memset( &overlapped
, 0, sizeof(overlapped
) );
1608 overlapped
.hEvent
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1610 readpipe
= CreateNamedPipeA( pipename
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_INBOUND
,
1611 PIPE_TYPE_BYTE
| PIPE_WAIT
, 1, 1024, 1024,
1612 NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1613 ok( readpipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipeA failed %u\n", GetLastError() );
1615 success
= ConnectNamedPipe( readpipe
, &overlapped
);
1616 ok( !success
, "ConnectNamedPipe unexpectedly succeeded\n" );
1617 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1619 writepipe
= CreateFileA( pipename
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
1620 ok( writepipe
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %u\n", GetLastError() );
1622 ret
= WaitForSingleObject( overlapped
.hEvent
, 1000 );
1623 ok( ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", ret
);
1625 memset( base
, 0, size
);
1628 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1629 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1630 ok( count
== 16, "wrong count %lu\n", count
);
1632 success
= ReadFile( readpipe
, base
, size
, NULL
, &overlapped
);
1633 ok( !success
, "ReadFile unexpectedly succeeded\n" );
1634 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1637 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1638 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1639 ok( count
== 16, "wrong count %lu\n", count
);
1642 success
= WriteFile( writepipe
, testdata
, sizeof(testdata
), &num_bytes
, NULL
);
1643 ok( success
, "WriteFile failed %u\n", GetLastError() );
1644 ok( num_bytes
== sizeof(testdata
), "wrong number of bytes written\n" );
1647 success
= GetOverlappedResult( readpipe
, &overlapped
, &num_bytes
, TRUE
);
1648 todo_wine
ok( success
, "GetOverlappedResult failed %u\n", GetLastError() );
1649 todo_wine
ok( num_bytes
== sizeof(testdata
), "wrong number of bytes read\n" );
1650 todo_wine
ok( !memcmp( base
, testdata
, sizeof(testdata
)), "didn't receive expected data\n" );
1653 memset( results
, 0, sizeof(results
) );
1654 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1655 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1656 todo_wine
ok( count
== 1, "wrong count %lu\n", count
);
1657 todo_wine
ok( results
[0] == base
, "wrong result %p\n", results
[0] );
1659 CloseHandle( readpipe
);
1660 CloseHandle( writepipe
);
1661 CloseHandle( overlapped
.hEvent
);
1663 /* some invalid parameter tests */
1665 SetLastError( 0xdeadbeef );
1667 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1670 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1671 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1673 SetLastError( 0xdeadbeef );
1674 ret
= pGetWriteWatch( 0, base
, size
, results
, NULL
, &pagesize
);
1675 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1676 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1678 SetLastError( 0xdeadbeef );
1680 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, NULL
);
1681 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1682 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1684 SetLastError( 0xdeadbeef );
1686 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1687 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1688 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1690 SetLastError( 0xdeadbeef );
1692 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1693 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1694 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1696 SetLastError( 0xdeadbeef );
1698 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1699 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1700 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1702 SetLastError( 0xdeadbeef );
1704 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1705 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1706 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1708 SetLastError( 0xdeadbeef );
1710 ret
= pGetWriteWatch( 0, base
, size
* 2, results
, &count
, &pagesize
);
1711 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1712 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1714 SetLastError( 0xdeadbeef );
1716 ret
= pGetWriteWatch( 0, base
+ size
- pagesize
, pagesize
+ 1, results
, &count
, &pagesize
);
1717 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1718 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1720 SetLastError( 0xdeadbeef );
1721 ret
= pResetWriteWatch( base
, 0 );
1722 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1723 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1725 SetLastError( 0xdeadbeef );
1726 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1727 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1728 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1730 else /* win98 is completely different */
1732 SetLastError( 0xdeadbeef );
1734 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1735 ok( ret
== ERROR_INVALID_PARAMETER
, "GetWriteWatch succeeded %u\n", ret
);
1736 ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
1739 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1740 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1743 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1744 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1747 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1748 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1750 ret
= pResetWriteWatch( base
, 0 );
1751 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1753 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1754 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1757 VirtualFree( base
, 0, MEM_RELEASE
);
1759 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1760 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1761 VirtualFree( base
, 0, MEM_RELEASE
);
1763 base
= VirtualAlloc( 0, size
, MEM_WRITE_WATCH
, PAGE_READWRITE
);
1764 ok( !base
, "VirtualAlloc succeeded\n" );
1765 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1767 /* initial protect doesn't matter */
1769 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_NOACCESS
);
1770 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1771 base
= VirtualAlloc( base
, size
, MEM_COMMIT
, PAGE_NOACCESS
);
1772 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1775 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1776 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1777 ok( count
== 0, "wrong count %lu\n", count
);
1779 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_READWRITE
, &old_prot
);
1780 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1781 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
1783 base
[5*pagesize
+ 200] = 3;
1785 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_NOACCESS
, &old_prot
);
1786 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1787 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1790 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1791 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1792 ok( count
== 1, "wrong count %lu\n", count
);
1793 ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1795 ret
= VirtualFree( base
, size
, MEM_DECOMMIT
);
1796 ok( ret
, "VirtualFree failed %u\n", GetLastError() );
1799 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1800 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1801 ok( count
== 1 || broken(count
== 0), /* win98 */
1802 "wrong count %lu\n", count
);
1803 if (count
) ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1805 VirtualFree( base
, 0, MEM_RELEASE
);
1808 #if defined(__i386__) || defined(__x86_64__)
1810 static DWORD WINAPI
stack_commit_func( void *arg
)
1812 volatile char *p
= (char *)&p
;
1814 /* trigger all guard pages, to ensure that the pages are committed */
1815 while (p
>= (char *)NtCurrentTeb()->DeallocationStack
+ 4 * 0x1000)
1821 ok( arg
== (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg
);
1825 static void test_stack_commit(void)
1828 static const char code_call_on_stack
[] = {
1829 0x55, /* pushl %ebp */
1830 0x56, /* pushl %esi */
1831 0x89, 0xe6, /* movl %esp,%esi */
1832 0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */
1833 0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */
1834 0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */
1835 0x83, 0xe0, 0xf0, /* andl $~15,%eax */
1836 0x83, 0xe8, 0x0c, /* subl $12,%eax */
1837 0x89, 0xc4, /* movl %eax,%esp */
1838 0x52, /* pushl %edx */
1839 0x31, 0xed, /* xorl %ebp,%ebp */
1840 0xff, 0xd1, /* call *%ecx */
1841 0x89, 0xf4, /* movl %esi,%esp */
1842 0x5e, /* popl %esi */
1843 0x5d, /* popl %ebp */
1844 0xc2, 0x0c, 0x00 }; /* ret $12 */
1846 static const char code_call_on_stack
[] = {
1847 0x55, /* pushq %rbp */
1848 0x48, 0x89, 0xe5, /* movq %rsp,%rbp */
1849 /* %rcx - func, %rdx - arg, %r8 - stack */
1850 0x48, 0x87, 0xca, /* xchgq %rcx,%rdx */
1851 0x49, 0x83, 0xe0, 0xf0, /* andq $~15,%r8 */
1852 0x49, 0x83, 0xe8, 0x20, /* subq $0x20,%r8 */
1853 0x4c, 0x89, 0xc4, /* movq %r8,%rsp */
1854 0xff, 0xd2, /* callq *%rdx */
1855 0x48, 0x89, 0xec, /* movq %rbp,%rsp */
1856 0x5d, /* popq %rbp */
1859 DWORD (WINAPI
*call_on_stack
)( DWORD (WINAPI
*func
)(void *), void *arg
, void *stack
);
1860 void *old_stack
, *old_stack_base
, *old_stack_limit
;
1861 void *new_stack
, *new_stack_base
;
1864 call_on_stack
= VirtualAlloc( 0, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
1865 ok( call_on_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1866 memcpy( call_on_stack
, code_call_on_stack
, sizeof(code_call_on_stack
) );
1868 /* allocate a new stack, only the first guard page is committed */
1869 new_stack
= VirtualAlloc( 0, 0x400000, MEM_RESERVE
, PAGE_READWRITE
);
1870 ok( new_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1871 new_stack_base
= (char *)new_stack
+ 0x400000;
1872 VirtualAlloc( (char *)new_stack_base
- 0x1000, 0x1000, MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
1874 old_stack
= NtCurrentTeb()->DeallocationStack
;
1875 old_stack_base
= NtCurrentTeb()->Tib
.StackBase
;
1876 old_stack_limit
= NtCurrentTeb()->Tib
.StackLimit
;
1878 NtCurrentTeb()->DeallocationStack
= new_stack
;
1879 NtCurrentTeb()->Tib
.StackBase
= new_stack_base
;
1880 NtCurrentTeb()->Tib
.StackLimit
= new_stack_base
;
1882 result
= call_on_stack( stack_commit_func
, (void *)0xdeadbeef, new_stack_base
);
1884 NtCurrentTeb()->DeallocationStack
= old_stack
;
1885 NtCurrentTeb()->Tib
.StackBase
= old_stack_base
;
1886 NtCurrentTeb()->Tib
.StackLimit
= old_stack_limit
;
1888 ok( result
== 42, "expected 42, got %u\n", result
);
1890 VirtualFree( new_stack
, 0, MEM_RELEASE
);
1891 VirtualFree( call_on_stack
, 0, MEM_RELEASE
);
1894 #endif /* defined(__i386__) || defined(__x86_64__) */
1897 static LONG num_guard_page_calls
;
1899 static DWORD
guard_page_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
1900 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
1902 trace( "exception: %08x flags:%x addr:%p\n",
1903 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
);
1905 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
1906 ok( rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
, "ExceptionCode is %08x instead of %08x\n",
1907 rec
->ExceptionCode
, STATUS_GUARD_PAGE_VIOLATION
);
1909 InterlockedIncrement( &num_guard_page_calls
);
1910 *(int *)rec
->ExceptionInformation
[1] += 0x100;
1912 return ExceptionContinueExecution
;
1915 static void test_guard_page(void)
1917 EXCEPTION_REGISTRATION_RECORD frame
;
1918 MEMORY_BASIC_INFORMATION info
;
1919 DWORD ret
, size
, old_prot
;
1920 int *value
, old_value
;
1928 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
1929 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1930 value
= (int *)base
;
1932 /* verify info structure */
1933 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1934 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
1935 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1936 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1937 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1938 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1939 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
1940 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1942 /* put some initial value into the memory */
1943 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
1944 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1945 ok( old_prot
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong old prot %x\n", old_prot
);
1950 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
1951 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1952 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1954 /* test behaviour of VirtualLock - first attempt should fail */
1955 SetLastError( 0xdeadbeef );
1956 success
= VirtualLock( base
, size
);
1957 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
1959 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
1961 success
= VirtualLock( base
, size
);
1963 ok( success
, "VirtualLock failed %u\n", GetLastError() );
1966 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
1967 success
= VirtualUnlock( base
, size
);
1968 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
1971 /* check info structure again, PAGE_GUARD should be removed now */
1972 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1973 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
1974 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1975 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1976 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1977 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1979 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1980 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1982 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
1983 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1985 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1987 /* test directly accessing the memory - we need to setup an exception handler first */
1988 frame
.Handler
= guard_page_handler
;
1989 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
1990 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
1992 InterlockedExchange( &num_guard_page_calls
, 0 );
1993 InterlockedExchange( &old_value
, *value
); /* exception handler increments value by 0x100 */
1995 ok( old_value
== 0x101, "memory block contains wrong value, expected 0x101, got 0x%x\n", old_value
);
1996 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
1998 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2000 /* check info structure again, PAGE_GUARD should be removed now */
2001 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2002 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
2003 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
2005 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2006 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2007 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2009 /* test accessing second integer in memory */
2010 frame
.Handler
= guard_page_handler
;
2011 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2012 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2014 InterlockedExchange( &num_guard_page_calls
, 0 );
2015 old_value
= *(value
+ 1);
2016 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
2017 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
2018 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2020 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2022 success
= VirtualLock( base
, size
);
2023 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2026 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
2027 success
= VirtualUnlock( base
, size
);
2028 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2031 VirtualFree( base
, 0, MEM_RELEASE
);
2033 /* combined guard page / write watch tests */
2034 if (!pGetWriteWatch
|| !pResetWriteWatch
)
2036 win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" );
2040 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
| PAGE_GUARD
);
2041 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
2043 win_skip( "MEM_WRITE_WATCH not supported\n" );
2046 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2047 value
= (int *)base
;
2049 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2050 ok( ret
, "VirtualQuery failed %u\n", GetLastError() );
2051 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
2052 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
2053 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
2054 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
2055 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
2056 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
2059 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
2060 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2061 ok( count
== 0, "wrong count %lu\n", count
);
2063 /* writing to a page should trigger should trigger guard page, even if write watch is set */
2064 frame
.Handler
= guard_page_handler
;
2065 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2066 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2068 InterlockedExchange( &num_guard_page_calls
, 0 );
2071 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2073 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2076 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2077 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2078 ok( count
== 1, "wrong count %lu\n", count
);
2079 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2081 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2082 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2084 /* write watch is triggered from inside of the guard page handler */
2085 frame
.Handler
= guard_page_handler
;
2086 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2087 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2089 InterlockedExchange( &num_guard_page_calls
, 0 );
2090 old_value
= *(value
+ 1); /* doesn't trigger write watch */
2091 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
2092 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2093 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2095 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2098 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2099 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2100 ok( count
== 1, "wrong count %lu\n", count
);
2101 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2103 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2104 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2106 /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */
2107 SetLastError( 0xdeadbeef );
2108 success
= VirtualLock( base
, size
);
2109 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
2111 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
2114 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
2115 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2116 ok( count
== 0, "wrong count %lu\n", count
);
2118 success
= VirtualLock( base
, size
);
2120 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2123 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2124 success
= VirtualUnlock( base
, size
);
2125 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2129 results
[0] = (void *)0xdeadbeef;
2130 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2131 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2133 ok( count
== 1 || broken(count
== 0) /* Windows 8 */, "wrong count %lu\n", count
);
2135 ok( results
[0] == base
|| broken(results
[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results
[0] );
2137 VirtualFree( base
, 0, MEM_RELEASE
);
2140 static LONG num_execute_fault_calls
;
2142 static DWORD
execute_fault_seh_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
2143 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
2145 ULONG flags
= MEM_EXECUTE_OPTION_ENABLE
;
2148 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2149 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2150 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2152 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2153 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
|| rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
,
2154 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec
->ExceptionCode
);
2156 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &flags
, sizeof(flags
), NULL
);
2158 if (rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
)
2161 err
= IsProcessorFeaturePresent( PF_NX_ENABLED
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2162 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2163 (DWORD
)rec
->ExceptionInformation
[0], err
);
2165 InterlockedIncrement( &num_guard_page_calls
);
2167 else if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2172 err
= (flags
& MEM_EXECUTE_OPTION_DISABLE
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2173 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2174 (DWORD
)rec
->ExceptionInformation
[0], err
);
2176 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2177 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2178 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2180 InterlockedIncrement( &num_execute_fault_calls
);
2183 return ExceptionContinueExecution
;
2186 static LONG CALLBACK
execute_fault_vec_handler( EXCEPTION_POINTERS
*ExceptionInfo
)
2188 PEXCEPTION_RECORD rec
= ExceptionInfo
->ExceptionRecord
;
2192 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2193 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2194 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2196 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2197 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
,
2198 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec
->ExceptionCode
);
2200 if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2201 InterlockedIncrement( &num_execute_fault_calls
);
2203 if (rec
->ExceptionInformation
[0] == EXCEPTION_READ_FAULT
)
2204 return EXCEPTION_CONTINUE_SEARCH
;
2206 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2207 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2208 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
2210 return EXCEPTION_CONTINUE_EXECUTION
;
2213 static inline DWORD
send_message_excpt( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2215 EXCEPTION_REGISTRATION_RECORD frame
;
2218 frame
.Handler
= execute_fault_seh_handler
;
2219 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2220 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2222 InterlockedExchange( &num_guard_page_calls
, 0 );
2223 InterlockedExchange( &num_execute_fault_calls
, 0 );
2224 ret
= SendMessageA( hWnd
, uMsg
, wParam
, lParam
);
2226 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2231 static inline DWORD
call_proc_excpt( DWORD (CALLBACK
*code
)(void *), void *arg
)
2233 EXCEPTION_REGISTRATION_RECORD frame
;
2236 frame
.Handler
= execute_fault_seh_handler
;
2237 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2238 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2240 InterlockedExchange( &num_guard_page_calls
, 0 );
2241 InterlockedExchange( &num_execute_fault_calls
, 0 );
2244 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2249 static LRESULT CALLBACK
jmp_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2251 if (uMsg
== WM_USER
)
2254 return DefWindowProcA( hWnd
, uMsg
, wParam
, lParam
);
2257 static LRESULT CALLBACK
atl_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2259 DWORD arg
= (DWORD
)hWnd
;
2260 if (uMsg
== WM_USER
)
2261 ok( arg
== 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg
);
2263 ok( arg
!= 0x11223344, "arg is unexpectedly 0x11223344\n" );
2267 static DWORD CALLBACK
atl5_test_func( void )
2272 static void test_atl_thunk_emulation( ULONG dep_flags
)
2274 static const char code_jmp
[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
2275 static const char code_atl1
[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2276 static const char code_atl2
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2277 static const char code_atl3
[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1};
2278 static const char code_atl4
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
2279 static const char code_atl5
[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04};
2280 static const char cls_name
[] = "atl_thunk_class";
2281 DWORD ret
, size
, old_prot
;
2282 ULONG old_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2283 BOOL success
, restore_flags
= FALSE
;
2291 trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2293 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
), NULL
);
2294 if (old_flags
!= dep_flags
)
2296 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &dep_flags
, sizeof(dep_flags
) );
2297 if (ret
== STATUS_INVALID_INFO_CLASS
) /* Windows 2000 */
2299 win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2302 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2303 restore_flags
= TRUE
;
2307 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
2308 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2310 /* Check result of GetProcessDEPPolicy */
2311 if (!pGetProcessDEPPolicy
)
2312 win_skip( "GetProcessDEPPolicy not supported\n" );
2315 BOOL (WINAPI
*get_dep_policy
)(HANDLE
, LPDWORD
, PBOOL
) = (void *)base
;
2316 BOOL policy_permanent
= 0xdeadbeef;
2317 DWORD policy_flags
= 0xdeadbeef;
2319 /* GetProcessDEPPolicy crashes on Windows when a NULL pointer is passed.
2320 * Moreover this function has a bug on Windows 8, which has the effect that
2321 * policy_permanent is set to the content of the CL register instead of 0,
2322 * when the policy is not permanent. To detect that we use an assembler
2323 * wrapper to call the function. */
2325 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2326 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)pGetProcessDEPPolicy
- (DWORD_PTR
)(base
+ 10);
2328 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2329 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2331 success
= get_dep_policy( GetCurrentProcess(), &policy_flags
, &policy_permanent
);
2332 ok( success
, "GetProcessDEPPolicy failed %u\n", GetLastError() );
2335 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2336 ret
|= PROCESS_DEP_ENABLE
;
2337 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
)
2338 ret
|= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
;
2340 ok( policy_flags
== ret
, "expected policy flags %d, got %d\n", ret
, policy_flags
);
2341 ok( !policy_permanent
|| broken(policy_permanent
== 0x44),
2342 "expected policy permanent FALSE, got %d\n", policy_permanent
);
2345 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2346 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2348 /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
2349 * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
2350 * where it is active, so that application which depend on that still work properly.
2351 * We have no exception handler enabled yet, so give proper EXECUTE permissions to
2352 * prevent crashes while creating the window. */
2354 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2355 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2357 memset( &wc
, 0, sizeof(wc
) );
2358 wc
.cbSize
= sizeof(wc
);
2359 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2360 wc
.hInstance
= GetModuleHandleA( 0 );
2361 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2362 wc
.hbrBackground
= NULL
;
2363 wc
.lpszClassName
= cls_name
;
2364 wc
.lpfnWndProc
= (WNDPROC
)base
;
2365 success
= RegisterClassExA(&wc
) != 0;
2366 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2368 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2369 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2371 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2372 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2374 /* At first try with an instruction which is not recognized as proper ATL thunk
2375 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2376 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2378 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2379 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2381 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2382 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2383 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2384 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !IsProcessorFeaturePresent( PF_NX_ENABLED
))
2386 trace( "DEP hardware support is not available\n" );
2387 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2388 dep_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2390 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2392 trace( "DEP hardware support is available\n" );
2393 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2396 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2398 /* Now a bit more complicated, the page containing the code is protected with
2399 * PAGE_GUARD memory protection. */
2401 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2402 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2404 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2405 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2406 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2407 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2408 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2410 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2412 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2413 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2414 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2415 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2417 /* Now test with a proper ATL thunk instruction. */
2419 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2420 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2422 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2423 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2425 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2426 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2428 /* Try executing with PAGE_READWRITE protection. */
2430 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2431 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2433 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2434 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2435 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2436 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2437 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2439 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2441 /* Now a bit more complicated, the page containing the code is protected with
2442 * PAGE_GUARD memory protection. */
2444 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2445 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2447 /* the same, but with PAGE_GUARD set */
2448 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2449 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2450 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2451 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2452 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2454 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2456 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2457 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2458 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2459 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2461 /* The following test shows that on Windows, even a vectored exception handler
2462 * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */
2464 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !(dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2466 if (pRtlAddVectoredExceptionHandler
&& pRtlRemoveVectoredExceptionHandler
)
2468 PVOID vectored_handler
;
2470 success
= VirtualProtect( base
, size
, PAGE_NOACCESS
, &old_prot
);
2471 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2473 vectored_handler
= pRtlAddVectoredExceptionHandler( TRUE
, &execute_fault_vec_handler
);
2474 ok( vectored_handler
!= 0, "RtlAddVectoredExceptionHandler failed\n" );
2476 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2478 pRtlRemoveVectoredExceptionHandler( vectored_handler
);
2480 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2481 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2484 win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" );
2487 /* Test alternative ATL thunk instructions. */
2489 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2490 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 10);
2492 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2493 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2495 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2496 /* FIXME: we don't check the content of the register ECX yet */
2497 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2498 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2499 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2500 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2502 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2504 memcpy( base
, code_atl3
, sizeof(code_atl3
) );
2505 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2507 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2508 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2510 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2511 /* FIXME: we don't check the content of the registers ECX/EDX yet */
2512 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2513 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2514 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2515 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2517 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2519 memcpy( base
, code_atl4
, sizeof(code_atl4
) );
2520 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2522 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2523 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2525 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2526 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2527 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2528 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2529 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2530 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2531 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2532 ok( num_execute_fault_calls
== 0 || broken(num_execute_fault_calls
== 1) /* Windows XP */,
2533 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2535 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2537 memcpy( base
, code_atl5
, sizeof(code_atl5
) );
2539 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2540 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2542 ret
= (DWORD_PTR
)atl5_test_func
;
2543 ret
= call_proc_excpt( (void *)base
, &ret
- 1 );
2544 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2545 ok( ret
== 44, "call returned wrong result, expected 44, got %d\n", ret
);
2546 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2547 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2548 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2549 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2550 ok( num_execute_fault_calls
== 0 || broken(num_execute_fault_calls
== 1) /* Windows XP */,
2551 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2553 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2555 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2557 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2558 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2560 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2561 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2563 DestroyWindow( hWnd
);
2565 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2566 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2568 VirtualFree( base
, 0, MEM_RELEASE
);
2570 /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */
2572 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
2573 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
2575 win_skip( "MEM_WRITE_WATCH not supported\n" );
2578 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2581 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2582 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2583 ok( count
== 0, "wrong count %lu\n", count
);
2585 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2586 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2589 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2590 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2591 ok( count
== 1, "wrong count %lu\n", count
);
2592 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2594 /* Create a new window class and associated Window (see above) */
2596 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2597 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2599 memset( &wc
, 0, sizeof(wc
) );
2600 wc
.cbSize
= sizeof(wc
);
2601 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2602 wc
.hInstance
= GetModuleHandleA( 0 );
2603 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2604 wc
.hbrBackground
= NULL
;
2605 wc
.lpszClassName
= cls_name
;
2606 wc
.lpfnWndProc
= (WNDPROC
)base
;
2607 success
= RegisterClassExA(&wc
) != 0;
2608 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2610 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2611 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2613 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2614 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2617 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2618 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2619 ok( count
== 0, "wrong count %lu\n", count
);
2621 /* At first try with an instruction which is not recognized as proper ATL thunk
2622 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2623 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2625 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2626 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2628 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2629 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2630 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2631 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2632 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2634 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2637 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2638 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2639 ok( count
== 0, "wrong count %lu\n", count
);
2641 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2642 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2643 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2644 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2646 /* Now a bit more complicated, the page containing the code is protected with
2647 * PAGE_GUARD memory protection. */
2649 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2650 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2652 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2653 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2654 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2655 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2656 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2658 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2660 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2661 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2662 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2663 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2666 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2667 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2668 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2670 /* Now test with a proper ATL thunk instruction. */
2672 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2673 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2676 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2677 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2678 ok( count
== 1, "wrong count %lu\n", count
);
2679 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2681 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2682 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2684 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2685 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2687 /* Try executing with PAGE_READWRITE protection. */
2689 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2690 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2692 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2693 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2694 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2695 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2696 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2698 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2701 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2702 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2703 ok( count
== 0, "wrong count %lu\n", count
);
2705 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2706 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2707 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2708 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2709 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2711 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2713 /* Now a bit more complicated, the page containing the code is protected with
2714 * PAGE_GUARD memory protection. */
2716 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2717 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2719 /* the same, but with PAGE_GUARD set */
2720 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2721 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2722 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2723 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2724 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2726 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2728 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2729 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2730 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2731 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2734 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2735 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2736 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2738 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2740 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2741 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2744 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2745 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2746 ok( count
== 1, "wrong count %lu\n", count
);
2747 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2749 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2750 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2752 DestroyWindow( hWnd
);
2754 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2755 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2757 VirtualFree( base
, 0, MEM_RELEASE
);
2762 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
) );
2763 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2767 #endif /* __i386__ */
2769 static void test_VirtualProtect(void)
2771 static const struct test_data
2773 DWORD prot_set
, prot_get
;
2776 { 0, 0 }, /* 0x00 */
2777 { PAGE_NOACCESS
, PAGE_NOACCESS
}, /* 0x01 */
2778 { PAGE_READONLY
, PAGE_READONLY
}, /* 0x02 */
2779 { PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x03 */
2780 { PAGE_READWRITE
, PAGE_READWRITE
}, /* 0x04 */
2781 { PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x05 */
2782 { PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x06 */
2783 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x07 */
2784 { PAGE_WRITECOPY
, 0 }, /* 0x08 */
2785 { PAGE_WRITECOPY
| PAGE_NOACCESS
, 0 }, /* 0x09 */
2786 { PAGE_WRITECOPY
| PAGE_READONLY
, 0 }, /* 0x0a */
2787 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, 0 }, /* 0x0b */
2788 { PAGE_WRITECOPY
| PAGE_READWRITE
, 0 }, /* 0x0c */
2789 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x0d */
2790 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x0e */
2791 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x0f */
2793 { PAGE_EXECUTE
, PAGE_EXECUTE
}, /* 0x10 */
2794 { PAGE_EXECUTE_READ
, PAGE_EXECUTE_READ
}, /* 0x20 */
2795 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x30 */
2796 { PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
2797 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0x50 */
2798 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0x60 */
2799 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x70 */
2800 { PAGE_EXECUTE_WRITECOPY
, 0 }, /* 0x80 */
2801 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, 0 }, /* 0x90 */
2802 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, 0 }, /* 0xa0 */
2803 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0xb0 */
2804 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, 0 }, /* 0xc0 */
2805 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0xd0 */
2806 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0xe0 */
2807 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 } /* 0xf0 */
2810 DWORD ret
, old_prot
, rw_prot
, exec_prot
, i
, j
;
2811 MEMORY_BASIC_INFORMATION info
;
2818 trace("system page size %#x\n", si
.dwPageSize
);
2820 SetLastError(0xdeadbeef);
2821 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_RESERVE
| MEM_COMMIT
, PAGE_NOACCESS
);
2822 ok(base
!= NULL
, "VirtualAlloc failed %d\n", GetLastError());
2824 SetLastError(0xdeadbeef);
2825 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_READONLY
, NULL
);
2826 ok(!ret
, "VirtualProtect should fail\n");
2827 ok(GetLastError() == ERROR_NOACCESS
, "expected ERROR_NOACCESS, got %d\n", GetLastError());
2828 old_prot
= 0xdeadbeef;
2829 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2830 ok(ret
, "VirtualProtect failed %d\n", GetLastError());
2831 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2834 size
= si
.dwPageSize
;
2835 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_READONLY
, NULL
);
2836 ok(status
== STATUS_ACCESS_VIOLATION
, "NtProtectVirtualMemory should fail, got %08x\n", status
);
2838 size
= si
.dwPageSize
;
2839 old_prot
= 0xdeadbeef;
2840 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_NOACCESS
, &old_prot
);
2841 ok(status
== STATUS_SUCCESS
, "NtProtectVirtualMemory should succeed, got %08x\n", status
);
2842 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2844 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
2846 SetLastError(0xdeadbeef);
2847 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2848 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2849 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2850 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2851 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
2852 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2853 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2854 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2855 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2857 old_prot
= 0xdeadbeef;
2858 SetLastError(0xdeadbeef);
2859 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot_set
, &old_prot
);
2862 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2863 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
2865 SetLastError(0xdeadbeef);
2866 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2867 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2868 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2869 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2870 ok(info
.Protect
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_get
);
2871 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2872 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2873 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2874 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2878 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
2879 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
2882 old_prot
= 0xdeadbeef;
2883 SetLastError(0xdeadbeef);
2884 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2885 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2887 ok(old_prot
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_get
);
2889 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
2894 for (i
= 0; i
<= 4; i
++)
2898 for (j
= 0; j
<= 4; j
++)
2900 DWORD prot
= exec_prot
| rw_prot
;
2902 SetLastError(0xdeadbeef);
2903 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, prot
);
2904 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
2906 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
2907 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2911 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
2913 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
2914 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2918 ok(ptr
!= NULL
, "VirtualAlloc(%02x) error %d\n", prot
, GetLastError());
2919 ok(ptr
== base
, "expected %p, got %p\n", base
, ptr
);
2923 SetLastError(0xdeadbeef);
2924 ret
= VirtualProtect(base
, si
.dwPageSize
, prot
, &old_prot
);
2925 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
2927 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
2928 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2932 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
2934 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
2935 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2938 ok(ret
, "VirtualProtect(%02x) error %d\n", prot
, GetLastError());
2944 exec_prot
= 1 << (i
+ 4);
2947 VirtualFree(base
, 0, MEM_RELEASE
);
2950 static BOOL
is_mem_writable(DWORD prot
)
2952 switch (prot
& 0xff)
2954 case PAGE_READWRITE
:
2955 case PAGE_WRITECOPY
:
2956 case PAGE_EXECUTE_READWRITE
:
2957 case PAGE_EXECUTE_WRITECOPY
:
2965 static void test_VirtualAlloc_protection(void)
2967 static const struct test_data
2973 { 0, FALSE
}, /* 0x00 */
2974 { PAGE_NOACCESS
, TRUE
}, /* 0x01 */
2975 { PAGE_READONLY
, TRUE
}, /* 0x02 */
2976 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x03 */
2977 { PAGE_READWRITE
, TRUE
}, /* 0x04 */
2978 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x05 */
2979 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x06 */
2980 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x07 */
2981 { PAGE_WRITECOPY
, FALSE
}, /* 0x08 */
2982 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
}, /* 0x09 */
2983 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
}, /* 0x0a */
2984 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
}, /* 0x0b */
2985 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
}, /* 0x0c */
2986 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x0d */
2987 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x0e */
2988 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x0f */
2990 { PAGE_EXECUTE
, TRUE
}, /* 0x10 */
2991 { PAGE_EXECUTE_READ
, TRUE
}, /* 0x20 */
2992 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x30 */
2993 { PAGE_EXECUTE_READWRITE
, TRUE
}, /* 0x40 */
2994 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0x50 */
2995 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0x60 */
2996 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x70 */
2997 { PAGE_EXECUTE_WRITECOPY
, FALSE
}, /* 0x80 */
2998 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
}, /* 0x90 */
2999 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xa0 */
3000 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0xb0 */
3001 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
}, /* 0xc0 */
3002 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0xd0 */
3003 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xe0 */
3004 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
} /* 0xf0 */
3008 MEMORY_BASIC_INFORMATION info
;
3012 trace("system page size %#x\n", si
.dwPageSize
);
3014 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3016 SetLastError(0xdeadbeef);
3017 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3021 ok(base
!= NULL
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3023 SetLastError(0xdeadbeef);
3024 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3025 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3026 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3027 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3028 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3029 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3030 ok(info
.AllocationProtect
== td
[i
].prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, td
[i
].prot
);
3031 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3032 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
3034 if (is_mem_writable(info
.Protect
))
3038 SetLastError(0xdeadbeef);
3039 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3040 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3041 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3044 SetLastError(0xdeadbeef);
3045 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3046 ok(ptr
== base
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3048 VirtualFree(base
, 0, MEM_RELEASE
);
3052 ok(!base
, "%d: VirtualAlloc should fail\n", i
);
3053 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3058 static void test_CreateFileMapping_protection(void)
3060 static const struct test_data
3064 DWORD prot_after_write
;
3067 { 0, FALSE
, 0 }, /* 0x00 */
3068 { PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x01 */
3069 { PAGE_READONLY
, TRUE
, PAGE_READONLY
}, /* 0x02 */
3070 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x03 */
3071 { PAGE_READWRITE
, TRUE
, PAGE_READWRITE
}, /* 0x04 */
3072 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x05 */
3073 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x06 */
3074 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x07 */
3075 { PAGE_WRITECOPY
, TRUE
, PAGE_READWRITE
}, /* 0x08 */
3076 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x09 */
3077 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0a */
3078 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0b */
3079 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0x0c */
3080 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0d */
3081 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0e */
3082 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0f */
3084 { PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE
}, /* 0x10 */
3085 { PAGE_EXECUTE_READ
, TRUE
, PAGE_EXECUTE_READ
}, /* 0x20 */
3086 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE_READ
}, /* 0x30 */
3087 { PAGE_EXECUTE_READWRITE
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
3088 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x50 */
3089 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0x60 */
3090 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x70 */
3091 { PAGE_EXECUTE_WRITECOPY
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x80 */
3092 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x90 */
3093 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xa0 */
3094 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xb0 */
3095 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0xc0 */
3096 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xd0 */
3097 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xe0 */
3098 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
} /* 0xf0 */
3101 DWORD ret
, i
, alloc_prot
, prot
, old_prot
;
3102 MEMORY_BASIC_INFORMATION info
;
3104 char temp_path
[MAX_PATH
];
3105 char file_name
[MAX_PATH
];
3107 BOOL page_exec_supported
= TRUE
;
3110 trace("system page size %#x\n", si
.dwPageSize
);
3112 GetTempPathA(MAX_PATH
, temp_path
);
3113 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3115 SetLastError(0xdeadbeef);
3116 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3117 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3118 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3119 SetEndOfFile(hfile
);
3121 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3123 SetLastError(0xdeadbeef);
3124 hmap
= CreateFileMappingW(hfile
, NULL
, td
[i
].prot
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3130 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, td
[i
].prot
, GetLastError());
3131 /* NT4 and win2k don't support EXEC on file mappings */
3132 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3134 page_exec_supported
= FALSE
;
3135 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3138 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3139 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3141 page_exec_supported
= FALSE
;
3142 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3146 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, td
[i
].prot
, GetLastError());
3148 base
= MapViewOfFile(hmap
, FILE_MAP_READ
, 0, 0, 0);
3149 ok(base
!= NULL
, "%d: MapViewOfFile failed %d\n", i
, GetLastError());
3151 SetLastError(0xdeadbeef);
3152 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3153 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3154 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3155 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3156 ok(info
.Protect
== PAGE_READONLY
, "%d: got %#x != expected PAGE_READONLY\n", i
, info
.Protect
);
3157 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3158 ok(info
.AllocationProtect
== PAGE_READONLY
, "%d: %#x != PAGE_READONLY\n", i
, info
.AllocationProtect
);
3159 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3160 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3162 if (is_mem_writable(info
.Protect
))
3166 SetLastError(0xdeadbeef);
3167 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3168 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3169 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3172 SetLastError(0xdeadbeef);
3173 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3174 ok(!ptr
, "%d: VirtualAlloc(%02x) should fail\n", i
, td
[i
].prot
);
3175 /* FIXME: remove once Wine is fixed */
3176 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3177 ok(GetLastError() == ERROR_ACCESS_DENIED
, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i
, GetLastError());
3179 SetLastError(0xdeadbeef);
3180 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3181 if (td
[i
].prot
== PAGE_READONLY
|| td
[i
].prot
== PAGE_WRITECOPY
)
3182 ok(ret
, "%d: VirtualProtect(%02x) error %d\n", i
, td
[i
].prot
, GetLastError());
3185 ok(!ret
, "%d: VirtualProtect(%02x) should fail\n", i
, td
[i
].prot
);
3186 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3189 UnmapViewOfFile(base
);
3194 ok(!hmap
, "%d: CreateFileMapping should fail\n", i
);
3195 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3199 if (page_exec_supported
) alloc_prot
= PAGE_EXECUTE_READWRITE
;
3200 else alloc_prot
= PAGE_READWRITE
;
3201 SetLastError(0xdeadbeef);
3202 hmap
= CreateFileMappingW(hfile
, NULL
, alloc_prot
, 0, si
.dwPageSize
, NULL
);
3203 ok(hmap
!= 0, "%d: CreateFileMapping error %d\n", i
, GetLastError());
3205 SetLastError(0xdeadbeef);
3206 base
= MapViewOfFile(hmap
, FILE_MAP_READ
| FILE_MAP_WRITE
| (page_exec_supported
? FILE_MAP_EXECUTE
: 0), 0, 0, 0);
3207 ok(base
!= NULL
, "MapViewOfFile failed %d\n", GetLastError());
3209 old_prot
= 0xdeadbeef;
3210 SetLastError(0xdeadbeef);
3211 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3212 ok(ret
, "VirtualProtect error %d\n", GetLastError());
3213 ok(old_prot
== alloc_prot
, "got %#x != expected %#x\n", old_prot
, alloc_prot
);
3215 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3217 SetLastError(0xdeadbeef);
3218 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3219 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3220 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3221 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3222 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
3223 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3224 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3225 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3226 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3228 old_prot
= 0xdeadbeef;
3229 SetLastError(0xdeadbeef);
3230 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3231 if (td
[i
].success
|| td
[i
].prot
== PAGE_NOACCESS
|| td
[i
].prot
== PAGE_EXECUTE
)
3235 /* win2k and XP don't support EXEC on file mappings */
3236 if (td
[i
].prot
== PAGE_EXECUTE
)
3238 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3241 /* NT4 and win2k don't support EXEC on file mappings */
3242 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3244 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3247 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3248 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3250 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3255 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3256 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
3259 /* looks strange but Windows doesn't do this for PAGE_WRITECOPY */
3260 if (prot
== PAGE_EXECUTE_WRITECOPY
) prot
= PAGE_EXECUTE_READWRITE
;
3262 SetLastError(0xdeadbeef);
3263 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3264 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3265 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3266 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3267 /* FIXME: remove the condition below once Wine is fixed */
3268 todo_wine_if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3269 ok(info
.Protect
== prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, prot
);
3270 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3271 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3272 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3273 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3275 if (is_mem_writable(info
.Protect
))
3279 SetLastError(0xdeadbeef);
3280 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3281 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3282 /* FIXME: remove the condition below once Wine is fixed */
3283 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3284 ok(info
.Protect
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_after_write
);
3289 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
3290 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3294 old_prot
= 0xdeadbeef;
3295 SetLastError(0xdeadbeef);
3296 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3297 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3298 /* FIXME: remove the condition below once Wine is fixed */
3299 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3300 ok(old_prot
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_after_write
);
3303 UnmapViewOfFile(base
);
3307 DeleteFileA(file_name
);
3310 #define ACCESS_READ 0x01
3311 #define ACCESS_WRITE 0x02
3312 #define ACCESS_EXECUTE 0x04
3313 #define ACCESS_WRITECOPY 0x08
3315 static DWORD
page_prot_to_access(DWORD prot
)
3319 case PAGE_READWRITE
:
3320 return ACCESS_READ
| ACCESS_WRITE
;
3323 case PAGE_EXECUTE_READ
:
3324 return ACCESS_READ
| ACCESS_EXECUTE
;
3326 case PAGE_EXECUTE_READWRITE
:
3327 return ACCESS_READ
| ACCESS_WRITE
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3329 case PAGE_EXECUTE_WRITECOPY
:
3330 return ACCESS_READ
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3335 case PAGE_WRITECOPY
:
3343 static BOOL
is_compatible_protection(DWORD map_prot
, DWORD view_prot
, DWORD prot
)
3345 DWORD map_access
, view_access
, prot_access
;
3347 map_access
= page_prot_to_access(map_prot
);
3348 view_access
= page_prot_to_access(view_prot
);
3349 prot_access
= page_prot_to_access(prot
);
3351 if (view_access
== prot_access
) return TRUE
;
3352 if (!view_access
) return FALSE
;
3354 if ((view_access
& prot_access
) != prot_access
) return FALSE
;
3355 if ((map_access
& prot_access
) == prot_access
) return TRUE
;
3360 static DWORD
map_prot_to_access(DWORD prot
)
3364 case PAGE_READWRITE
:
3365 case PAGE_EXECUTE_READWRITE
:
3366 return SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3368 case PAGE_WRITECOPY
:
3370 case PAGE_EXECUTE_READ
:
3371 case PAGE_EXECUTE_WRITECOPY
:
3372 return SECTION_MAP_READ
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3378 static BOOL
is_compatible_access(DWORD map_prot
, DWORD view_prot
)
3380 DWORD access
= map_prot_to_access(map_prot
);
3381 if (!view_prot
) view_prot
= SECTION_MAP_READ
;
3382 return (view_prot
& access
) == view_prot
;
3385 static void *map_view_of_file(HANDLE handle
, DWORD access
)
3388 LARGE_INTEGER offset
;
3394 if (!pNtMapViewOfSection
) return NULL
;
3397 offset
.u
.LowPart
= 0;
3398 offset
.u
.HighPart
= 0;
3400 exec
= access
& FILE_MAP_EXECUTE
;
3401 access
&= ~FILE_MAP_EXECUTE
;
3403 if (access
== FILE_MAP_COPY
)
3406 protect
= PAGE_EXECUTE_WRITECOPY
;
3408 protect
= PAGE_WRITECOPY
;
3410 else if (access
& FILE_MAP_WRITE
)
3413 protect
= PAGE_EXECUTE_READWRITE
;
3415 protect
= PAGE_READWRITE
;
3417 else if (access
& FILE_MAP_READ
)
3420 protect
= PAGE_EXECUTE_READ
;
3422 protect
= PAGE_READONLY
;
3424 else protect
= PAGE_NOACCESS
;
3427 status
= pNtMapViewOfSection(handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
3428 &count
, 1 /* ViewShare */, 0, protect
);
3431 /* for simplicity */
3432 SetLastError(ERROR_ACCESS_DENIED
);
3438 static void test_mapping(void)
3440 static const DWORD page_prot
[] =
3442 PAGE_NOACCESS
, PAGE_READONLY
, PAGE_READWRITE
, PAGE_WRITECOPY
,
3443 PAGE_EXECUTE_READ
, PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_WRITECOPY
3450 { 0, PAGE_NOACCESS
}, /* 0x00 */
3451 { FILE_MAP_COPY
, PAGE_WRITECOPY
}, /* 0x01 */
3452 { FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x02 */
3453 { FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x03 */
3454 { FILE_MAP_READ
, PAGE_READONLY
}, /* 0x04 */
3455 { FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x05 */
3456 { FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x06 */
3457 { FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x07 */
3458 { SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x08 */
3459 { SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x09 */
3460 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0a */
3461 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0b */
3462 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_READONLY
}, /* 0x0c */
3463 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x0d */
3464 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0e */
3465 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0f */
3466 { FILE_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x20 */
3467 { FILE_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_EXECUTE_WRITECOPY
}, /* 0x21 */
3468 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x22 */
3469 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x23 */
3470 { FILE_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x24 */
3471 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x25 */
3472 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x26 */
3473 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x27 */
3474 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x28 */
3475 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x29 */
3476 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2a */
3477 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x2b */
3478 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x2c */
3479 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x2d */
3480 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2e */
3481 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
} /* 0x2f */
3483 void *base
, *nt_base
, *ptr
;
3484 DWORD i
, j
, k
, ret
, old_prot
, prev_prot
;
3486 char temp_path
[MAX_PATH
];
3487 char file_name
[MAX_PATH
];
3489 MEMORY_BASIC_INFORMATION info
, nt_info
;
3492 trace("system page size %#x\n", si
.dwPageSize
);
3494 GetTempPathA(MAX_PATH
, temp_path
);
3495 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3497 SetLastError(0xdeadbeef);
3498 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3499 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3500 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3501 SetEndOfFile(hfile
);
3503 for (i
= 0; i
< sizeof(page_prot
)/sizeof(page_prot
[0]); i
++)
3505 SetLastError(0xdeadbeef);
3506 hmap
= CreateFileMappingW(hfile
, NULL
, page_prot
[i
] | SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3508 if (page_prot
[i
] == PAGE_NOACCESS
)
3512 ok(!hmap
, "CreateFileMapping(PAGE_NOACCESS) should fail\n");
3513 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3515 /* A trick to create a not accessible mapping */
3516 SetLastError(0xdeadbeef);
3517 hmap
= CreateFileMappingW(hfile
, NULL
, PAGE_READWRITE
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3518 ok(hmap
!= 0, "CreateFileMapping(PAGE_READWRITE) error %d\n", GetLastError());
3519 SetLastError(0xdeadbeef);
3520 ret
= DuplicateHandle(GetCurrentProcess(), hmap
, GetCurrentProcess(), &hmap2
, 0, FALSE
, 0);
3521 ok(ret
, "DuplicateHandle error %d\n", GetLastError());
3528 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, page_prot
[i
], GetLastError());
3530 /* NT4 and win2k don't support EXEC on file mappings */
3531 if (page_prot
[i
] == PAGE_EXECUTE_READ
|| page_prot
[i
] == PAGE_EXECUTE_READWRITE
)
3533 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3536 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3537 if (page_prot
[i
] == PAGE_EXECUTE_WRITECOPY
)
3539 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3544 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, page_prot
[i
], GetLastError());
3546 for (j
= 0; j
< sizeof(view
)/sizeof(view
[0]); j
++)
3548 nt_base
= map_view_of_file(hmap
, view
[j
].access
);
3551 SetLastError(0xdeadbeef);
3552 ret
= VirtualQuery(nt_base
, &nt_info
, sizeof(nt_info
));
3553 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3554 UnmapViewOfFile(nt_base
);
3557 SetLastError(0xdeadbeef);
3558 base
= MapViewOfFile(hmap
, view
[j
].access
, 0, 0, 0);
3560 /* Vista+ supports FILE_MAP_EXECUTE properly, earlier versions don't */
3561 ok(!nt_base
== !base
||
3562 broken((view
[j
].access
& FILE_MAP_EXECUTE
) && !nt_base
!= !base
),
3563 "%d: (%04x/%04x) NT %p kernel %p\n", j
, page_prot
[i
], view
[j
].access
, nt_base
, base
);
3565 if (!is_compatible_access(page_prot
[i
], view
[j
].access
))
3567 ok(!base
, "%d: MapViewOfFile(%04x/%04x) should fail\n", j
, page_prot
[i
], view
[j
].access
);
3568 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %d\n", GetLastError());
3572 /* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */
3573 if (!base
&& (view
[j
].access
& FILE_MAP_EXECUTE
))
3575 ok(broken(!base
), "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3579 ok(base
!= NULL
, "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3581 SetLastError(0xdeadbeef);
3582 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3583 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3584 ok(info
.BaseAddress
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.BaseAddress
, base
);
3585 ok(info
.RegionSize
== si
.dwPageSize
, "%d: (%04x) got %#lx != expected %#x\n", j
, view
[j
].access
, info
.RegionSize
, si
.dwPageSize
);
3586 ok(info
.Protect
== view
[j
].prot
||
3587 broken(view
[j
].prot
== PAGE_EXECUTE_READ
&& info
.Protect
== PAGE_READONLY
) || /* win2k */
3588 broken(view
[j
].prot
== PAGE_EXECUTE_READWRITE
&& info
.Protect
== PAGE_READWRITE
) || /* win2k */
3589 broken(view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3590 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.Protect
, view
[j
].prot
);
3591 ok(info
.AllocationBase
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.AllocationBase
, base
);
3592 ok(info
.AllocationProtect
== info
.Protect
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.AllocationProtect
, info
.Protect
);
3593 ok(info
.State
== MEM_COMMIT
, "%d: (%04x) got %#x, expected MEM_COMMIT\n", j
, view
[j
].access
, info
.State
);
3594 ok(info
.Type
== MEM_MAPPED
, "%d: (%04x) got %#x, expected MEM_MAPPED\n", j
, view
[j
].access
, info
.Type
);
3596 if (nt_base
&& base
)
3598 ok(nt_info
.RegionSize
== info
.RegionSize
, "%d: (%04x) got %#lx != expected %#lx\n", j
, view
[j
].access
, nt_info
.RegionSize
, info
.RegionSize
);
3599 ok(nt_info
.Protect
== info
.Protect
/* Vista+ */ ||
3600 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3601 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Protect
, info
.Protect
);
3602 ok(nt_info
.AllocationProtect
== info
.AllocationProtect
/* Vista+ */ ||
3603 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3604 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.AllocationProtect
, info
.AllocationProtect
);
3605 ok(nt_info
.State
== info
.State
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.State
, info
.State
);
3606 ok(nt_info
.Type
== info
.Type
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Type
, info
.Type
);
3609 prev_prot
= info
.Protect
;
3611 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3613 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3614 SetLastError(0xdeadbeef);
3615 old_prot
= 0xdeadbeef;
3616 ret
= VirtualProtect(base
, si
.dwPageSize
, page_prot
[k
], &old_prot
);
3617 if (is_compatible_protection(page_prot
[i
], view
[j
].prot
, page_prot
[k
]))
3619 /* win2k and XP don't support EXEC on file mappings */
3620 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE
)
3622 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3625 /* NT4 and win2k don't support EXEC on file mappings */
3626 if (!ret
&& (page_prot
[k
] == PAGE_EXECUTE_READ
|| page_prot
[k
] == PAGE_EXECUTE_READWRITE
))
3628 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3631 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3632 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE_WRITECOPY
)
3634 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n");
3637 /* win2k and XP don't support PAGE_EXECUTE_WRITECOPY views properly */
3638 if (!ret
&& view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
)
3640 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY view properly\n");
3644 ok(ret
, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3645 ok(old_prot
== prev_prot
, "got %#x, expected %#x\n", old_prot
, prev_prot
);
3646 prev_prot
= page_prot
[k
];
3650 /* NT4 doesn't fail on incompatible map and view */
3653 ok(broken(ret
), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3654 skip("Incompatible map and view are not properly handled on this platform\n");
3655 break; /* NT4 won't pass remaining tests */
3658 ok(!ret
, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3659 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3663 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3665 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3666 SetLastError(0xdeadbeef);
3667 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, page_prot
[k
]);
3668 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", page_prot
[k
]);
3669 /* FIXME: remove once Wine is fixed */
3670 todo_wine_if (page_prot
[k
] == PAGE_WRITECOPY
|| page_prot
[k
] == PAGE_EXECUTE_WRITECOPY
)
3671 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3674 UnmapViewOfFile(base
);
3681 DeleteFileA(file_name
);
3684 static void test_shared_memory(BOOL is_child
)
3689 SetLastError(0xdeadbef);
3690 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c");
3691 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3693 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3695 SetLastError(0xdeadbef);
3696 p
= MapViewOfFile(mapping
, FILE_MAP_READ
|FILE_MAP_WRITE
, 0, 0, 4096);
3697 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3701 ok(*p
== 0x1a2b3c4d, "expected 0x1a2b3c4d in child, got %#x\n", *p
);
3706 char cmdline
[MAX_PATH
];
3707 PROCESS_INFORMATION pi
;
3708 STARTUPINFOA si
= { sizeof(si
) };
3713 winetest_get_mainargs(&argv
);
3714 sprintf(cmdline
, "\"%s\" virtual sharedmem", argv
[0]);
3715 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3716 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3717 winetest_wait_child_process(pi
.hProcess
);
3718 CloseHandle(pi
.hThread
);
3719 CloseHandle(pi
.hProcess
);
3723 CloseHandle(mapping
);
3726 static void test_shared_memory_ro(BOOL is_child
, DWORD child_access
)
3731 SetLastError(0xdeadbef);
3732 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c_ro");
3733 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3735 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3737 SetLastError(0xdeadbef);
3738 p
= MapViewOfFile(mapping
, is_child
? child_access
: FILE_MAP_READ
, 0, 0, 4096);
3739 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3748 char cmdline
[MAX_PATH
];
3749 PROCESS_INFORMATION pi
;
3750 STARTUPINFOA si
= { sizeof(si
) };
3753 winetest_get_mainargs(&argv
);
3754 sprintf(cmdline
, "\"%s\" virtual sharedmemro %x", argv
[0], child_access
);
3755 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3756 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3757 winetest_wait_child_process(pi
.hProcess
);
3758 CloseHandle(pi
.hThread
);
3759 CloseHandle(pi
.hProcess
);
3761 if(child_access
& FILE_MAP_WRITE
)
3762 ok(*p
== 0xdeadbeef, "*p = %x, expected 0xdeadbeef\n", *p
);
3764 ok(!*p
, "*p = %x, expected 0\n", *p
);
3768 CloseHandle(mapping
);
3775 argc
= winetest_get_mainargs( &argv
);
3779 if (!strcmp(argv
[2], "sleep"))
3781 Sleep(5000); /* spawned process runs for at most 5 seconds */
3784 if (!strcmp(argv
[2], "sharedmem"))
3786 test_shared_memory(TRUE
);
3789 if (!strcmp(argv
[2], "sharedmemro"))
3791 test_shared_memory_ro(TRUE
, strtol(argv
[3], NULL
, 16));
3798 mem
= VirtualAlloc(NULL
, 1<<20, MEM_COMMIT
|MEM_RESERVE
,
3799 PAGE_EXECUTE_READWRITE
);
3800 ok(mem
!= NULL
, "VirtualAlloc failed %u\n", GetLastError());
3801 if (mem
== NULL
) break;
3802 ret
= VirtualFree(mem
, 0, MEM_RELEASE
);
3803 ok(ret
, "VirtualFree failed %u\n", GetLastError());
3809 hkernel32
= GetModuleHandleA("kernel32.dll");
3810 hntdll
= GetModuleHandleA("ntdll.dll");
3812 pVirtualAllocEx
= (void *) GetProcAddress(hkernel32
, "VirtualAllocEx");
3813 pVirtualFreeEx
= (void *) GetProcAddress(hkernel32
, "VirtualFreeEx");
3814 pGetWriteWatch
= (void *) GetProcAddress(hkernel32
, "GetWriteWatch");
3815 pResetWriteWatch
= (void *) GetProcAddress(hkernel32
, "ResetWriteWatch");
3816 pGetProcessDEPPolicy
= (void *)GetProcAddress( hkernel32
, "GetProcessDEPPolicy" );
3817 pIsWow64Process
= (void *)GetProcAddress( hkernel32
, "IsWow64Process" );
3818 pNtAreMappedFilesTheSame
= (void *)GetProcAddress( hntdll
, "NtAreMappedFilesTheSame" );
3819 pNtMapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtMapViewOfSection" );
3820 pNtUnmapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtUnmapViewOfSection" );
3821 pRtlAddVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlAddVectoredExceptionHandler" );
3822 pRtlRemoveVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlRemoveVectoredExceptionHandler" );
3823 pNtProtectVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtProtectVirtualMemory" );
3824 pNtAllocateVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtAllocateVirtualMemory" );
3825 pNtFreeVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtFreeVirtualMemory" );
3827 test_shared_memory(FALSE
);
3828 test_shared_memory_ro(FALSE
, FILE_MAP_READ
|FILE_MAP_WRITE
);
3829 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
);
3830 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
|FILE_MAP_WRITE
);
3832 test_CreateFileMapping_protection();
3833 test_VirtualAlloc_protection();
3834 test_VirtualProtect();
3835 test_VirtualAllocEx();
3836 test_VirtualAlloc();
3837 test_MapViewOfFile();
3838 test_NtMapViewOfSection();
3839 test_NtAreMappedFilesTheSame();
3840 test_CreateFileMapping();
3841 test_IsBadReadPtr();
3842 test_IsBadWritePtr();
3843 test_IsBadCodePtr();
3845 #if defined(__i386__) || defined(__x86_64__)
3846 test_stack_commit();
3850 /* The following tests should be executed as a last step, and in exactly this
3851 * order, since ATL thunk emulation cannot be enabled anymore on Windows. */
3852 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE
);
3853 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
);
3854 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
| MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
);