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 struct _TEB
* (WINAPI
*pNtCurrentTeb
)(void);
47 static PVOID (WINAPI
*pRtlAddVectoredExceptionHandler
)(ULONG
, PVECTORED_EXCEPTION_HANDLER
);
48 static ULONG (WINAPI
*pRtlRemoveVectoredExceptionHandler
)(PVOID
);
49 static BOOL (WINAPI
*pGetProcessDEPPolicy
)(HANDLE
, LPDWORD
, PBOOL
);
50 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
51 static NTSTATUS (WINAPI
*pNtProtectVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
, ULONG
*);
52 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG
, SIZE_T
*, ULONG
, ULONG
);
53 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
55 /* ############################### */
57 static HANDLE
create_target_process(const char *arg
)
60 char cmdline
[MAX_PATH
];
61 PROCESS_INFORMATION pi
;
63 STARTUPINFOA si
= { 0 };
66 winetest_get_mainargs( &argv
);
67 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], arg
);
68 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
69 ok(ret
, "error: %u\n", GetLastError());
70 ret
= CloseHandle(pi
.hThread
);
71 ok(ret
, "error %u\n", GetLastError());
75 static void test_VirtualAllocEx(void)
77 const unsigned int alloc_size
= 1<<15;
79 SIZE_T bytes_written
= 0, bytes_read
= 0, i
;
83 MEMORY_BASIC_INFORMATION info
;
86 /* not exported in all windows-versions */
87 if ((!pVirtualAllocEx
) || (!pVirtualFreeEx
)) {
88 win_skip("Virtual{Alloc,Free}Ex not available\n");
92 hProcess
= create_target_process("sleep");
93 ok(hProcess
!= NULL
, "Can't start process\n");
95 SetLastError(0xdeadbeef);
96 addr1
= pVirtualAllocEx(hProcess
, NULL
, alloc_size
, MEM_COMMIT
,
97 PAGE_EXECUTE_READWRITE
);
98 if (!addr1
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
100 win_skip("VirtualAllocEx not implemented\n");
101 TerminateProcess(hProcess
, 0);
102 CloseHandle(hProcess
);
106 src
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
107 dst
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
108 for (i
= 0; i
< alloc_size
; i
++)
111 ok(addr1
!= NULL
, "VirtualAllocEx error %u\n", GetLastError());
112 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
113 ok(b
&& (bytes_written
== alloc_size
), "%lu bytes written\n",
115 b
= ReadProcessMemory(hProcess
, addr1
, dst
, alloc_size
, &bytes_read
);
116 ok(b
&& (bytes_read
== alloc_size
), "%lu bytes read\n", bytes_read
);
117 ok(!memcmp(src
, dst
, alloc_size
), "Data from remote process differs\n");
119 /* test invalid source buffers */
121 b
= VirtualProtect( src
+ 0x2000, 0x2000, PAGE_NOACCESS
, &old_prot
);
122 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
123 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
124 ok( !b
, "WriteProcessMemory succeeded\n" );
125 ok( GetLastError() == ERROR_NOACCESS
||
126 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
127 "wrong error %u\n", GetLastError() );
128 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
129 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
130 ok( !b
, "ReadProcessMemory succeeded\n" );
131 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
132 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
134 b
= VirtualProtect( src
, 0x2000, PAGE_NOACCESS
, &old_prot
);
135 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
136 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
137 ok( !b
, "WriteProcessMemory succeeded\n" );
138 ok( GetLastError() == ERROR_NOACCESS
||
139 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
140 "wrong error %u\n", GetLastError() );
141 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
142 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
143 ok( !b
, "ReadProcessMemory succeeded\n" );
144 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
145 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
147 b
= pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
);
148 ok(b
!= 0, "VirtualFreeEx, error %u\n", GetLastError());
150 VirtualFree( src
, 0, MEM_FREE
);
151 VirtualFree( dst
, 0, MEM_FREE
);
154 * The following tests parallel those in test_VirtualAlloc()
157 SetLastError(0xdeadbeef);
158 addr1
= pVirtualAllocEx(hProcess
, 0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
159 ok(addr1
== NULL
, "VirtualAllocEx should fail on zero-sized allocation\n");
160 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* NT */ ||
161 GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, /* Win9x */
162 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
164 addr1
= pVirtualAllocEx(hProcess
, 0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
165 ok(addr1
!= NULL
, "VirtualAllocEx failed\n");
167 /* test a not committed memory */
168 memset(&info
, 'q', sizeof(info
));
169 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
), "VirtualQueryEx failed\n");
170 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
171 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
172 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
173 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
174 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
175 /* NT reports Protect == 0 for a not committed memory block */
176 ok(info
.Protect
== 0 /* NT */ ||
177 info
.Protect
== PAGE_NOACCESS
, /* Win9x */
178 "%x != PAGE_NOACCESS\n", info
.Protect
);
179 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
181 SetLastError(0xdeadbeef);
182 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
183 "VirtualProtectEx should fail on a not committed memory\n");
184 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
185 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
186 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
188 addr2
= pVirtualAllocEx(hProcess
, addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
189 ok(addr1
== addr2
, "VirtualAllocEx failed\n");
191 /* test a committed memory */
192 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
),
193 "VirtualQueryEx failed\n");
194 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
195 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
196 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
197 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
198 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
199 /* this time NT reports PAGE_NOACCESS as well */
200 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
201 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
203 /* this should fail, since not the whole range is committed yet */
204 SetLastError(0xdeadbeef);
205 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
206 "VirtualProtectEx should fail on a not committed memory\n");
207 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
208 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
209 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
212 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtectEx failed\n");
213 ok(old_prot
== PAGE_NOACCESS
, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
216 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtectEx failed\n");
217 ok(old_prot
== PAGE_READONLY
, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
219 ok(!pVirtualFreeEx(hProcess
, addr1
, 0x10000, 0),
220 "VirtualFreeEx should fail with type 0\n");
221 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
222 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
224 ok(pVirtualFreeEx(hProcess
, addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFreeEx failed\n");
226 /* if the type is MEM_RELEASE, size must be 0 */
227 ok(!pVirtualFreeEx(hProcess
, addr1
, 1, MEM_RELEASE
),
228 "VirtualFreeEx should fail\n");
229 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
230 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
232 ok(pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
), "VirtualFreeEx failed\n");
234 TerminateProcess(hProcess
, 0);
235 CloseHandle(hProcess
);
238 static void test_VirtualAlloc(void)
242 MEMORY_BASIC_INFORMATION info
;
246 SetLastError(0xdeadbeef);
247 addr1
= VirtualAlloc(0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
248 ok(addr1
== NULL
, "VirtualAlloc should fail on zero-sized allocation\n");
249 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* NT */ ||
250 GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, /* Win9x */
251 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
253 addr1
= VirtualAlloc(0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
254 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
256 /* test a not committed memory */
257 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
258 "VirtualQuery failed\n");
259 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
260 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
261 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
262 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
263 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
264 /* NT reports Protect == 0 for a not committed memory block */
265 ok(info
.Protect
== 0 /* NT */ ||
266 info
.Protect
== PAGE_NOACCESS
, /* Win9x */
267 "%x != PAGE_NOACCESS\n", info
.Protect
);
268 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
270 SetLastError(0xdeadbeef);
271 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
272 "VirtualProtect should fail on a not committed memory\n");
273 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
274 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
275 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
277 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
278 ok(addr1
== addr2
, "VirtualAlloc failed\n");
280 /* test a committed memory */
281 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
282 "VirtualQuery failed\n");
283 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
284 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
285 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
286 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
287 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
288 /* this time NT reports PAGE_NOACCESS as well */
289 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
290 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
292 /* this should fail, since not the whole range is committed yet */
293 SetLastError(0xdeadbeef);
294 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
295 "VirtualProtect should fail on a not committed memory\n");
296 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
297 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
298 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
300 ok(VirtualProtect(addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtect failed\n");
301 ok(old_prot
== PAGE_NOACCESS
,
302 "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
304 ok(VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtect failed\n");
305 ok(old_prot
== PAGE_READONLY
,
306 "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
308 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
309 "VirtualQuery failed\n");
310 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
311 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
312 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
313 memset( addr1
, 0x55, 20 );
314 ok( *(DWORD
*)addr1
== 0x55555555, "wrong data %x\n", *(DWORD
*)addr1
);
316 addr2
= VirtualAlloc( addr1
, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
317 ok( addr2
== addr1
|| broken( !addr2
&& GetLastError() == ERROR_INVALID_PARAMETER
), /* win9x */
318 "VirtualAlloc failed err %u\n", GetLastError() );
319 ok( *(DWORD
*)addr1
== 0x55555555 || *(DWORD
*)addr1
== 0, "wrong data %x\n", *(DWORD
*)addr1
);
322 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
323 "VirtualQuery failed\n");
324 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
325 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
326 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
328 addr2
= VirtualAlloc( (char *)addr1
+ 0x1000, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
329 ok( (char *)addr2
== (char *)addr1
+ 0x1000, "VirtualAlloc failed\n" );
331 ok(VirtualQuery(addr2
, &info
, sizeof(info
)) == sizeof(info
),
332 "VirtualQuery failed\n");
333 ok(info
.RegionSize
== 0xf000, "%lx != 0xf000\n", info
.RegionSize
);
334 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
335 ok(info
.Protect
== 0, "%x != 0\n", info
.Protect
);
337 addr2
= VirtualAlloc( (char *)addr1
+ 0xf000, 0x2000, MEM_RESET
, PAGE_NOACCESS
);
338 ok( !addr2
, "VirtualAlloc failed\n" );
339 ok( GetLastError() == ERROR_INVALID_ADDRESS
, "wrong error %u\n", GetLastError() );
342 /* invalid protection values */
343 SetLastError(0xdeadbeef);
344 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_RESERVE
, 0);
345 ok(!addr2
, "VirtualAlloc succeeded\n");
346 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
348 SetLastError(0xdeadbeef);
349 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_COMMIT
, 0);
350 ok(!addr2
, "VirtualAlloc succeeded\n");
351 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
353 SetLastError(0xdeadbeef);
354 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_READONLY
| PAGE_EXECUTE
);
355 ok(!addr2
, "VirtualAlloc succeeded\n");
356 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
358 SetLastError(0xdeadbeef);
359 ok(!VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
| PAGE_EXECUTE_WRITECOPY
, &old_prot
),
360 "VirtualProtect succeeded\n");
361 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
363 SetLastError(0xdeadbeef);
364 ok(!VirtualProtect(addr1
, 0x1000, 0, &old_prot
), "VirtualProtect succeeded\n");
365 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
367 SetLastError(0xdeadbeef);
368 ok(!VirtualFree(addr1
, 0x10000, 0), "VirtualFree should fail with type 0\n");
369 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
370 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
372 ok(VirtualFree(addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFree failed\n");
374 /* if the type is MEM_RELEASE, size must be 0 */
375 ok(!VirtualFree(addr1
, 1, MEM_RELEASE
), "VirtualFree should fail\n");
376 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
377 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
379 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
381 addr1
= VirtualAlloc(0, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
382 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
383 ok(!((ULONG_PTR
)addr1
& 0xffff), "returned memory %p is not aligned to 64k\n", addr1
);
385 /* allocation conflicts because of 64k align */
387 addr2
= (char *)addr1
+ 0x1000;
388 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
,
389 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
390 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
392 /* it should conflict, even when zero_bits is explicitly set */
394 addr2
= (char *)addr1
+ 0x1000;
395 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 12, &size
,
396 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
398 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
399 if (status
== STATUS_SUCCESS
) ok(VirtualFree(addr2
, 0, MEM_RELEASE
), "VirtualFree failed\n");
401 /* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
402 SetLastError(0xdeadbeef);
403 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_RESERVE
| MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
404 ok(!addr2
, "VirtualAlloc unexpectedly succeeded\n");
405 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
407 /* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
409 addr2
= (char *)addr1
+ 0x1000;
410 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
, MEM_RESERVE
|
411 MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
413 ok(status
== STATUS_INVALID_PARAMETER_5
, "NtAllocateVirtualMemory returned %08x\n", status
);
415 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
418 static void test_MapViewOfFile(void)
420 static const char testfile
[] = "testfile.xxx";
422 HANDLE file
, mapping
, map2
;
423 void *ptr
, *ptr2
, *addr
;
424 MEMORY_BASIC_INFORMATION info
;
427 SetLastError(0xdeadbeef);
428 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
429 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
430 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
431 SetEndOfFile( file
);
433 /* read/write mapping */
435 SetLastError(0xdeadbeef);
436 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
437 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
439 SetLastError(0xdeadbeef);
440 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
441 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAPE_READ error %u\n", GetLastError() );
442 UnmapViewOfFile( ptr
);
444 /* this fails on win9x but succeeds on NT */
445 SetLastError(0xdeadbeef);
446 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
447 if (ptr
) UnmapViewOfFile( ptr
);
448 else ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
450 SetLastError(0xdeadbeef);
451 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
452 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
453 UnmapViewOfFile( ptr
);
455 SetLastError(0xdeadbeef);
456 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
457 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
458 UnmapViewOfFile( ptr
);
460 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
461 FILE_MAP_READ
|FILE_MAP_WRITE
, FALSE
, 0 );
462 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
463 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
464 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
465 UnmapViewOfFile( ptr
);
468 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
469 FILE_MAP_READ
, FALSE
, 0 );
470 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
471 SetLastError(0xdeadbeef);
472 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
475 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
477 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
, 0, FALSE
, 0 );
478 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
479 SetLastError(0xdeadbeef);
480 ptr
= MapViewOfFile( map2
, 0, 0, 0, 4096 );
481 ok( !ptr
, "MapViewOfFile succeeded\n" );
482 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
484 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
485 FILE_MAP_READ
, FALSE
, 0 );
486 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
487 ptr
= MapViewOfFile( map2
, 0, 0, 0, 4096 );
488 ok( ptr
!= NULL
, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
490 else win_skip( "no access checks on win9x\n" );
492 UnmapViewOfFile( ptr
);
494 CloseHandle( mapping
);
496 /* read-only mapping */
498 SetLastError(0xdeadbeef);
499 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
500 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
502 SetLastError(0xdeadbeef);
503 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
504 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
505 UnmapViewOfFile( ptr
);
507 /* this fails on win9x but succeeds on NT */
508 SetLastError(0xdeadbeef);
509 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
510 if (ptr
) UnmapViewOfFile( ptr
);
511 else ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
513 SetLastError(0xdeadbeef);
514 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
515 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
516 UnmapViewOfFile( ptr
);
518 SetLastError(0xdeadbeef);
519 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
520 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
521 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
522 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
523 CloseHandle( mapping
);
525 /* copy-on-write mapping */
527 SetLastError(0xdeadbeef);
528 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
529 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
531 SetLastError(0xdeadbeef);
532 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
533 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
534 UnmapViewOfFile( ptr
);
536 SetLastError(0xdeadbeef);
537 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
538 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
539 UnmapViewOfFile( ptr
);
541 SetLastError(0xdeadbeef);
542 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
543 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
544 UnmapViewOfFile( ptr
);
546 SetLastError(0xdeadbeef);
547 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
548 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
549 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
550 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
551 CloseHandle( mapping
);
553 /* no access mapping */
555 SetLastError(0xdeadbeef);
556 mapping
= CreateFileMappingA( file
, NULL
, PAGE_NOACCESS
, 0, 4096, NULL
);
557 /* fails on NT but succeeds on win9x */
558 if (!mapping
) ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
561 SetLastError(0xdeadbeef);
562 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
563 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
564 UnmapViewOfFile( ptr
);
566 SetLastError(0xdeadbeef);
567 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
568 ok( !ptr
, "MapViewOfFile FILE_MAP_COPY succeeded\n" );
569 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
571 SetLastError(0xdeadbeef);
572 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
573 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
574 UnmapViewOfFile( ptr
);
576 SetLastError(0xdeadbeef);
577 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
578 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
579 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
581 CloseHandle( mapping
);
586 /* now try read-only file */
588 SetLastError(0xdeadbeef);
589 file
= CreateFileA( testfile
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0 );
590 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
592 SetLastError(0xdeadbeef);
593 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
594 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
595 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
596 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
598 SetLastError(0xdeadbeef);
599 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
600 ok( mapping
!= 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
601 CloseHandle( mapping
);
603 SetLastError(0xdeadbeef);
604 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
605 ok( mapping
!= 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
606 CloseHandle( mapping
);
609 /* now try no access file */
611 SetLastError(0xdeadbeef);
612 file
= CreateFileA( testfile
, 0, 0, NULL
, OPEN_EXISTING
, 0, 0 );
613 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
615 SetLastError(0xdeadbeef);
616 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
617 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
618 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
619 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
621 SetLastError(0xdeadbeef);
622 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
623 ok( !mapping
, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
624 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
625 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
627 SetLastError(0xdeadbeef);
628 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
629 ok( !mapping
, "CreateFileMapping PAGE_READONLY succeeded\n" );
630 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
631 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
634 DeleteFileA( testfile
);
636 SetLastError(0xdeadbeef);
638 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, name
);
639 /* nt4 doesn't have Local\\ */
640 if (!file
&& GetLastError() == ERROR_PATH_NOT_FOUND
)
643 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, name
);
645 ok( file
!= 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
647 SetLastError(0xdeadbeef);
648 mapping
= OpenFileMappingA( FILE_MAP_READ
, FALSE
, name
);
649 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
650 SetLastError(0xdeadbeef);
651 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
655 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
656 SetLastError(0xdeadbeef);
657 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
658 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
659 SetLastError(0xdeadbeef);
660 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
661 ok( size
== sizeof(info
),
662 "VirtualQuery error %u\n", GetLastError() );
663 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
664 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
665 ok( info
.AllocationProtect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.AllocationProtect
);
666 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
667 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
668 ok( info
.Protect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.Protect
);
670 else win_skip( "no access checks on win9x\n" );
671 UnmapViewOfFile( ptr
);
672 CloseHandle( mapping
);
674 SetLastError(0xdeadbeef);
675 mapping
= OpenFileMappingA( FILE_MAP_WRITE
, FALSE
, name
);
676 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
677 SetLastError(0xdeadbeef);
678 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
682 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
683 SetLastError(0xdeadbeef);
684 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
685 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
686 SetLastError(0xdeadbeef);
687 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
688 ok( size
== sizeof(info
),
689 "VirtualQuery error %u\n", GetLastError() );
690 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
691 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
692 ok( info
.AllocationProtect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.AllocationProtect
);
693 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
694 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
695 ok( info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
697 else win_skip( "no access checks on win9x\n" );
698 UnmapViewOfFile( ptr
);
699 CloseHandle( mapping
);
703 /* read/write mapping with SEC_RESERVE */
704 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
| SEC_RESERVE
, 0, MAPPING_SIZE
, NULL
);
705 ok(mapping
!= INVALID_HANDLE_VALUE
, "CreateFileMappingA failed with error %d\n", GetLastError());
707 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
708 ok(ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
710 ptr2
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
711 /* on NT ptr != ptr2 but on Win9x ptr == ptr2 */
712 ok(ptr2
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
713 trace("mapping same section resulted in views %p and %p\n", ptr
, ptr2
);
715 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
716 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
717 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
718 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
719 ok(info
.RegionSize
== MAPPING_SIZE
, "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
720 ok(info
.State
== MEM_RESERVE
, "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
721 if (info
.Type
== MEM_PRIVATE
) /* win9x is different for uncommitted mappings */
723 ok(info
.AllocationProtect
== PAGE_NOACCESS
,
724 "AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info
.AllocationProtect
);
725 ok(info
.Protect
== PAGE_NOACCESS
,
726 "Protect should have been PAGE_NOACCESS instead of 0x%x\n", info
.Protect
);
730 ok(info
.AllocationProtect
== PAGE_READWRITE
,
731 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
732 ok(info
.Protect
== 0, "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
733 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
738 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
739 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
740 ok(info
.BaseAddress
== ptr2
,
741 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
742 ok(info
.AllocationBase
== ptr2
,
743 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
744 ok(info
.AllocationProtect
== PAGE_READWRITE
,
745 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
746 ok(info
.RegionSize
== MAPPING_SIZE
,
747 "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
748 ok(info
.State
== MEM_RESERVE
,
749 "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
750 ok(info
.Protect
== 0,
751 "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
752 ok(info
.Type
== MEM_MAPPED
,
753 "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
756 ptr
= VirtualAlloc(ptr
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
757 ok(ptr
!= NULL
, "VirtualAlloc failed with error %d\n", GetLastError());
759 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
760 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
761 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
762 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
763 ok(info
.RegionSize
== 0x10000, "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
764 ok(info
.State
== MEM_COMMIT
, "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
765 ok(info
.Protect
== PAGE_READONLY
, "Protect should have been PAGE_READONLY instead of 0x%x\n", info
.Protect
);
766 if (info
.Type
== MEM_PRIVATE
) /* win9x is different for uncommitted mappings */
768 ok(info
.AllocationProtect
== PAGE_NOACCESS
,
769 "AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info
.AllocationProtect
);
773 ok(info
.AllocationProtect
== PAGE_READWRITE
,
774 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
775 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
778 /* shows that the VirtualAlloc above affects the mapping, not just the
779 * virtual memory in this process - it also affects all other processes
780 * with a view of the mapping, but that isn't tested here */
783 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
784 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
785 ok(info
.BaseAddress
== ptr2
,
786 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
787 ok(info
.AllocationBase
== ptr2
,
788 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
789 ok(info
.AllocationProtect
== PAGE_READWRITE
,
790 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
791 ok(info
.RegionSize
== 0x10000,
792 "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
793 ok(info
.State
== MEM_COMMIT
,
794 "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
795 ok(info
.Protect
== PAGE_READWRITE
,
796 "Protect should have been PAGE_READWRITE instead of 0x%x\n", info
.Protect
);
797 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
800 addr
= VirtualAlloc( ptr
, MAPPING_SIZE
, MEM_RESET
, PAGE_READONLY
);
801 ok( addr
== ptr
|| broken(!addr
&& GetLastError() == ERROR_INVALID_PARAMETER
), /* win9x */
802 "VirtualAlloc failed with error %u\n", GetLastError() );
804 ret
= VirtualFree( ptr
, 0x10000, MEM_DECOMMIT
);
805 ok( !ret
|| broken(ret
) /* win9x */, "VirtualFree succeeded\n" );
807 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "VirtualFree failed with %u\n", GetLastError() );
809 ret
= UnmapViewOfFile(ptr2
);
810 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
811 ret
= UnmapViewOfFile(ptr
);
812 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
813 CloseHandle(mapping
);
815 addr
= VirtualAlloc(NULL
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
816 ok( addr
!= NULL
, "VirtualAlloc failed with error %u\n", GetLastError() );
818 SetLastError(0xdeadbeef);
819 ok( !UnmapViewOfFile(addr
), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
820 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
821 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
822 SetLastError(0xdeadbeef);
823 ok( !UnmapViewOfFile((char *)addr
+ 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
824 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
825 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
826 SetLastError(0xdeadbeef);
827 ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
828 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
829 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
831 ok( VirtualFree(addr
, 0, MEM_RELEASE
), "VirtualFree failed\n" );
833 /* close named mapping handle without unmapping */
835 SetLastError(0xdeadbeef);
836 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
837 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
838 SetLastError(0xdeadbeef);
839 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
840 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
841 SetLastError(0xdeadbeef);
842 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
843 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
844 SetLastError(0xdeadbeef);
845 ret
= CloseHandle(map2
);
846 ok(ret
, "CloseHandle error %d\n", GetLastError());
847 SetLastError(0xdeadbeef);
848 ret
= CloseHandle(mapping
);
849 ok(ret
, "CloseHandle error %d\n", GetLastError());
851 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
852 ok( !ret
, "memory is not accessible\n" );
854 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
855 ok(ret
, "VirtualQuery error %d\n", GetLastError());
856 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
857 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
858 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
859 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
860 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
861 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
862 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
864 SetLastError(0xdeadbeef);
865 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
867 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
869 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
870 if (map2
) CloseHandle(map2
); /* FIXME: remove once Wine is fixed */
871 SetLastError(0xdeadbeef);
872 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
873 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
875 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set error %d\n", GetLastError() );
876 SetLastError(0xdeadbeef);
877 ret
= CloseHandle(mapping
);
878 ok(ret
, "CloseHandle error %d\n", GetLastError());
880 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
881 ok( !ret
, "memory is not accessible\n" );
883 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
884 ok(ret
, "VirtualQuery error %d\n", GetLastError());
885 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
886 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
887 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
888 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
889 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
890 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
891 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
893 SetLastError(0xdeadbeef);
894 ret
= UnmapViewOfFile(ptr
);
895 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
897 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
898 ok( ret
, "memory is accessible\n" );
900 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
901 ok(ret
, "VirtualQuery error %d\n", GetLastError());
902 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
903 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
904 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
905 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
906 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
907 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
909 SetLastError(0xdeadbeef);
910 file
= CreateFileA(testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
911 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
912 SetFilePointer(file
, 4096, NULL
, FILE_BEGIN
);
915 SetLastError(0xdeadbeef);
916 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
917 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
918 SetLastError(0xdeadbeef);
919 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
920 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
921 SetLastError(0xdeadbeef);
922 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
923 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
924 SetLastError(0xdeadbeef);
925 ret
= CloseHandle(map2
);
926 ok(ret
, "CloseHandle error %d\n", GetLastError());
927 SetLastError(0xdeadbeef);
928 ret
= CloseHandle(mapping
);
929 ok(ret
, "CloseHandle error %d\n", GetLastError());
931 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
932 ok( !ret
, "memory is not accessible\n" );
934 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
935 ok(ret
, "VirtualQuery error %d\n", GetLastError());
936 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
937 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
938 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
939 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
940 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
941 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
942 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
944 SetLastError(0xdeadbeef);
945 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
947 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
949 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
951 SetLastError(0xdeadbeef);
952 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
953 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
955 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set error %d\n", GetLastError() );
956 SetLastError(0xdeadbeef);
957 ret
= CloseHandle(mapping
);
958 ok(ret
, "CloseHandle error %d\n", GetLastError());
960 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
961 ok( !ret
, "memory is not accessible\n" );
963 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
964 ok(ret
, "VirtualQuery error %d\n", GetLastError());
965 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
966 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
967 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
968 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
969 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
970 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
971 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
973 SetLastError(0xdeadbeef);
974 ret
= UnmapViewOfFile(ptr
);
975 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
977 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
978 ok( ret
, "memory is accessible\n" );
980 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
981 ok(ret
, "VirtualQuery error %d\n", GetLastError());
982 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
983 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
984 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
985 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
986 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
987 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
990 DeleteFileA(testfile
);
993 static void test_NtMapViewOfSection(void)
997 static const char testfile
[] = "testfile.xxx";
998 static const char data
[] = "test data for NtMapViewOfSection";
999 char buffer
[sizeof(data
)];
1000 HANDLE file
, mapping
;
1003 DWORD status
, written
;
1004 SIZE_T size
, result
;
1005 LARGE_INTEGER offset
;
1007 if (!pNtMapViewOfSection
|| !pNtUnmapViewOfSection
)
1009 win_skip( "NtMapViewOfSection not available\n" );
1013 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1014 ok( file
!= INVALID_HANDLE_VALUE
, "Failed to create test file\n" );
1015 WriteFile( file
, data
, sizeof(data
), &written
, NULL
);
1016 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1017 SetEndOfFile( file
);
1019 /* read/write mapping */
1021 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1022 ok( mapping
!= 0, "CreateFileMapping failed\n" );
1024 hProcess
= create_target_process("sleep");
1025 ok(hProcess
!= NULL
, "Can't start process\n");
1029 offset
.QuadPart
= 0;
1030 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1031 ok( !status
, "NtMapViewOfSection failed status %x\n", status
);
1032 ok( !((ULONG_PTR
)ptr
& 0xffff), "returned memory %p is not aligned to 64k\n", ptr
);
1034 ret
= ReadProcessMemory( hProcess
, ptr
, buffer
, sizeof(buffer
), &result
);
1035 ok( ret
, "ReadProcessMemory failed\n" );
1036 ok( result
== sizeof(buffer
), "ReadProcessMemory didn't read all data (%lx)\n", result
);
1037 ok( !memcmp( buffer
, data
, sizeof(buffer
) ), "Wrong data read\n" );
1039 /* for some unknown reason NtMapViewOfSection fails with STATUS_NO_MEMORY when zero_bits != 0 ? */
1042 offset
.QuadPart
= 0;
1043 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1045 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1046 if (status
== STATUS_SUCCESS
)
1048 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1049 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1054 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1056 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1057 if (status
== STATUS_SUCCESS
)
1059 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1060 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1063 /* mapping at the same page conflicts */
1066 offset
.QuadPart
= 0;
1067 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1068 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1070 /* offset has to be aligned */
1073 offset
.QuadPart
= 1;
1074 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1075 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1077 /* ptr has to be aligned */
1078 ptr2
= (char *)ptr
+ 42;
1080 offset
.QuadPart
= 0;
1081 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1082 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1084 /* still not 64k aligned */
1085 ptr2
= (char *)ptr
+ 0x1000;
1087 offset
.QuadPart
= 0;
1088 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1089 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1091 /* zero_bits != 0 is not allowed when an address is set */
1092 ptr2
= (char *)ptr
+ 0x1000;
1094 offset
.QuadPart
= 0;
1095 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1096 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1098 ptr2
= (char *)ptr
+ 0x1000;
1100 offset
.QuadPart
= 0;
1101 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1102 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1104 ptr2
= (char *)ptr
+ 0x1001;
1106 offset
.QuadPart
= 0;
1107 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1108 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1110 ptr2
= (char *)ptr
+ 0x1000;
1112 offset
.QuadPart
= 1;
1113 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1114 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1116 if (sizeof(void *) == sizeof(int) && (!pIsWow64Process
||
1117 !pIsWow64Process( GetCurrentProcess(), &is_wow64
) || !is_wow64
))
1119 /* new memory region conflicts with previous mapping */
1122 offset
.QuadPart
= 0;
1123 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1124 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1125 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1127 ptr2
= (char *)ptr
+ 42;
1129 offset
.QuadPart
= 0;
1130 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1131 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1132 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1134 /* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
1135 ptr2
= (char *)ptr
+ 0x1000;
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_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1141 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1142 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1143 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1144 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1146 /* the address is rounded down if not on a page boundary */
1147 ptr2
= (char *)ptr
+ 0x1001;
1149 offset
.QuadPart
= 0;
1150 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1151 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1152 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1153 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1154 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1155 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1156 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1158 ptr2
= (char *)ptr
+ 0x2000;
1160 offset
.QuadPart
= 0;
1161 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1162 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1163 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1164 ok( (char *)ptr2
== (char *)ptr
+ 0x2000,
1165 "expected address %p, got %p\n", (char *)ptr
+ 0x2000, ptr2
);
1166 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1167 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1171 ptr2
= (char *)ptr
+ 0x1000;
1173 offset
.QuadPart
= 0;
1174 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1175 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1177 ok( status
== STATUS_INVALID_PARAMETER_9
, "NtMapViewOfSection returned %x\n", status
);
1180 status
= pNtUnmapViewOfSection( hProcess
, ptr
);
1181 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1183 CloseHandle( mapping
);
1184 CloseHandle( file
);
1185 DeleteFileA( testfile
);
1187 TerminateProcess(hProcess
, 0);
1188 CloseHandle(hProcess
);
1191 static void test_NtAreMappedFilesTheSame(void)
1193 static const char testfile
[] = "testfile.xxx";
1194 HANDLE file
, file2
, mapping
, map2
;
1197 char path
[MAX_PATH
];
1199 if (!pNtAreMappedFilesTheSame
)
1201 win_skip( "NtAreMappedFilesTheSame not available\n" );
1205 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1206 NULL
, CREATE_ALWAYS
, 0, 0 );
1207 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1208 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1209 SetEndOfFile( file
);
1211 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1212 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1214 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1215 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1217 file2
= CreateFileA( testfile
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1218 NULL
, OPEN_EXISTING
, 0, 0 );
1219 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1221 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1222 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1223 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1224 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1225 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1226 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1227 UnmapViewOfFile( ptr2
);
1229 ptr2
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1230 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1231 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1232 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1233 UnmapViewOfFile( ptr2
);
1234 CloseHandle( map2
);
1236 map2
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1237 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1238 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1239 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1240 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1241 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1242 UnmapViewOfFile( ptr2
);
1243 CloseHandle( map2
);
1244 CloseHandle( file2
);
1246 status
= pNtAreMappedFilesTheSame( ptr
, ptr
);
1247 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1248 "NtAreMappedFilesTheSame returned %x\n", status
);
1250 status
= pNtAreMappedFilesTheSame( ptr
, (char *)ptr
+ 30 );
1251 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1252 "NtAreMappedFilesTheSame returned %x\n", status
);
1254 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1255 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1257 status
= pNtAreMappedFilesTheSame( ptr
, (void *)0xdeadbeef );
1258 ok( status
== STATUS_CONFLICTING_ADDRESSES
|| status
== STATUS_INVALID_ADDRESS
,
1259 "NtAreMappedFilesTheSame returned %x\n", status
);
1261 status
= pNtAreMappedFilesTheSame( ptr
, NULL
);
1262 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1264 status
= pNtAreMappedFilesTheSame( ptr
, (void *)GetProcessHeap() );
1265 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1267 status
= pNtAreMappedFilesTheSame( NULL
, NULL
);
1268 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1270 ptr2
= VirtualAlloc( NULL
, 0x10000, MEM_COMMIT
, PAGE_READWRITE
);
1271 ok( ptr2
!= NULL
, "VirtualAlloc error %u\n", GetLastError() );
1272 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1273 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1274 VirtualFree( ptr2
, 0, MEM_RELEASE
);
1276 UnmapViewOfFile( ptr
);
1277 CloseHandle( mapping
);
1278 CloseHandle( file
);
1280 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
1281 GetModuleHandleA("kernel32.dll") );
1282 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1283 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1284 GetModuleHandleA("kernel32.dll") );
1285 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1286 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1287 (char *)GetModuleHandleA("kernel32.dll") + 4096 );
1288 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1290 GetSystemDirectoryA( path
, MAX_PATH
);
1291 strcat( path
, "\\kernel32.dll" );
1292 file
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1293 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1295 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1296 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1297 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1298 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1299 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1300 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1301 UnmapViewOfFile( ptr
);
1302 CloseHandle( mapping
);
1304 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1305 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1306 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
1307 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1308 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1310 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1312 file2
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1313 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1314 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1315 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1316 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 0 );
1317 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1318 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1319 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1320 UnmapViewOfFile( ptr2
);
1321 CloseHandle( map2
);
1322 CloseHandle( file2
);
1324 UnmapViewOfFile( ptr
);
1325 CloseHandle( mapping
);
1327 CloseHandle( file
);
1328 DeleteFileA( testfile
);
1331 static void test_CreateFileMapping(void)
1333 HANDLE handle
, handle2
;
1335 /* test case sensitivity */
1337 SetLastError(0xdeadbeef);
1338 handle
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1339 "Wine Test Mapping");
1340 ok( handle
!= NULL
, "CreateFileMapping failed with error %u\n", GetLastError());
1341 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1343 SetLastError(0xdeadbeef);
1344 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1345 "Wine Test Mapping");
1346 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1347 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
1348 CloseHandle( handle2
);
1350 SetLastError(0xdeadbeef);
1351 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1352 "WINE TEST MAPPING");
1353 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1354 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1355 CloseHandle( handle2
);
1357 SetLastError(0xdeadbeef);
1358 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "Wine Test Mapping");
1359 ok( handle2
!= NULL
, "OpenFileMapping failed with error %d\n", GetLastError());
1360 CloseHandle( handle2
);
1362 SetLastError(0xdeadbeef);
1363 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "WINE TEST MAPPING");
1364 ok( !handle2
, "OpenFileMapping succeeded\n");
1365 ok( GetLastError() == ERROR_FILE_NOT_FOUND
|| GetLastError() == ERROR_INVALID_NAME
/* win9x */,
1366 "wrong error %u\n", GetLastError());
1368 CloseHandle( handle
);
1371 static void test_IsBadReadPtr(void)
1374 void *ptr
= (void *)0xdeadbeef;
1377 ret
= IsBadReadPtr(NULL
, 0);
1378 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1380 ret
= IsBadReadPtr(NULL
, 1);
1381 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1383 ret
= IsBadReadPtr(ptr
, 0);
1384 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1386 ret
= IsBadReadPtr(ptr
, 1);
1387 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1389 ret
= IsBadReadPtr(&stackvar
, 0);
1390 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1392 ret
= IsBadReadPtr(&stackvar
, sizeof(char));
1393 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1396 static void test_IsBadWritePtr(void)
1399 void *ptr
= (void *)0xdeadbeef;
1402 ret
= IsBadWritePtr(NULL
, 0);
1403 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1405 ret
= IsBadWritePtr(NULL
, 1);
1406 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1408 ret
= IsBadWritePtr(ptr
, 0);
1409 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1411 ret
= IsBadWritePtr(ptr
, 1);
1412 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1414 ret
= IsBadWritePtr(&stackval
, 0);
1415 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1417 ret
= IsBadWritePtr(&stackval
, sizeof(char));
1418 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1421 static void test_IsBadCodePtr(void)
1424 void *ptr
= (void *)0xdeadbeef;
1427 ret
= IsBadCodePtr(NULL
);
1428 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1430 ret
= IsBadCodePtr(ptr
);
1431 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1433 ret
= IsBadCodePtr((void *)&stackval
);
1434 ok(ret
== FALSE
, "Expected IsBadCodePtr to return FALSE, got %d\n", ret
);
1437 static void test_write_watch(void)
1439 static const char pipename
[] = "\\\\.\\pipe\\test_write_watch_pipe";
1440 static const char testdata
[] = "Hello World";
1441 DWORD ret
, size
, old_prot
, num_bytes
;
1442 MEMORY_BASIC_INFORMATION info
;
1443 HANDLE readpipe
, writepipe
;
1444 OVERLAPPED overlapped
;
1451 if (!pGetWriteWatch
|| !pResetWriteWatch
)
1453 win_skip( "GetWriteWatch not supported\n" );
1458 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1460 (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
1462 win_skip( "MEM_WRITE_WATCH not supported\n" );
1465 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1466 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1467 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1468 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1469 ok( info
.AllocationProtect
== PAGE_READWRITE
, "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1470 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1471 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1472 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1473 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1476 SetLastError( 0xdeadbeef );
1477 ret
= pGetWriteWatch( 0, NULL
, size
, results
, &count
, &pagesize
);
1478 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1479 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
1480 broken( GetLastError() == 0xdeadbeef ), /* win98 */
1481 "wrong error %u\n", GetLastError() );
1483 SetLastError( 0xdeadbeef );
1484 ret
= pGetWriteWatch( 0, GetModuleHandleW(NULL
), size
, results
, &count
, &pagesize
);
1487 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1488 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1492 ok( count
== 0, "wrong count %lu\n", count
);
1495 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1496 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1497 ok( count
== 0, "wrong count %lu\n", count
);
1499 base
[pagesize
+ 1] = 0x44;
1502 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1503 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1504 ok( count
== 1, "wrong count %lu\n", count
);
1505 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1508 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1509 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1510 ok( count
== 1, "wrong count %lu\n", count
);
1511 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1514 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1515 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1516 ok( count
== 0, "wrong count %lu\n", count
);
1518 base
[2*pagesize
+ 3] = 0x11;
1519 base
[4*pagesize
+ 8] = 0x11;
1522 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1523 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1524 ok( count
== 2, "wrong count %lu\n", count
);
1525 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1526 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1529 ret
= pGetWriteWatch( 0, base
+ 3*pagesize
, 2*pagesize
, results
, &count
, &pagesize
);
1530 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1531 ok( count
== 1, "wrong count %lu\n", count
);
1532 ok( results
[0] == base
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1534 ret
= pResetWriteWatch( base
, 3*pagesize
);
1535 ok( !ret
, "pResetWriteWatch failed %u\n", GetLastError() );
1538 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1539 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1540 ok( count
== 1, "wrong count %lu\n", count
);
1541 ok( results
[0] == base
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1543 *(DWORD
*)(base
+ 2*pagesize
- 2) = 0xdeadbeef;
1546 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1547 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1548 ok( count
== 3, "wrong count %lu\n", count
);
1549 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1550 ok( results
[1] == base
+ 2*pagesize
, "wrong result %p\n", results
[1] );
1551 ok( results
[2] == base
+ 4*pagesize
, "wrong result %p\n", results
[2] );
1554 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1555 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1556 ok( count
== 1, "wrong count %lu\n", count
);
1557 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1560 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1561 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1562 ok( count
== 2, "wrong count %lu\n", count
);
1563 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1564 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1566 /* changing protections doesn't affect watches */
1568 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READONLY
, &old_prot
);
1569 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1570 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1572 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1573 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1574 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1575 ok( info
.RegionSize
== 3*pagesize
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1576 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1577 ok( info
.Protect
== PAGE_READONLY
, "wrong Protect 0x%x\n", info
.Protect
);
1579 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READWRITE
, &old_prot
);
1580 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1581 ok( old_prot
== PAGE_READONLY
, "wrong old prot %x\n", old_prot
);
1584 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1585 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1586 ok( count
== 2, "wrong count %lu\n", count
);
1587 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1588 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1590 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1591 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1592 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1593 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1594 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1595 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1597 /* ReadFile should trigger write watches */
1599 memset( &overlapped
, 0, sizeof(overlapped
) );
1600 overlapped
.hEvent
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1602 readpipe
= CreateNamedPipeA( pipename
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_INBOUND
,
1603 PIPE_TYPE_BYTE
| PIPE_WAIT
, 1, 1024, 1024,
1604 NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1605 ok( readpipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipeA failed %u\n", GetLastError() );
1607 success
= ConnectNamedPipe( readpipe
, &overlapped
);
1608 ok( !success
, "ConnectNamedPipe unexpectedly succeeded\n" );
1609 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1611 writepipe
= CreateFileA( pipename
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
1612 ok( writepipe
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %u\n", GetLastError() );
1614 ret
= WaitForSingleObject( overlapped
.hEvent
, 1000 );
1615 ok( ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", ret
);
1617 memset( base
, 0, size
);
1620 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1621 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1622 ok( count
== 16, "wrong count %lu\n", count
);
1624 success
= ReadFile( readpipe
, base
, size
, NULL
, &overlapped
);
1625 ok( !success
, "ReadFile unexpectedly succeeded\n" );
1626 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1629 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1630 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1631 ok( count
== 16, "wrong count %lu\n", count
);
1634 success
= WriteFile( writepipe
, testdata
, sizeof(testdata
), &num_bytes
, NULL
);
1635 ok( success
, "WriteFile failed %u\n", GetLastError() );
1636 ok( num_bytes
== sizeof(testdata
), "wrong number of bytes written\n" );
1639 success
= GetOverlappedResult( readpipe
, &overlapped
, &num_bytes
, TRUE
);
1640 todo_wine
ok( success
, "GetOverlappedResult failed %u\n", GetLastError() );
1641 todo_wine
ok( num_bytes
== sizeof(testdata
), "wrong number of bytes read\n" );
1642 todo_wine
ok( !memcmp( base
, testdata
, sizeof(testdata
)), "didn't receive expected data\n" );
1645 memset( results
, 0, sizeof(results
) );
1646 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1647 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1648 todo_wine
ok( count
== 1, "wrong count %lu\n", count
);
1649 todo_wine
ok( results
[0] == base
, "wrong result %p\n", results
[0] );
1651 CloseHandle( readpipe
);
1652 CloseHandle( writepipe
);
1653 CloseHandle( overlapped
.hEvent
);
1655 /* some invalid parameter tests */
1657 SetLastError( 0xdeadbeef );
1659 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1662 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1663 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1665 SetLastError( 0xdeadbeef );
1666 ret
= pGetWriteWatch( 0, base
, size
, results
, NULL
, &pagesize
);
1667 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1668 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1670 SetLastError( 0xdeadbeef );
1672 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, NULL
);
1673 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1674 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1676 SetLastError( 0xdeadbeef );
1678 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1679 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1680 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1682 SetLastError( 0xdeadbeef );
1684 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1685 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1686 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1688 SetLastError( 0xdeadbeef );
1690 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1691 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1692 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1694 SetLastError( 0xdeadbeef );
1696 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1697 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1698 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1700 SetLastError( 0xdeadbeef );
1702 ret
= pGetWriteWatch( 0, base
, size
* 2, results
, &count
, &pagesize
);
1703 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1704 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1706 SetLastError( 0xdeadbeef );
1708 ret
= pGetWriteWatch( 0, base
+ size
- pagesize
, pagesize
+ 1, results
, &count
, &pagesize
);
1709 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1710 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1712 SetLastError( 0xdeadbeef );
1713 ret
= pResetWriteWatch( base
, 0 );
1714 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1715 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1717 SetLastError( 0xdeadbeef );
1718 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1719 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1720 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1722 else /* win98 is completely different */
1724 SetLastError( 0xdeadbeef );
1726 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1727 ok( ret
== ERROR_INVALID_PARAMETER
, "GetWriteWatch succeeded %u\n", ret
);
1728 ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
1731 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1732 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1735 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1736 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1739 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1740 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1742 ret
= pResetWriteWatch( base
, 0 );
1743 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1745 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1746 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1749 VirtualFree( base
, 0, MEM_FREE
);
1751 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1752 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1753 VirtualFree( base
, 0, MEM_FREE
);
1755 base
= VirtualAlloc( 0, size
, MEM_WRITE_WATCH
, PAGE_READWRITE
);
1756 ok( !base
, "VirtualAlloc succeeded\n" );
1757 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1759 /* initial protect doesn't matter */
1761 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_NOACCESS
);
1762 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1763 base
= VirtualAlloc( base
, size
, MEM_COMMIT
, PAGE_NOACCESS
);
1764 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1767 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1768 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1769 ok( count
== 0, "wrong count %lu\n", count
);
1771 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_READWRITE
, &old_prot
);
1772 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1773 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
1775 base
[5*pagesize
+ 200] = 3;
1777 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_NOACCESS
, &old_prot
);
1778 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1779 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1782 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1783 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1784 ok( count
== 1, "wrong count %lu\n", count
);
1785 ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1787 ret
= VirtualFree( base
, size
, MEM_DECOMMIT
);
1788 ok( ret
, "VirtualFree failed %u\n", GetLastError() );
1791 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1792 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1793 ok( count
== 1 || broken(count
== 0), /* win98 */
1794 "wrong count %lu\n", count
);
1795 if (count
) ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1797 VirtualFree( base
, 0, MEM_FREE
);
1802 static DWORD num_guard_page_calls
;
1804 static DWORD
guard_page_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
1805 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
1807 trace( "exception: %08x flags:%x addr:%p\n",
1808 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
);
1810 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
1811 ok( rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
, "ExceptionCode is %08x instead of %08x\n",
1812 rec
->ExceptionCode
, STATUS_GUARD_PAGE_VIOLATION
);
1814 num_guard_page_calls
++;
1815 *(int *)rec
->ExceptionInformation
[1] += 0x100;
1817 return ExceptionContinueExecution
;
1820 static void test_guard_page(void)
1822 EXCEPTION_REGISTRATION_RECORD frame
;
1823 MEMORY_BASIC_INFORMATION info
;
1824 DWORD ret
, size
, old_prot
;
1825 int *value
, old_value
;
1834 win_skip( "NtCurrentTeb not supported\n" );
1839 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
1840 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1841 value
= (int *)base
;
1843 /* verify info structure */
1844 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1845 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
1846 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1847 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1848 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1849 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1850 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
1851 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1853 /* put some initial value into the memory */
1854 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
1855 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1856 ok( old_prot
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong old prot %x\n", old_prot
);
1861 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
1862 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1863 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1865 /* test behaviour of VirtualLock - first attempt should fail */
1866 SetLastError( 0xdeadbeef );
1867 success
= VirtualLock( base
, size
);
1868 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
1870 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
1872 success
= VirtualLock( base
, size
);
1874 ok( success
, "VirtualLock failed %u\n", GetLastError() );
1877 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
1878 success
= VirtualUnlock( base
, size
);
1879 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
1882 /* check info structure again, PAGE_GUARD should be removed now */
1883 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1884 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
1885 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1886 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1887 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1888 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1890 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1891 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1893 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
1894 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1896 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1898 /* test directly accessing the memory - we need to setup an exception handler first */
1899 frame
.Handler
= guard_page_handler
;
1900 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
1901 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
1903 num_guard_page_calls
= 0;
1904 old_value
= *value
; /* exception handler increments value by 0x100 */
1906 ok( old_value
== 0x101, "memory block contains wrong value, expected 0x101, got 0x%x\n", old_value
);
1907 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
1909 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
1911 /* check info structure again, PAGE_GUARD should be removed now */
1912 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1913 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
1914 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1916 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
1917 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1918 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1920 /* test accessing second integer in memory */
1921 frame
.Handler
= guard_page_handler
;
1922 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
1923 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
1925 num_guard_page_calls
= 0;
1926 old_value
= *(value
+ 1);
1927 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
1928 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
1929 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
1931 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
1933 success
= VirtualLock( base
, size
);
1934 ok( success
, "VirtualLock failed %u\n", GetLastError() );
1937 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
1938 success
= VirtualUnlock( base
, size
);
1939 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
1942 VirtualFree( base
, 0, MEM_FREE
);
1944 /* combined guard page / write watch tests */
1945 if (!pGetWriteWatch
|| !pResetWriteWatch
)
1947 win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" );
1951 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
| PAGE_GUARD
);
1952 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
1954 win_skip( "MEM_WRITE_WATCH not supported\n" );
1957 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1958 value
= (int *)base
;
1960 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1961 ok( ret
, "VirtualQuery failed %u\n", GetLastError() );
1962 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1963 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1964 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1965 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1966 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
1967 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1970 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1971 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1972 ok( count
== 0, "wrong count %lu\n", count
);
1974 /* writing to a page should trigger should trigger guard page, even if write watch is set */
1975 frame
.Handler
= guard_page_handler
;
1976 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
1977 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
1979 num_guard_page_calls
= 0;
1982 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
1984 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
1987 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1988 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1989 ok( count
== 1, "wrong count %lu\n", count
);
1990 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
1992 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
1993 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1995 /* write watch is triggered from inside of the guard page handler */
1996 frame
.Handler
= guard_page_handler
;
1997 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
1998 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2000 num_guard_page_calls
= 0;
2001 old_value
= *(value
+ 1); /* doesn't trigger write watch */
2002 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
2003 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2004 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2006 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2009 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2010 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2011 ok( count
== 1, "wrong count %lu\n", count
);
2012 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2014 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2015 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2017 /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */
2018 SetLastError( 0xdeadbeef );
2019 success
= VirtualLock( base
, size
);
2020 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
2022 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
2025 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
2026 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2027 ok( count
== 0, "wrong count %lu\n", count
);
2029 success
= VirtualLock( base
, size
);
2031 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2034 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2035 success
= VirtualUnlock( base
, size
);
2036 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2040 results
[0] = (void *)0xdeadbeef;
2041 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2042 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2044 ok( count
== 1 || broken(count
== 0) /* Windows 8 */, "wrong count %lu\n", count
);
2046 ok( results
[0] == base
|| broken(results
[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results
[0] );
2048 VirtualFree( base
, 0, MEM_FREE
);
2051 static DWORD WINAPI
stack_commit_func( void *arg
)
2053 volatile char *p
= (char *)&p
;
2055 /* trigger all guard pages, to ensure that the pages are committed */
2056 while (p
>= (char *)pNtCurrentTeb()->DeallocationStack
+ 3 * 0x1000)
2062 ok( arg
== (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg
);
2066 static void test_stack_commit(void)
2068 static const char code_call_on_stack
[] = {
2069 0x55, /* pushl %ebp */
2070 0x56, /* pushl %esi */
2071 0x89, 0xe6, /* movl %esp,%esi */
2072 0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */
2073 0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */
2074 0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */
2075 0x83, 0xe0, 0xf0, /* andl $~15,%eax */
2076 0x83, 0xe8, 0x0c, /* subl $12,%eax */
2077 0x89, 0xc4, /* movl %eax,%esp */
2078 0x52, /* pushl %edx */
2079 0x31, 0xed, /* xorl %ebp,%ebp */
2080 0xff, 0xd1, /* call *%ecx */
2081 0x89, 0xf4, /* movl %esi,%esp */
2082 0x5e, /* popl %esi */
2083 0x5d, /* popl %ebp */
2084 0xc2, 0x0c, 0x00 }; /* ret $12 */
2086 DWORD (WINAPI
*call_on_stack
)( DWORD (WINAPI
*func
)(void *), void *arg
, void *stack
);
2087 void *old_stack
, *old_stack_base
, *old_stack_limit
;
2088 void *new_stack
, *new_stack_base
;
2093 win_skip( "NtCurrentTeb not supported\n" );
2097 call_on_stack
= VirtualAlloc( 0, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
2098 ok( call_on_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2099 memcpy( call_on_stack
, code_call_on_stack
, sizeof(code_call_on_stack
) );
2101 /* allocate a new stack, only the first guard page is committed */
2102 new_stack
= VirtualAlloc( 0, 0x400000, MEM_RESERVE
, PAGE_READWRITE
);
2103 ok( new_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2104 new_stack_base
= (char *)new_stack
+ 0x400000;
2105 VirtualAlloc( (char *)new_stack_base
- 0x1000, 0x1000, MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
2107 old_stack
= pNtCurrentTeb()->DeallocationStack
;
2108 old_stack_base
= pNtCurrentTeb()->Tib
.StackBase
;
2109 old_stack_limit
= pNtCurrentTeb()->Tib
.StackLimit
;
2111 pNtCurrentTeb()->DeallocationStack
= new_stack
;
2112 pNtCurrentTeb()->Tib
.StackBase
= new_stack_base
;
2113 pNtCurrentTeb()->Tib
.StackLimit
= new_stack_base
;
2115 result
= call_on_stack( stack_commit_func
, (void *)0xdeadbeef, new_stack_base
);
2116 ok( result
== 42, "expected 42, got %u\n", result
);
2118 pNtCurrentTeb()->DeallocationStack
= old_stack
;
2119 pNtCurrentTeb()->Tib
.StackBase
= old_stack_base
;
2120 pNtCurrentTeb()->Tib
.StackLimit
= old_stack_limit
;
2122 VirtualFree( new_stack
, 0, MEM_FREE
);
2123 VirtualFree( call_on_stack
, 0, MEM_FREE
);
2126 DWORD num_execute_fault_calls
;
2128 static DWORD
execute_fault_seh_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
2129 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
2131 ULONG flags
= MEM_EXECUTE_OPTION_ENABLE
;
2134 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2135 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2136 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2138 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2139 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
|| rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
,
2140 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec
->ExceptionCode
);
2142 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &flags
, sizeof(flags
), NULL
);
2144 if (rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
)
2147 err
= IsProcessorFeaturePresent( PF_NX_ENABLED
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2148 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2149 (DWORD
)rec
->ExceptionInformation
[0], err
);
2151 num_guard_page_calls
++;
2153 else if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2158 err
= (flags
& MEM_EXECUTE_OPTION_DISABLE
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2159 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2160 (DWORD
)rec
->ExceptionInformation
[0], err
);
2162 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2163 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2164 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2166 num_execute_fault_calls
++;
2169 return ExceptionContinueExecution
;
2172 static LONG CALLBACK
execute_fault_vec_handler( EXCEPTION_POINTERS
*ExceptionInfo
)
2174 PEXCEPTION_RECORD rec
= ExceptionInfo
->ExceptionRecord
;
2178 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2179 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2180 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2182 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2183 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
,
2184 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec
->ExceptionCode
);
2186 if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2187 num_execute_fault_calls
++;
2189 if (rec
->ExceptionInformation
[0] == EXCEPTION_READ_FAULT
)
2190 return EXCEPTION_CONTINUE_SEARCH
;
2192 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2193 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2194 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
2196 return EXCEPTION_CONTINUE_EXECUTION
;
2199 static inline DWORD
send_message_excpt( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2201 EXCEPTION_REGISTRATION_RECORD frame
;
2204 frame
.Handler
= execute_fault_seh_handler
;
2205 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
2206 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2208 num_guard_page_calls
= num_execute_fault_calls
= 0;
2209 ret
= SendMessageA( hWnd
, uMsg
, wParam
, lParam
);
2211 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2216 static inline DWORD
call_proc_excpt( DWORD (CALLBACK
*code
)(void *), void *arg
)
2218 EXCEPTION_REGISTRATION_RECORD frame
;
2221 frame
.Handler
= execute_fault_seh_handler
;
2222 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
2223 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2225 num_guard_page_calls
= num_execute_fault_calls
= 0;
2228 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2233 static LRESULT CALLBACK
jmp_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2235 if (uMsg
== WM_USER
)
2238 return DefWindowProcA( hWnd
, uMsg
, wParam
, lParam
);
2241 static LRESULT CALLBACK
atl_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2243 DWORD arg
= (DWORD
)hWnd
;
2244 if (uMsg
== WM_USER
)
2245 ok( arg
== 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg
);
2247 ok( arg
!= 0x11223344, "arg is unexpectedly 0x11223344\n" );
2251 static DWORD CALLBACK
atl5_test_func( void )
2256 static void test_atl_thunk_emulation( ULONG dep_flags
)
2258 static const char code_jmp
[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
2259 static const char code_atl1
[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2260 static const char code_atl2
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2261 static const char code_atl3
[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1};
2262 static const char code_atl4
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
2263 static const char code_atl5
[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04};
2264 static const char cls_name
[] = "atl_thunk_class";
2265 DWORD ret
, size
, old_prot
;
2266 ULONG old_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2267 BOOL success
, restore_flags
= FALSE
;
2277 win_skip( "NtCurrentTeb not supported\n" );
2281 trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2283 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
), NULL
);
2284 if (old_flags
!= dep_flags
)
2286 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &dep_flags
, sizeof(dep_flags
) );
2287 if (ret
== STATUS_INVALID_INFO_CLASS
) /* Windows 2000 */
2289 win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2292 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2293 restore_flags
= TRUE
;
2297 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
2298 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2300 /* Check result of GetProcessDEPPolicy */
2301 if (!pGetProcessDEPPolicy
)
2302 win_skip( "GetProcessDEPPolicy not supported\n" );
2305 BOOL (WINAPI
*get_dep_policy
)(HANDLE
, LPDWORD
, PBOOL
) = (void *)base
;
2306 BOOL policy_permanent
= 0xdeadbeef;
2307 DWORD policy_flags
= 0xdeadbeef;
2309 /* GetProcessDEPPolicy crashes on Windows when a NULL pointer is passed.
2310 * Moreover this function has a bug on Windows 8, which has the effect that
2311 * policy_permanent is set to the content of the CL register instead of 0,
2312 * when the policy is not permanent. To detect that we use an assembler
2313 * wrapper to call the function. */
2315 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2316 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)pGetProcessDEPPolicy
- (DWORD_PTR
)(base
+ 10);
2318 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2319 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2321 success
= get_dep_policy( GetCurrentProcess(), &policy_flags
, &policy_permanent
);
2322 ok( success
, "GetProcessDEPPolicy failed %u\n", GetLastError() );
2325 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2326 ret
|= PROCESS_DEP_ENABLE
;
2327 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
)
2328 ret
|= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
;
2330 ok( policy_flags
== ret
, "expected policy flags %d, got %d\n", ret
, policy_flags
);
2331 ok( !policy_permanent
|| broken(policy_permanent
== 0x44),
2332 "expected policy permanent FALSE, got %d\n", policy_permanent
);
2335 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2336 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2338 /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
2339 * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
2340 * where it is active, so that application which depend on that still work properly.
2341 * We have no exception handler enabled yet, so give proper EXECUTE permissions to
2342 * prevent crashes while creating the window. */
2344 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2345 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2347 memset( &wc
, 0, sizeof(wc
) );
2348 wc
.cbSize
= sizeof(wc
);
2349 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2350 wc
.hInstance
= GetModuleHandleA( 0 );
2351 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2352 wc
.hbrBackground
= NULL
;
2353 wc
.lpszClassName
= cls_name
;
2354 wc
.lpfnWndProc
= (WNDPROC
)base
;
2355 success
= RegisterClassExA(&wc
) != 0;
2356 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2358 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2359 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2361 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2362 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2364 /* At first try with an instruction which is not recognized as proper ATL thunk
2365 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2366 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2368 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2369 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2371 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2372 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2373 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2374 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !IsProcessorFeaturePresent( PF_NX_ENABLED
))
2376 trace( "DEP hardware support is not available\n" );
2377 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2378 dep_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2380 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2382 trace( "DEP hardware support is available\n" );
2383 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2386 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2388 /* Now a bit more complicated, the page containing the code is protected with
2389 * PAGE_GUARD memory protection. */
2391 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2392 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2394 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2395 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2396 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2397 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2398 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2400 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2402 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2403 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2404 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2405 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2407 /* Now test with a proper ATL thunk instruction. */
2409 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2410 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2412 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2413 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2415 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2416 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2418 /* Try executing with PAGE_READWRITE protection. */
2420 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2421 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2423 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2424 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2425 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2426 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2427 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2429 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2431 /* Now a bit more complicated, the page containing the code is protected with
2432 * PAGE_GUARD memory protection. */
2434 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2435 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2437 /* the same, but with PAGE_GUARD set */
2438 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2439 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2440 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2441 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2442 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2444 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2446 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2447 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2448 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2449 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2451 /* The following test shows that on Windows, even a vectored exception handler
2452 * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */
2454 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !(dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2456 if (pRtlAddVectoredExceptionHandler
&& pRtlRemoveVectoredExceptionHandler
)
2458 PVOID vectored_handler
;
2460 success
= VirtualProtect( base
, size
, PAGE_NOACCESS
, &old_prot
);
2461 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2463 vectored_handler
= pRtlAddVectoredExceptionHandler( TRUE
, &execute_fault_vec_handler
);
2464 ok( vectored_handler
!= 0, "RtlAddVectoredExceptionHandler failed\n" );
2466 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2468 pRtlRemoveVectoredExceptionHandler( vectored_handler
);
2470 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2471 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2474 win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" );
2477 /* Test alternative ATL thunk instructions. */
2479 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2480 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 10);
2482 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2483 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2485 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2486 /* FIXME: we don't check the content of the register ECX yet */
2487 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2488 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2489 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2490 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2492 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2494 memcpy( base
, code_atl3
, sizeof(code_atl3
) );
2495 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2497 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2498 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2500 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2501 /* FIXME: we don't check the content of the registers ECX/EDX yet */
2502 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2503 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2504 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2505 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2507 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2509 memcpy( base
, code_atl4
, sizeof(code_atl4
) );
2510 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2512 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2513 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2515 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2516 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2517 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2518 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2519 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2520 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2521 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2522 ok( num_execute_fault_calls
== 0 || broken(num_execute_fault_calls
== 1) /* Windows XP */,
2523 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2525 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2527 memcpy( base
, code_atl5
, sizeof(code_atl5
) );
2529 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2530 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2532 ret
= (DWORD_PTR
)atl5_test_func
;
2533 ret
= call_proc_excpt( (void *)base
, &ret
- 1 );
2534 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2535 ok( ret
== 44, "call returned wrong result, expected 44, got %d\n", ret
);
2536 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2537 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2538 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2539 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2540 ok( num_execute_fault_calls
== 0 || broken(num_execute_fault_calls
== 1) /* Windows XP */,
2541 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2543 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2545 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2547 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2548 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2550 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2551 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2553 DestroyWindow( hWnd
);
2555 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2556 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2558 VirtualFree( base
, 0, MEM_FREE
);
2560 /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */
2562 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
2563 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
2565 win_skip( "MEM_WRITE_WATCH not supported\n" );
2568 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2571 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2572 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2573 ok( count
== 0, "wrong count %lu\n", count
);
2575 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2576 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2579 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2580 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2581 ok( count
== 1, "wrong count %lu\n", count
);
2582 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2584 /* Create a new window class and associcated Window (see above) */
2586 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2587 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2589 memset( &wc
, 0, sizeof(wc
) );
2590 wc
.cbSize
= sizeof(wc
);
2591 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2592 wc
.hInstance
= GetModuleHandleA( 0 );
2593 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2594 wc
.hbrBackground
= NULL
;
2595 wc
.lpszClassName
= cls_name
;
2596 wc
.lpfnWndProc
= (WNDPROC
)base
;
2597 success
= RegisterClassExA(&wc
) != 0;
2598 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2600 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2601 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2603 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2604 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2607 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2608 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2609 ok( count
== 0, "wrong count %lu\n", count
);
2611 /* At first try with an instruction which is not recognized as proper ATL thunk
2612 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2613 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2615 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2616 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2618 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2619 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2620 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2621 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2622 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2624 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2627 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2628 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2629 ok( count
== 0, "wrong count %lu\n", count
);
2631 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2632 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2633 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2634 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2636 /* Now a bit more complicated, the page containing the code is protected with
2637 * PAGE_GUARD memory protection. */
2639 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2640 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2642 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2643 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2644 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2645 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2646 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2648 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2650 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2651 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2652 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2653 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2656 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2657 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2658 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2660 /* Now test with a proper ATL thunk instruction. */
2662 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2663 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2666 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2667 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2668 ok( count
== 1, "wrong count %lu\n", count
);
2669 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2671 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2672 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2674 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2675 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2677 /* Try executing with PAGE_READWRITE protection. */
2679 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2680 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2682 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2683 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2684 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2685 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2686 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2688 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2691 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2692 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2693 ok( count
== 0, "wrong count %lu\n", count
);
2695 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2696 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2697 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2698 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2699 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2701 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2703 /* Now a bit more complicated, the page containing the code is protected with
2704 * PAGE_GUARD memory protection. */
2706 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2707 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2709 /* the same, but with PAGE_GUARD set */
2710 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2711 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2712 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2713 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2714 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2716 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2718 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2719 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2720 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2721 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2724 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2725 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2726 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2728 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2730 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2731 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2734 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2735 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2736 ok( count
== 1, "wrong count %lu\n", count
);
2737 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2739 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2740 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2742 DestroyWindow( hWnd
);
2744 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2745 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2747 VirtualFree( base
, 0, MEM_FREE
);
2752 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
) );
2753 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2757 #endif /* __i386__ */
2759 static void test_VirtualProtect(void)
2761 static const struct test_data
2763 DWORD prot_set
, prot_get
;
2766 { 0, 0 }, /* 0x00 */
2767 { PAGE_NOACCESS
, PAGE_NOACCESS
}, /* 0x01 */
2768 { PAGE_READONLY
, PAGE_READONLY
}, /* 0x02 */
2769 { PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x03 */
2770 { PAGE_READWRITE
, PAGE_READWRITE
}, /* 0x04 */
2771 { PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x05 */
2772 { PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x06 */
2773 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x07 */
2774 { PAGE_WRITECOPY
, 0 }, /* 0x08 */
2775 { PAGE_WRITECOPY
| PAGE_NOACCESS
, 0 }, /* 0x09 */
2776 { PAGE_WRITECOPY
| PAGE_READONLY
, 0 }, /* 0x0a */
2777 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, 0 }, /* 0x0b */
2778 { PAGE_WRITECOPY
| PAGE_READWRITE
, 0 }, /* 0x0c */
2779 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x0d */
2780 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x0e */
2781 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x0f */
2783 { PAGE_EXECUTE
, PAGE_EXECUTE
}, /* 0x10 */
2784 { PAGE_EXECUTE_READ
, PAGE_EXECUTE_READ
}, /* 0x20 */
2785 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x30 */
2786 { PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
2787 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0x50 */
2788 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0x60 */
2789 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x70 */
2790 { PAGE_EXECUTE_WRITECOPY
, 0 }, /* 0x80 */
2791 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, 0 }, /* 0x90 */
2792 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, 0 }, /* 0xa0 */
2793 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0xb0 */
2794 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, 0 }, /* 0xc0 */
2795 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0xd0 */
2796 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0xe0 */
2797 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 } /* 0xf0 */
2800 DWORD ret
, old_prot
, rw_prot
, exec_prot
, i
, j
;
2801 MEMORY_BASIC_INFORMATION info
;
2808 trace("system page size %#x\n", si
.dwPageSize
);
2810 SetLastError(0xdeadbeef);
2811 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_RESERVE
| MEM_COMMIT
, PAGE_NOACCESS
);
2812 ok(base
!= NULL
, "VirtualAlloc failed %d\n", GetLastError());
2814 SetLastError(0xdeadbeef);
2815 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_READONLY
, NULL
);
2816 ok(!ret
, "VirtualProtect should fail\n");
2817 ok(GetLastError() == ERROR_NOACCESS
, "expected ERROR_NOACCESS, got %d\n", GetLastError());
2818 old_prot
= 0xdeadbeef;
2819 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2820 ok(ret
, "VirtualProtect failed %d\n", GetLastError());
2821 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2824 size
= si
.dwPageSize
;
2825 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_READONLY
, NULL
);
2826 ok(status
== STATUS_ACCESS_VIOLATION
, "NtProtectVirtualMemory should fail, got %08x\n", status
);
2828 size
= si
.dwPageSize
;
2829 old_prot
= 0xdeadbeef;
2830 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_NOACCESS
, &old_prot
);
2831 ok(status
== STATUS_SUCCESS
, "NtProtectVirtualMemory should succeed, got %08x\n", status
);
2832 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2834 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
2836 SetLastError(0xdeadbeef);
2837 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2838 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2839 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2840 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2841 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
2842 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2843 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2844 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2845 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2847 old_prot
= 0xdeadbeef;
2848 SetLastError(0xdeadbeef);
2849 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot_set
, &old_prot
);
2852 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2853 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
2855 SetLastError(0xdeadbeef);
2856 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2857 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2858 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2859 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2860 ok(info
.Protect
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_get
);
2861 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2862 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2863 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2864 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2868 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
2869 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
2872 old_prot
= 0xdeadbeef;
2873 SetLastError(0xdeadbeef);
2874 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2875 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2877 ok(old_prot
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_get
);
2879 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
2884 for (i
= 0; i
<= 4; i
++)
2888 for (j
= 0; j
<= 4; j
++)
2890 DWORD prot
= exec_prot
| rw_prot
;
2892 SetLastError(0xdeadbeef);
2893 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, prot
);
2894 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
2896 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
2897 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2901 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
2903 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
2904 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2908 ok(ptr
!= NULL
, "VirtualAlloc(%02x) error %d\n", prot
, GetLastError());
2909 ok(ptr
== base
, "expected %p, got %p\n", base
, ptr
);
2913 SetLastError(0xdeadbeef);
2914 ret
= VirtualProtect(base
, si
.dwPageSize
, prot
, &old_prot
);
2915 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
2917 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
2918 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2922 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
2924 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
2925 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2928 ok(ret
, "VirtualProtect(%02x) error %d\n", prot
, GetLastError());
2934 exec_prot
= 1 << (i
+ 4);
2937 VirtualFree(base
, 0, MEM_FREE
);
2940 static BOOL
is_mem_writable(DWORD prot
)
2942 switch (prot
& 0xff)
2944 case PAGE_READWRITE
:
2945 case PAGE_WRITECOPY
:
2946 case PAGE_EXECUTE_READWRITE
:
2947 case PAGE_EXECUTE_WRITECOPY
:
2955 static void test_VirtualAlloc_protection(void)
2957 static const struct test_data
2963 { 0, FALSE
}, /* 0x00 */
2964 { PAGE_NOACCESS
, TRUE
}, /* 0x01 */
2965 { PAGE_READONLY
, TRUE
}, /* 0x02 */
2966 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x03 */
2967 { PAGE_READWRITE
, TRUE
}, /* 0x04 */
2968 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x05 */
2969 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x06 */
2970 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x07 */
2971 { PAGE_WRITECOPY
, FALSE
}, /* 0x08 */
2972 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
}, /* 0x09 */
2973 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
}, /* 0x0a */
2974 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
}, /* 0x0b */
2975 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
}, /* 0x0c */
2976 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x0d */
2977 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x0e */
2978 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x0f */
2980 { PAGE_EXECUTE
, TRUE
}, /* 0x10 */
2981 { PAGE_EXECUTE_READ
, TRUE
}, /* 0x20 */
2982 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x30 */
2983 { PAGE_EXECUTE_READWRITE
, TRUE
}, /* 0x40 */
2984 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0x50 */
2985 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0x60 */
2986 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x70 */
2987 { PAGE_EXECUTE_WRITECOPY
, FALSE
}, /* 0x80 */
2988 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
}, /* 0x90 */
2989 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xa0 */
2990 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0xb0 */
2991 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
}, /* 0xc0 */
2992 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0xd0 */
2993 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xe0 */
2994 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
} /* 0xf0 */
2998 MEMORY_BASIC_INFORMATION info
;
3002 trace("system page size %#x\n", si
.dwPageSize
);
3004 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3006 SetLastError(0xdeadbeef);
3007 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3011 ok(base
!= NULL
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3013 SetLastError(0xdeadbeef);
3014 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3015 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3016 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3017 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3018 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3019 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3020 ok(info
.AllocationProtect
== td
[i
].prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, td
[i
].prot
);
3021 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3022 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
3024 if (is_mem_writable(info
.Protect
))
3028 SetLastError(0xdeadbeef);
3029 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3030 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3031 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3034 SetLastError(0xdeadbeef);
3035 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3036 ok(ptr
== base
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3038 VirtualFree(base
, 0, MEM_FREE
);
3042 ok(!base
, "%d: VirtualAlloc should fail\n", i
);
3043 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3048 static void test_CreateFileMapping_protection(void)
3050 static const struct test_data
3054 DWORD prot_after_write
;
3057 { 0, FALSE
, 0 }, /* 0x00 */
3058 { PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x01 */
3059 { PAGE_READONLY
, TRUE
, PAGE_READONLY
}, /* 0x02 */
3060 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x03 */
3061 { PAGE_READWRITE
, TRUE
, PAGE_READWRITE
}, /* 0x04 */
3062 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x05 */
3063 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x06 */
3064 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x07 */
3065 { PAGE_WRITECOPY
, TRUE
, PAGE_READWRITE
}, /* 0x08 */
3066 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x09 */
3067 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0a */
3068 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0b */
3069 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0x0c */
3070 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0d */
3071 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0e */
3072 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0f */
3074 { PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE
}, /* 0x10 */
3075 { PAGE_EXECUTE_READ
, TRUE
, PAGE_EXECUTE_READ
}, /* 0x20 */
3076 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE_READ
}, /* 0x30 */
3077 { PAGE_EXECUTE_READWRITE
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
3078 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x50 */
3079 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0x60 */
3080 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x70 */
3081 { PAGE_EXECUTE_WRITECOPY
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x80 */
3082 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x90 */
3083 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xa0 */
3084 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xb0 */
3085 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0xc0 */
3086 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xd0 */
3087 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xe0 */
3088 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
} /* 0xf0 */
3091 DWORD ret
, i
, alloc_prot
, prot
, old_prot
;
3092 MEMORY_BASIC_INFORMATION info
;
3094 char temp_path
[MAX_PATH
];
3095 char file_name
[MAX_PATH
];
3097 BOOL page_exec_supported
= TRUE
;
3100 trace("system page size %#x\n", si
.dwPageSize
);
3102 GetTempPathA(MAX_PATH
, temp_path
);
3103 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3105 SetLastError(0xdeadbeef);
3106 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3107 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3108 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3109 SetEndOfFile(hfile
);
3111 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3113 SetLastError(0xdeadbeef);
3114 hmap
= CreateFileMappingW(hfile
, NULL
, td
[i
].prot
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3120 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, td
[i
].prot
, GetLastError());
3121 /* NT4 and win2k don't support EXEC on file mappings */
3122 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3124 page_exec_supported
= FALSE
;
3125 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3128 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3129 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3131 page_exec_supported
= FALSE
;
3132 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3136 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, td
[i
].prot
, GetLastError());
3138 base
= MapViewOfFile(hmap
, FILE_MAP_READ
, 0, 0, 0);
3139 ok(base
!= NULL
, "%d: MapViewOfFile failed %d\n", i
, GetLastError());
3141 SetLastError(0xdeadbeef);
3142 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3143 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3144 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3145 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3146 ok(info
.Protect
== PAGE_READONLY
, "%d: got %#x != expected PAGE_READONLY\n", i
, info
.Protect
);
3147 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3148 ok(info
.AllocationProtect
== PAGE_READONLY
, "%d: %#x != PAGE_READONLY\n", i
, info
.AllocationProtect
);
3149 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3150 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3152 if (is_mem_writable(info
.Protect
))
3156 SetLastError(0xdeadbeef);
3157 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3158 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3159 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3162 SetLastError(0xdeadbeef);
3163 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3164 ok(!ptr
, "%d: VirtualAlloc(%02x) should fail\n", i
, td
[i
].prot
);
3165 /* FIXME: remove once Wine is fixed */
3166 if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3168 ok(GetLastError() == ERROR_ACCESS_DENIED
, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i
, GetLastError());
3170 ok(GetLastError() == ERROR_ACCESS_DENIED
, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i
, GetLastError());
3172 SetLastError(0xdeadbeef);
3173 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3174 if (td
[i
].prot
== PAGE_READONLY
|| td
[i
].prot
== PAGE_WRITECOPY
)
3175 ok(ret
, "%d: VirtualProtect(%02x) error %d\n", i
, td
[i
].prot
, GetLastError());
3178 ok(!ret
, "%d: VirtualProtect(%02x) should fail\n", i
, td
[i
].prot
);
3179 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3182 UnmapViewOfFile(base
);
3187 ok(!hmap
, "%d: CreateFileMapping should fail\n", i
);
3188 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3192 if (page_exec_supported
) alloc_prot
= PAGE_EXECUTE_READWRITE
;
3193 else alloc_prot
= PAGE_READWRITE
;
3194 SetLastError(0xdeadbeef);
3195 hmap
= CreateFileMappingW(hfile
, NULL
, alloc_prot
, 0, si
.dwPageSize
, NULL
);
3196 ok(hmap
!= 0, "%d: CreateFileMapping error %d\n", i
, GetLastError());
3198 SetLastError(0xdeadbeef);
3199 base
= MapViewOfFile(hmap
, FILE_MAP_READ
| FILE_MAP_WRITE
| (page_exec_supported
? FILE_MAP_EXECUTE
: 0), 0, 0, 0);
3200 ok(base
!= NULL
, "MapViewOfFile failed %d\n", GetLastError());
3202 old_prot
= 0xdeadbeef;
3203 SetLastError(0xdeadbeef);
3204 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3205 ok(ret
, "VirtualProtect error %d\n", GetLastError());
3206 ok(old_prot
== alloc_prot
, "got %#x != expected %#x\n", old_prot
, alloc_prot
);
3208 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3210 SetLastError(0xdeadbeef);
3211 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3212 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3213 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3214 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3215 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
3216 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3217 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3218 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3219 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3221 old_prot
= 0xdeadbeef;
3222 SetLastError(0xdeadbeef);
3223 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3224 if (td
[i
].success
|| td
[i
].prot
== PAGE_NOACCESS
|| td
[i
].prot
== PAGE_EXECUTE
)
3228 /* win2k and XP don't support EXEC on file mappings */
3229 if (td
[i
].prot
== PAGE_EXECUTE
)
3231 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3234 /* NT4 and win2k don't support EXEC on file mappings */
3235 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3237 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3240 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3241 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3243 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3248 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3249 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
3252 /* looks strange but Windows doesn't do this for PAGE_WRITECOPY */
3253 if (prot
== PAGE_EXECUTE_WRITECOPY
) prot
= PAGE_EXECUTE_READWRITE
;
3255 SetLastError(0xdeadbeef);
3256 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3257 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3258 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3259 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3260 /* FIXME: remove the condition below once Wine is fixed */
3261 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3262 todo_wine
ok(info
.Protect
== prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, prot
);
3264 ok(info
.Protect
== prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, prot
);
3265 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3266 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3267 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3268 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3270 if (is_mem_writable(info
.Protect
))
3274 SetLastError(0xdeadbeef);
3275 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3276 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3277 /* FIXME: remove the condition below once Wine is fixed */
3278 if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3279 todo_wine
ok(info
.Protect
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_after_write
);
3281 ok(info
.Protect
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_after_write
);
3286 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
3287 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3291 old_prot
= 0xdeadbeef;
3292 SetLastError(0xdeadbeef);
3293 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3294 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3295 /* FIXME: remove the condition below once Wine is fixed */
3296 if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3297 todo_wine
ok(old_prot
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_after_write
);
3299 ok(old_prot
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_after_write
);
3302 UnmapViewOfFile(base
);
3306 DeleteFileA(file_name
);
3309 #define ACCESS_READ 0x01
3310 #define ACCESS_WRITE 0x02
3311 #define ACCESS_EXECUTE 0x04
3312 #define ACCESS_WRITECOPY 0x08
3314 static DWORD
page_prot_to_access(DWORD prot
)
3318 case PAGE_READWRITE
:
3319 return ACCESS_READ
| ACCESS_WRITE
;
3322 case PAGE_EXECUTE_READ
:
3323 return ACCESS_READ
| ACCESS_EXECUTE
;
3325 case PAGE_EXECUTE_READWRITE
:
3326 return ACCESS_READ
| ACCESS_WRITE
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3328 case PAGE_EXECUTE_WRITECOPY
:
3329 return ACCESS_READ
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3334 case PAGE_WRITECOPY
:
3342 static BOOL
is_compatible_protection(DWORD map_prot
, DWORD view_prot
, DWORD prot
)
3344 DWORD map_access
, view_access
, prot_access
;
3346 map_access
= page_prot_to_access(map_prot
);
3347 view_access
= page_prot_to_access(view_prot
);
3348 prot_access
= page_prot_to_access(prot
);
3350 if (view_access
== prot_access
) return TRUE
;
3351 if (!view_access
) return FALSE
;
3353 if ((view_access
& prot_access
) != prot_access
) return FALSE
;
3354 if ((map_access
& prot_access
) == prot_access
) return TRUE
;
3359 static DWORD
map_prot_to_access(DWORD prot
)
3363 case PAGE_READWRITE
:
3364 case PAGE_EXECUTE_READWRITE
:
3365 return SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3367 case PAGE_WRITECOPY
:
3369 case PAGE_EXECUTE_READ
:
3370 case PAGE_EXECUTE_WRITECOPY
:
3371 return SECTION_MAP_READ
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3377 static BOOL
is_compatible_access(DWORD map_prot
, DWORD view_prot
)
3379 DWORD access
= map_prot_to_access(map_prot
);
3380 if (!view_prot
) view_prot
= SECTION_MAP_READ
;
3381 return (view_prot
& access
) == view_prot
;
3384 static void *map_view_of_file(HANDLE handle
, DWORD access
)
3387 LARGE_INTEGER offset
;
3393 if (!pNtMapViewOfSection
) return NULL
;
3396 offset
.u
.LowPart
= 0;
3397 offset
.u
.HighPart
= 0;
3399 exec
= access
& FILE_MAP_EXECUTE
;
3400 access
&= ~FILE_MAP_EXECUTE
;
3402 if (access
== FILE_MAP_COPY
)
3405 protect
= PAGE_EXECUTE_WRITECOPY
;
3407 protect
= PAGE_WRITECOPY
;
3409 else if (access
& FILE_MAP_WRITE
)
3412 protect
= PAGE_EXECUTE_READWRITE
;
3414 protect
= PAGE_READWRITE
;
3416 else if (access
& FILE_MAP_READ
)
3419 protect
= PAGE_EXECUTE_READ
;
3421 protect
= PAGE_READONLY
;
3423 else protect
= PAGE_NOACCESS
;
3426 status
= pNtMapViewOfSection(handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
3427 &count
, 1 /* ViewShare */, 0, protect
);
3430 /* for simplicity */
3431 SetLastError(ERROR_ACCESS_DENIED
);
3437 static void test_mapping(void)
3439 static const DWORD page_prot
[] =
3441 PAGE_NOACCESS
, PAGE_READONLY
, PAGE_READWRITE
, PAGE_WRITECOPY
,
3442 PAGE_EXECUTE_READ
, PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_WRITECOPY
3449 { 0, PAGE_NOACCESS
}, /* 0x00 */
3450 { FILE_MAP_COPY
, PAGE_WRITECOPY
}, /* 0x01 */
3451 { FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x02 */
3452 { FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x03 */
3453 { FILE_MAP_READ
, PAGE_READONLY
}, /* 0x04 */
3454 { FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x05 */
3455 { FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x06 */
3456 { FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x07 */
3457 { SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x08 */
3458 { SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x09 */
3459 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0a */
3460 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0b */
3461 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_READONLY
}, /* 0x0c */
3462 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x0d */
3463 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0e */
3464 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0f */
3465 { FILE_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x20 */
3466 { FILE_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_EXECUTE_WRITECOPY
}, /* 0x21 */
3467 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x22 */
3468 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x23 */
3469 { FILE_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x24 */
3470 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x25 */
3471 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x26 */
3472 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x27 */
3473 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x28 */
3474 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x29 */
3475 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2a */
3476 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x2b */
3477 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x2c */
3478 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x2d */
3479 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2e */
3480 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
} /* 0x2f */
3482 void *base
, *nt_base
, *ptr
;
3483 DWORD i
, j
, k
, ret
, old_prot
, prev_prot
;
3485 char temp_path
[MAX_PATH
];
3486 char file_name
[MAX_PATH
];
3488 MEMORY_BASIC_INFORMATION info
, nt_info
;
3491 trace("system page size %#x\n", si
.dwPageSize
);
3493 GetTempPathA(MAX_PATH
, temp_path
);
3494 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3496 SetLastError(0xdeadbeef);
3497 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3498 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3499 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3500 SetEndOfFile(hfile
);
3502 for (i
= 0; i
< sizeof(page_prot
)/sizeof(page_prot
[0]); i
++)
3504 SetLastError(0xdeadbeef);
3505 hmap
= CreateFileMappingW(hfile
, NULL
, page_prot
[i
] | SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3507 if (page_prot
[i
] == PAGE_NOACCESS
)
3511 ok(!hmap
, "CreateFileMapping(PAGE_NOACCESS) should fail\n");
3512 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3514 /* A trick to create a not accessible mapping */
3515 SetLastError(0xdeadbeef);
3516 hmap
= CreateFileMappingW(hfile
, NULL
, PAGE_READWRITE
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3517 ok(hmap
!= 0, "CreateFileMapping(PAGE_READWRITE) error %d\n", GetLastError());
3518 SetLastError(0xdeadbeef);
3519 ret
= DuplicateHandle(GetCurrentProcess(), hmap
, GetCurrentProcess(), &hmap2
, 0, FALSE
, 0);
3520 ok(ret
, "DuplicateHandle error %d\n", GetLastError());
3527 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, page_prot
[i
], GetLastError());
3529 /* NT4 and win2k don't support EXEC on file mappings */
3530 if (page_prot
[i
] == PAGE_EXECUTE_READ
|| page_prot
[i
] == PAGE_EXECUTE_READWRITE
)
3532 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3535 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3536 if (page_prot
[i
] == PAGE_EXECUTE_WRITECOPY
)
3538 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3543 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, page_prot
[i
], GetLastError());
3545 for (j
= 0; j
< sizeof(view
)/sizeof(view
[0]); j
++)
3547 nt_base
= map_view_of_file(hmap
, view
[j
].access
);
3550 SetLastError(0xdeadbeef);
3551 ret
= VirtualQuery(nt_base
, &nt_info
, sizeof(nt_info
));
3552 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3553 UnmapViewOfFile(nt_base
);
3556 SetLastError(0xdeadbeef);
3557 base
= MapViewOfFile(hmap
, view
[j
].access
, 0, 0, 0);
3559 /* Vista+ supports FILE_MAP_EXECUTE properly, earlier versions don't */
3560 ok(!nt_base
== !base
||
3561 broken((view
[j
].access
& FILE_MAP_EXECUTE
) && !nt_base
!= !base
),
3562 "%d: (%04x/%04x) NT %p kernel %p\n", j
, page_prot
[i
], view
[j
].access
, nt_base
, base
);
3564 if (!is_compatible_access(page_prot
[i
], view
[j
].access
))
3566 ok(!base
, "%d: MapViewOfFile(%04x/%04x) should fail\n", j
, page_prot
[i
], view
[j
].access
);
3567 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %d\n", GetLastError());
3571 /* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */
3572 if (!base
&& (view
[j
].access
& FILE_MAP_EXECUTE
))
3574 ok(broken(!base
), "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3578 ok(base
!= NULL
, "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3580 SetLastError(0xdeadbeef);
3581 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3582 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3583 ok(info
.BaseAddress
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.BaseAddress
, base
);
3584 ok(info
.RegionSize
== si
.dwPageSize
, "%d: (%04x) got %#lx != expected %#x\n", j
, view
[j
].access
, info
.RegionSize
, si
.dwPageSize
);
3585 ok(info
.Protect
== view
[j
].prot
||
3586 broken(view
[j
].prot
== PAGE_EXECUTE_READ
&& info
.Protect
== PAGE_READONLY
) || /* win2k */
3587 broken(view
[j
].prot
== PAGE_EXECUTE_READWRITE
&& info
.Protect
== PAGE_READWRITE
) || /* win2k */
3588 broken(view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3589 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.Protect
, view
[j
].prot
);
3590 ok(info
.AllocationBase
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.AllocationBase
, base
);
3591 ok(info
.AllocationProtect
== info
.Protect
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.AllocationProtect
, info
.Protect
);
3592 ok(info
.State
== MEM_COMMIT
, "%d: (%04x) got %#x, expected MEM_COMMIT\n", j
, view
[j
].access
, info
.State
);
3593 ok(info
.Type
== MEM_MAPPED
, "%d: (%04x) got %#x, expected MEM_MAPPED\n", j
, view
[j
].access
, info
.Type
);
3595 if (nt_base
&& base
)
3597 ok(nt_info
.RegionSize
== info
.RegionSize
, "%d: (%04x) got %#lx != expected %#lx\n", j
, view
[j
].access
, nt_info
.RegionSize
, info
.RegionSize
);
3598 ok(nt_info
.Protect
== info
.Protect
/* Vista+ */ ||
3599 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3600 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Protect
, info
.Protect
);
3601 ok(nt_info
.AllocationProtect
== info
.AllocationProtect
/* Vista+ */ ||
3602 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3603 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.AllocationProtect
, info
.AllocationProtect
);
3604 ok(nt_info
.State
== info
.State
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.State
, info
.State
);
3605 ok(nt_info
.Type
== info
.Type
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Type
, info
.Type
);
3608 prev_prot
= info
.Protect
;
3610 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3612 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3613 SetLastError(0xdeadbeef);
3614 old_prot
= 0xdeadbeef;
3615 ret
= VirtualProtect(base
, si
.dwPageSize
, page_prot
[k
], &old_prot
);
3616 if (is_compatible_protection(page_prot
[i
], view
[j
].prot
, page_prot
[k
]))
3618 /* win2k and XP don't support EXEC on file mappings */
3619 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE
)
3621 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3624 /* NT4 and win2k don't support EXEC on file mappings */
3625 if (!ret
&& (page_prot
[k
] == PAGE_EXECUTE_READ
|| page_prot
[k
] == PAGE_EXECUTE_READWRITE
))
3627 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3630 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3631 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE_WRITECOPY
)
3633 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n");
3636 /* win2k and XP don't support PAGE_EXECUTE_WRITECOPY views properly */
3637 if (!ret
&& view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
)
3639 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY view properly\n");
3643 ok(ret
, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3644 ok(old_prot
== prev_prot
, "got %#x, expected %#x\n", old_prot
, prev_prot
);
3645 prev_prot
= page_prot
[k
];
3649 /* NT4 doesn't fail on incompatible map and view */
3652 ok(broken(ret
), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3653 skip("Incompatible map and view are not properly handled on this platform\n");
3654 break; /* NT4 won't pass remaining tests */
3657 ok(!ret
, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3658 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3662 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3664 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3665 SetLastError(0xdeadbeef);
3666 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, page_prot
[k
]);
3667 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", page_prot
[k
]);
3668 /* FIXME: remove once Wine is fixed */
3669 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());
3673 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3676 UnmapViewOfFile(base
);
3683 DeleteFileA(file_name
);
3686 static void test_shared_memory(BOOL is_child
)
3691 SetLastError(0xdeadbef);
3692 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c");
3693 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3695 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3697 SetLastError(0xdeadbef);
3698 p
= MapViewOfFile(mapping
, FILE_MAP_READ
|FILE_MAP_WRITE
, 0, 0, 4096);
3699 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3703 ok(*p
== 0x1a2b3c4d, "expected 0x1a2b3c4d in child, got %#x\n", *p
);
3708 char cmdline
[MAX_PATH
];
3709 PROCESS_INFORMATION pi
;
3710 STARTUPINFOA si
= { sizeof(si
) };
3715 winetest_get_mainargs(&argv
);
3716 sprintf(cmdline
, "\"%s\" virtual sharedmem", argv
[0]);
3717 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3718 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3719 winetest_wait_child_process(pi
.hProcess
);
3720 CloseHandle(pi
.hThread
);
3721 CloseHandle(pi
.hProcess
);
3725 CloseHandle(mapping
);
3728 static void test_shared_memory_ro(BOOL is_child
, DWORD child_access
)
3733 SetLastError(0xdeadbef);
3734 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c_ro");
3735 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3737 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3739 SetLastError(0xdeadbef);
3740 p
= MapViewOfFile(mapping
, is_child
? child_access
: FILE_MAP_READ
, 0, 0, 4096);
3741 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3750 char cmdline
[MAX_PATH
];
3751 PROCESS_INFORMATION pi
;
3752 STARTUPINFOA si
= { sizeof(si
) };
3755 winetest_get_mainargs(&argv
);
3756 sprintf(cmdline
, "\"%s\" virtual sharedmemro %x", argv
[0], child_access
);
3757 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3758 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3759 winetest_wait_child_process(pi
.hProcess
);
3760 CloseHandle(pi
.hThread
);
3761 CloseHandle(pi
.hProcess
);
3763 if(child_access
& FILE_MAP_WRITE
)
3764 ok(*p
== 0xdeadbeef, "*p = %x, expected 0xdeadbeef\n", *p
);
3766 ok(!*p
, "*p = %x, expected 0\n", *p
);
3770 CloseHandle(mapping
);
3777 argc
= winetest_get_mainargs( &argv
);
3781 if (!strcmp(argv
[2], "sleep"))
3783 Sleep(5000); /* spawned process runs for at most 5 seconds */
3786 if (!strcmp(argv
[2], "sharedmem"))
3788 test_shared_memory(TRUE
);
3791 if (!strcmp(argv
[2], "sharedmemro"))
3793 test_shared_memory_ro(TRUE
, strtol(argv
[3], NULL
, 16));
3800 mem
= VirtualAlloc(NULL
, 1<<20, MEM_COMMIT
|MEM_RESERVE
,
3801 PAGE_EXECUTE_READWRITE
);
3802 ok(mem
!= NULL
, "VirtualAlloc failed %u\n", GetLastError());
3803 if (mem
== NULL
) break;
3804 ret
= VirtualFree(mem
, 0, MEM_RELEASE
);
3805 ok(ret
, "VirtualFree failed %u\n", GetLastError());
3811 hkernel32
= GetModuleHandleA("kernel32.dll");
3812 hntdll
= GetModuleHandleA("ntdll.dll");
3814 pVirtualAllocEx
= (void *) GetProcAddress(hkernel32
, "VirtualAllocEx");
3815 pVirtualFreeEx
= (void *) GetProcAddress(hkernel32
, "VirtualFreeEx");
3816 pGetWriteWatch
= (void *) GetProcAddress(hkernel32
, "GetWriteWatch");
3817 pResetWriteWatch
= (void *) GetProcAddress(hkernel32
, "ResetWriteWatch");
3818 pGetProcessDEPPolicy
= (void *)GetProcAddress( hkernel32
, "GetProcessDEPPolicy" );
3819 pIsWow64Process
= (void *)GetProcAddress( hkernel32
, "IsWow64Process" );
3820 pNtAreMappedFilesTheSame
= (void *)GetProcAddress( hntdll
, "NtAreMappedFilesTheSame" );
3821 pNtMapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtMapViewOfSection" );
3822 pNtUnmapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtUnmapViewOfSection" );
3823 pNtCurrentTeb
= (void *)GetProcAddress( hntdll
, "NtCurrentTeb" );
3824 pRtlAddVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlAddVectoredExceptionHandler" );
3825 pRtlRemoveVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlRemoveVectoredExceptionHandler" );
3826 pNtProtectVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtProtectVirtualMemory" );
3827 pNtAllocateVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtAllocateVirtualMemory" );
3828 pNtFreeVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtFreeVirtualMemory" );
3830 test_shared_memory(FALSE
);
3831 test_shared_memory_ro(FALSE
, FILE_MAP_READ
|FILE_MAP_WRITE
);
3832 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
);
3833 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
|FILE_MAP_WRITE
);
3835 test_CreateFileMapping_protection();
3836 test_VirtualAlloc_protection();
3837 test_VirtualProtect();
3838 test_VirtualAllocEx();
3839 test_VirtualAlloc();
3840 test_MapViewOfFile();
3841 test_NtMapViewOfSection();
3842 test_NtAreMappedFilesTheSame();
3843 test_CreateFileMapping();
3844 test_IsBadReadPtr();
3845 test_IsBadWritePtr();
3846 test_IsBadCodePtr();
3850 test_stack_commit();
3851 /* The following tests should be executed as a last step, and in exactly this
3852 * order, since ATL thunk emulation cannot be enabled anymore on Windows. */
3853 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE
);
3854 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
);
3855 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
| MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
);