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
*pNtCreateSection
)(HANDLE
*, ACCESS_MASK
, const OBJECT_ATTRIBUTES
*,
45 const LARGE_INTEGER
*, ULONG
, ULONG
, HANDLE
);
46 static NTSTATUS (WINAPI
*pNtMapViewOfSection
)(HANDLE
, HANDLE
, PVOID
*, ULONG
, SIZE_T
, const LARGE_INTEGER
*, SIZE_T
*, ULONG
, ULONG
, ULONG
);
47 static DWORD (WINAPI
*pNtUnmapViewOfSection
)(HANDLE
, PVOID
);
48 static NTSTATUS (WINAPI
*pNtQuerySection
)(HANDLE
, SECTION_INFORMATION_CLASS
, void *, ULONG
, ULONG
*);
49 static PVOID (WINAPI
*pRtlAddVectoredExceptionHandler
)(ULONG
, PVECTORED_EXCEPTION_HANDLER
);
50 static ULONG (WINAPI
*pRtlRemoveVectoredExceptionHandler
)(PVOID
);
51 static BOOL (WINAPI
*pGetProcessDEPPolicy
)(HANDLE
, LPDWORD
, PBOOL
);
52 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
53 static NTSTATUS (WINAPI
*pNtProtectVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
, ULONG
*);
54 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG
, SIZE_T
*, ULONG
, ULONG
);
55 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
57 /* ############################### */
59 static HANDLE
create_target_process(const char *arg
)
62 char cmdline
[MAX_PATH
];
63 PROCESS_INFORMATION pi
;
65 STARTUPINFOA si
= { 0 };
68 winetest_get_mainargs( &argv
);
69 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], arg
);
70 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
71 ok(ret
, "error: %u\n", GetLastError());
72 ret
= CloseHandle(pi
.hThread
);
73 ok(ret
, "error %u\n", GetLastError());
77 static void test_VirtualAllocEx(void)
79 const unsigned int alloc_size
= 1<<15;
81 SIZE_T bytes_written
= 0, bytes_read
= 0, i
;
85 MEMORY_BASIC_INFORMATION info
;
88 /* not exported in all windows-versions */
89 if ((!pVirtualAllocEx
) || (!pVirtualFreeEx
)) {
90 win_skip("Virtual{Alloc,Free}Ex not available\n");
94 hProcess
= create_target_process("sleep");
95 ok(hProcess
!= NULL
, "Can't start process\n");
97 SetLastError(0xdeadbeef);
98 addr1
= pVirtualAllocEx(hProcess
, NULL
, alloc_size
, MEM_COMMIT
,
99 PAGE_EXECUTE_READWRITE
);
100 ok(addr1
!= NULL
, "VirtualAllocEx error %u\n", GetLastError());
102 src
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
103 dst
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
104 for (i
= 0; i
< alloc_size
; i
++)
107 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
108 ok(b
&& (bytes_written
== alloc_size
), "%lu bytes written\n",
110 b
= ReadProcessMemory(hProcess
, addr1
, dst
, alloc_size
, &bytes_read
);
111 ok(b
&& (bytes_read
== alloc_size
), "%lu bytes read\n", bytes_read
);
112 ok(!memcmp(src
, dst
, alloc_size
), "Data from remote process differs\n");
114 /* test invalid source buffers */
116 b
= VirtualProtect( src
+ 0x2000, 0x2000, PAGE_NOACCESS
, &old_prot
);
117 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
118 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
119 ok( !b
, "WriteProcessMemory succeeded\n" );
120 ok( GetLastError() == ERROR_NOACCESS
||
121 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
122 "wrong error %u\n", GetLastError() );
123 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
124 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
125 ok( !b
, "ReadProcessMemory succeeded\n" );
126 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
127 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
129 b
= VirtualProtect( src
, 0x2000, PAGE_NOACCESS
, &old_prot
);
130 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
131 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
132 ok( !b
, "WriteProcessMemory succeeded\n" );
133 ok( GetLastError() == ERROR_NOACCESS
||
134 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
135 "wrong error %u\n", GetLastError() );
136 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
137 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
138 ok( !b
, "ReadProcessMemory succeeded\n" );
139 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
140 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
142 b
= pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
);
143 ok(b
!= 0, "VirtualFreeEx, error %u\n", GetLastError());
145 VirtualFree( src
, 0, MEM_RELEASE
);
146 VirtualFree( dst
, 0, MEM_RELEASE
);
149 * The following tests parallel those in test_VirtualAlloc()
152 SetLastError(0xdeadbeef);
153 addr1
= pVirtualAllocEx(hProcess
, 0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
154 ok(addr1
== NULL
, "VirtualAllocEx should fail on zero-sized allocation\n");
155 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
156 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
158 addr1
= pVirtualAllocEx(hProcess
, 0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
159 ok(addr1
!= NULL
, "VirtualAllocEx failed\n");
161 /* test a not committed memory */
162 memset(&info
, 'q', sizeof(info
));
163 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
), "VirtualQueryEx failed\n");
164 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
165 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
166 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
167 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
168 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
169 ok(info
.Protect
== 0, "%x != PAGE_NOACCESS\n", info
.Protect
);
170 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
172 SetLastError(0xdeadbeef);
173 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
174 "VirtualProtectEx should fail on a not committed memory\n");
175 ok(GetLastError() == ERROR_INVALID_ADDRESS
,
176 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
178 addr2
= pVirtualAllocEx(hProcess
, addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
179 ok(addr1
== addr2
, "VirtualAllocEx failed\n");
181 /* test a committed memory */
182 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
),
183 "VirtualQueryEx failed\n");
184 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
185 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
186 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
187 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
188 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
189 /* this time NT reports PAGE_NOACCESS as well */
190 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
191 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
193 /* this should fail, since not the whole range is committed yet */
194 SetLastError(0xdeadbeef);
195 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
196 "VirtualProtectEx should fail on a not committed memory\n");
197 ok(GetLastError() == ERROR_INVALID_ADDRESS
,
198 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
201 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtectEx failed\n");
202 ok(old_prot
== PAGE_NOACCESS
, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
205 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtectEx failed\n");
206 ok(old_prot
== PAGE_READONLY
, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
208 ok(!pVirtualFreeEx(hProcess
, addr1
, 0x10000, 0),
209 "VirtualFreeEx should fail with type 0\n");
210 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
211 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
213 ok(pVirtualFreeEx(hProcess
, addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFreeEx failed\n");
215 /* if the type is MEM_RELEASE, size must be 0 */
216 ok(!pVirtualFreeEx(hProcess
, addr1
, 1, MEM_RELEASE
),
217 "VirtualFreeEx should fail\n");
218 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
219 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
221 ok(pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
), "VirtualFreeEx failed\n");
223 TerminateProcess(hProcess
, 0);
224 CloseHandle(hProcess
);
227 static void test_VirtualAlloc(void)
231 MEMORY_BASIC_INFORMATION info
;
235 SetLastError(0xdeadbeef);
236 addr1
= VirtualAlloc(0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
237 ok(addr1
== NULL
, "VirtualAlloc should fail on zero-sized allocation\n");
238 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
239 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
241 addr1
= VirtualAlloc(0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
242 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
244 /* test a not committed memory */
245 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
246 "VirtualQuery failed\n");
247 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
248 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
249 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
250 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
251 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
252 ok(info
.Protect
== 0, "%x != PAGE_NOACCESS\n", info
.Protect
);
253 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
255 SetLastError(0xdeadbeef);
256 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
257 "VirtualProtect should fail on a not committed memory\n");
258 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
259 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
261 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
262 ok(addr1
== addr2
, "VirtualAlloc failed\n");
264 /* test a committed memory */
265 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
266 "VirtualQuery failed\n");
267 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
268 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
269 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
270 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
271 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
272 /* this time NT reports PAGE_NOACCESS as well */
273 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
274 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
276 /* this should fail, since not the whole range is committed yet */
277 SetLastError(0xdeadbeef);
278 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
279 "VirtualProtect should fail on a not committed memory\n");
280 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
281 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
283 ok(VirtualProtect(addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtect failed\n");
284 ok(old_prot
== PAGE_NOACCESS
,
285 "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
287 ok(VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtect failed\n");
288 ok(old_prot
== PAGE_READONLY
,
289 "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
291 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
292 "VirtualQuery failed\n");
293 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
294 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
295 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
296 memset( addr1
, 0x55, 20 );
297 ok( *(DWORD
*)addr1
== 0x55555555, "wrong data %x\n", *(DWORD
*)addr1
);
299 addr2
= VirtualAlloc( addr1
, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
300 ok( addr2
== addr1
, "VirtualAlloc failed err %u\n", GetLastError() );
301 ok( *(DWORD
*)addr1
== 0x55555555 || *(DWORD
*)addr1
== 0, "wrong data %x\n", *(DWORD
*)addr1
);
302 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
303 "VirtualQuery failed\n");
304 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
305 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
306 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
308 addr2
= VirtualAlloc( (char *)addr1
+ 0x1000, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
309 ok( (char *)addr2
== (char *)addr1
+ 0x1000, "VirtualAlloc failed\n" );
311 ok(VirtualQuery(addr2
, &info
, sizeof(info
)) == sizeof(info
),
312 "VirtualQuery failed\n");
313 ok(info
.RegionSize
== 0xf000, "%lx != 0xf000\n", info
.RegionSize
);
314 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
315 ok(info
.Protect
== 0, "%x != 0\n", info
.Protect
);
317 addr2
= VirtualAlloc( (char *)addr1
+ 0xf000, 0x2000, MEM_RESET
, PAGE_NOACCESS
);
318 ok( !addr2
, "VirtualAlloc failed\n" );
319 ok( GetLastError() == ERROR_INVALID_ADDRESS
, "wrong error %u\n", GetLastError() );
321 /* invalid protection values */
322 SetLastError(0xdeadbeef);
323 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_RESERVE
, 0);
324 ok(!addr2
, "VirtualAlloc succeeded\n");
325 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
327 SetLastError(0xdeadbeef);
328 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_COMMIT
, 0);
329 ok(!addr2
, "VirtualAlloc succeeded\n");
330 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
332 SetLastError(0xdeadbeef);
333 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_READONLY
| PAGE_EXECUTE
);
334 ok(!addr2
, "VirtualAlloc succeeded\n");
335 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
337 SetLastError(0xdeadbeef);
338 ok(!VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
| PAGE_EXECUTE_WRITECOPY
, &old_prot
),
339 "VirtualProtect succeeded\n");
340 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
342 SetLastError(0xdeadbeef);
343 ok(!VirtualProtect(addr1
, 0x1000, 0, &old_prot
), "VirtualProtect succeeded\n");
344 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
346 SetLastError(0xdeadbeef);
347 ok(!VirtualFree(addr1
, 0x10000, 0), "VirtualFree should fail with type 0\n");
348 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
349 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
351 SetLastError(0xdeadbeef);
352 ok(!VirtualFree(addr1
, 0, MEM_FREE
), "VirtualFree should fail with type MEM_FREE\n");
353 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
354 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
356 ok(VirtualFree(addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFree failed\n");
358 /* if the type is MEM_RELEASE, size must be 0 */
359 ok(!VirtualFree(addr1
, 1, MEM_RELEASE
), "VirtualFree should fail\n");
360 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
361 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
363 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
365 /* memory returned by VirtualAlloc should be aligned to 64k */
366 addr1
= VirtualAlloc(0, 0x2000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
367 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
368 ok(!((ULONG_PTR
)addr1
& 0xffff), "returned memory %p is not aligned to 64k\n", addr1
);
369 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
370 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
371 ok(addr2
== addr1
, "VirtualAlloc returned %p, expected %p\n", addr2
, addr1
);
373 /* allocation conflicts because of 64k align */
375 addr2
= (char *)addr1
+ 0x1000;
376 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
,
377 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
378 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
380 /* it should conflict, even when zero_bits is explicitly set */
382 addr2
= (char *)addr1
+ 0x1000;
383 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 12, &size
,
384 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
386 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
387 if (status
== STATUS_SUCCESS
) ok(VirtualFree(addr2
, 0, MEM_RELEASE
), "VirtualFree failed\n");
389 /* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
390 SetLastError(0xdeadbeef);
391 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_RESERVE
| MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
392 ok(!addr2
, "VirtualAlloc unexpectedly succeeded\n");
393 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
395 /* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
397 addr2
= (char *)addr1
+ 0x1000;
398 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
, MEM_RESERVE
|
399 MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
401 ok(status
== STATUS_INVALID_PARAMETER_5
, "NtAllocateVirtualMemory returned %08x\n", status
);
403 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
406 static void test_MapViewOfFile(void)
408 static const char testfile
[] = "testfile.xxx";
410 HANDLE file
, mapping
, map2
;
411 void *ptr
, *ptr2
, *addr
;
412 SECTION_BASIC_INFORMATION section_info
;
413 MEMORY_BASIC_INFORMATION info
;
418 LARGE_INTEGER map_size
;
420 SetLastError(0xdeadbeef);
421 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
422 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
423 SetFilePointer( file
, 12288, NULL
, FILE_BEGIN
);
424 SetEndOfFile( file
);
426 /* read/write mapping */
428 SetLastError(0xdeadbeef);
429 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
430 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
432 SetLastError(0xdeadbeef);
433 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
434 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
435 UnmapViewOfFile( ptr
);
437 SetLastError(0xdeadbeef);
438 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
439 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
440 UnmapViewOfFile( ptr
);
442 SetLastError(0xdeadbeef);
443 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
444 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
445 UnmapViewOfFile( ptr
);
447 SetLastError(0xdeadbeef);
448 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
449 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
450 UnmapViewOfFile( ptr
);
452 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
453 FILE_MAP_READ
|FILE_MAP_WRITE
, FALSE
, 0 );
454 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
455 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
456 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
457 UnmapViewOfFile( ptr
);
460 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
461 FILE_MAP_READ
, FALSE
, 0 );
462 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
463 SetLastError(0xdeadbeef);
464 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
465 ok( !ptr
, "MapViewOfFile succeeded\n" );
466 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
468 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
, 0, FALSE
, 0 );
469 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
470 SetLastError(0xdeadbeef);
471 ptr
= MapViewOfFile( map2
, 0, 0, 0, 4096 );
472 ok( !ptr
, "MapViewOfFile succeeded\n" );
473 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
475 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
476 FILE_MAP_READ
, FALSE
, 0 );
477 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
478 ptr
= MapViewOfFile( map2
, 0, 0, 0, 4096 );
479 ok( ptr
!= NULL
, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
481 UnmapViewOfFile( ptr
);
483 CloseHandle( mapping
);
485 /* read-only mapping */
487 SetLastError(0xdeadbeef);
488 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
489 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
491 SetLastError(0xdeadbeef);
492 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
493 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
494 UnmapViewOfFile( ptr
);
496 SetLastError(0xdeadbeef);
497 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
498 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
499 UnmapViewOfFile( ptr
);
501 SetLastError(0xdeadbeef);
502 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
503 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
504 UnmapViewOfFile( ptr
);
506 SetLastError(0xdeadbeef);
507 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
508 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
509 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
510 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
511 CloseHandle( mapping
);
513 /* copy-on-write mapping */
515 SetLastError(0xdeadbeef);
516 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
517 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
519 SetLastError(0xdeadbeef);
520 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
521 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
522 UnmapViewOfFile( ptr
);
524 SetLastError(0xdeadbeef);
525 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
526 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
527 UnmapViewOfFile( ptr
);
529 SetLastError(0xdeadbeef);
530 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
531 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
532 UnmapViewOfFile( ptr
);
534 SetLastError(0xdeadbeef);
535 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
536 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
537 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
538 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
539 CloseHandle( mapping
);
541 /* no access mapping */
543 SetLastError(0xdeadbeef);
544 mapping
= CreateFileMappingA( file
, NULL
, PAGE_NOACCESS
, 0, 4096, NULL
);
545 ok( !mapping
, "CreateFileMappingA succeeded\n" );
546 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
549 /* now try read-only file */
551 SetLastError(0xdeadbeef);
552 file
= CreateFileA( testfile
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0 );
553 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
555 SetLastError(0xdeadbeef);
556 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
557 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
558 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
559 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
561 SetLastError(0xdeadbeef);
562 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
563 ok( mapping
!= 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
564 CloseHandle( mapping
);
566 SetLastError(0xdeadbeef);
567 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
568 ok( mapping
!= 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
569 CloseHandle( mapping
);
572 /* now try no access file */
574 SetLastError(0xdeadbeef);
575 file
= CreateFileA( testfile
, 0, 0, NULL
, OPEN_EXISTING
, 0, 0 );
576 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
578 SetLastError(0xdeadbeef);
579 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
580 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
581 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
582 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
584 SetLastError(0xdeadbeef);
585 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
586 ok( !mapping
, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
587 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
588 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
590 SetLastError(0xdeadbeef);
591 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
592 ok( !mapping
, "CreateFileMapping PAGE_READONLY succeeded\n" );
593 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
594 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
597 DeleteFileA( testfile
);
599 SetLastError(0xdeadbeef);
601 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4090, name
);
602 /* nt4 doesn't have Local\\ */
603 if (!file
&& GetLastError() == ERROR_PATH_NOT_FOUND
)
606 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4090, name
);
608 ok( file
!= 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
610 SetLastError(0xdeadbeef);
611 mapping
= OpenFileMappingA( FILE_MAP_READ
, FALSE
, name
);
612 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
613 SetLastError(0xdeadbeef);
614 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
615 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
616 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
617 SetLastError(0xdeadbeef);
618 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
619 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
620 SetLastError(0xdeadbeef);
621 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
622 ok( size
== sizeof(info
),
623 "VirtualQuery error %u\n", GetLastError() );
624 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
625 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
626 ok( info
.AllocationProtect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.AllocationProtect
);
627 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
628 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
629 ok( info
.Protect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.Protect
);
630 UnmapViewOfFile( ptr
);
631 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
632 sizeof(section_info
), &info_size
);
633 ok( status
== STATUS_ACCESS_DENIED
, "NtQuerySection failed err %x\n", status
);
634 CloseHandle( mapping
);
635 mapping
= OpenFileMappingA( FILE_MAP_READ
| SECTION_QUERY
, FALSE
, name
);
636 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
637 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
638 sizeof(section_info
), &info_size
);
639 ok( !status
, "NtQuerySection failed err %x\n", status
);
640 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
641 ok( section_info
.Attributes
== SEC_COMMIT
, "NtQuerySection wrong attr %08x\n",
642 section_info
.Attributes
);
643 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
644 ok( section_info
.Size
.QuadPart
== info
.RegionSize
, "NtQuerySection wrong size %x%08x / %08lx\n",
645 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
, info
.RegionSize
);
646 CloseHandle( mapping
);
648 SetLastError(0xdeadbeef);
649 mapping
= OpenFileMappingA( FILE_MAP_WRITE
, FALSE
, name
);
650 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
651 SetLastError(0xdeadbeef);
652 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
653 ok( !ptr
, "MapViewOfFile succeeded\n " );
654 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
655 SetLastError(0xdeadbeef);
656 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
657 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
658 SetLastError(0xdeadbeef);
659 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
660 ok( size
== sizeof(info
),
661 "VirtualQuery error %u\n", GetLastError() );
662 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
663 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
664 ok( info
.AllocationProtect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.AllocationProtect
);
665 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
666 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
667 ok( info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
668 UnmapViewOfFile( ptr
);
669 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
670 sizeof(section_info
), &info_size
);
671 ok( status
== STATUS_ACCESS_DENIED
, "NtQuerySection failed err %x\n", status
);
672 CloseHandle( mapping
);
674 mapping
= OpenFileMappingA( FILE_MAP_WRITE
| SECTION_QUERY
, FALSE
, name
);
675 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
676 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
677 sizeof(section_info
), &info_size
);
678 ok( !status
, "NtQuerySection failed err %x\n", status
);
679 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
680 ok( section_info
.Attributes
== SEC_COMMIT
, "NtQuerySection wrong attr %08x\n",
681 section_info
.Attributes
);
682 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
683 ok( section_info
.Size
.QuadPart
== info
.RegionSize
, "NtQuerySection wrong size %x%08x / %08lx\n",
684 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
, info
.RegionSize
);
685 CloseHandle( mapping
);
689 /* read/write mapping with SEC_RESERVE */
690 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
| SEC_RESERVE
, 0, MAPPING_SIZE
, NULL
);
691 ok(mapping
!= INVALID_HANDLE_VALUE
, "CreateFileMappingA failed with error %d\n", GetLastError());
692 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
693 sizeof(section_info
), NULL
);
694 ok( !status
, "NtQuerySection failed err %x\n", status
);
695 ok( section_info
.Attributes
== SEC_RESERVE
, "NtQuerySection wrong attr %08x\n",
696 section_info
.Attributes
);
697 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
698 ok( section_info
.Size
.QuadPart
== MAPPING_SIZE
, "NtQuerySection wrong size %x%08x / %08x\n",
699 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
, MAPPING_SIZE
);
701 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
702 ok(ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
704 ptr2
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
705 ok( ptr2
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
706 ok( ptr
!= ptr2
, "MapViewOfFile returned same pointer\n" );
708 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
709 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
710 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
711 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
712 ok(info
.RegionSize
== MAPPING_SIZE
, "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
713 ok(info
.State
== MEM_RESERVE
, "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
714 ok(info
.AllocationProtect
== PAGE_READWRITE
,
715 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
716 ok(info
.Protect
== 0, "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
717 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
719 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
720 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
721 ok(info
.BaseAddress
== ptr2
,
722 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
723 ok(info
.AllocationBase
== ptr2
,
724 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
725 ok(info
.AllocationProtect
== PAGE_READWRITE
,
726 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
727 ok(info
.RegionSize
== MAPPING_SIZE
,
728 "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
729 ok(info
.State
== MEM_RESERVE
, "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
730 ok(info
.Protect
== 0, "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
731 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
733 ptr
= VirtualAlloc(ptr
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
734 ok(ptr
!= NULL
, "VirtualAlloc failed with error %d\n", GetLastError());
736 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
737 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
738 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
739 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
740 ok(info
.RegionSize
== 0x10000, "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
741 ok(info
.State
== MEM_COMMIT
, "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
742 ok(info
.Protect
== PAGE_READONLY
, "Protect should have been PAGE_READONLY instead of 0x%x\n", info
.Protect
);
743 ok(info
.AllocationProtect
== PAGE_READWRITE
,
744 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
745 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
747 /* shows that the VirtualAlloc above affects the mapping, not just the
748 * virtual memory in this process - it also affects all other processes
749 * with a view of the mapping, but that isn't tested here */
750 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
751 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
752 ok(info
.BaseAddress
== ptr2
,
753 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
754 ok(info
.AllocationBase
== ptr2
,
755 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
756 ok(info
.AllocationProtect
== PAGE_READWRITE
,
757 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
758 ok(info
.RegionSize
== 0x10000,
759 "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
760 ok(info
.State
== MEM_COMMIT
,
761 "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
762 ok(info
.Protect
== PAGE_READWRITE
,
763 "Protect should have been PAGE_READWRITE instead of 0x%x\n", info
.Protect
);
764 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
766 addr
= VirtualAlloc( ptr
, MAPPING_SIZE
, MEM_RESET
, PAGE_READONLY
);
767 ok( addr
== ptr
, "VirtualAlloc failed with error %u\n", GetLastError() );
769 ret
= VirtualFree( ptr
, 0x10000, MEM_DECOMMIT
);
770 ok( !ret
, "VirtualFree succeeded\n" );
771 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "VirtualFree failed with %u\n", GetLastError() );
773 ret
= UnmapViewOfFile(ptr2
);
774 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
775 ret
= UnmapViewOfFile(ptr
);
776 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
777 CloseHandle(mapping
);
779 addr
= VirtualAlloc(NULL
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
780 ok( addr
!= NULL
, "VirtualAlloc failed with error %u\n", GetLastError() );
782 SetLastError(0xdeadbeef);
783 ok( !UnmapViewOfFile(addr
), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
784 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
785 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
786 SetLastError(0xdeadbeef);
787 ok( !UnmapViewOfFile((char *)addr
+ 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
788 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
789 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
790 SetLastError(0xdeadbeef);
791 ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
792 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
793 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
795 ok( VirtualFree(addr
, 0, MEM_RELEASE
), "VirtualFree failed\n" );
797 /* close named mapping handle without unmapping */
799 SetLastError(0xdeadbeef);
800 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
801 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
802 SetLastError(0xdeadbeef);
803 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
804 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
805 SetLastError(0xdeadbeef);
806 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
807 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
808 SetLastError(0xdeadbeef);
809 ret
= CloseHandle(map2
);
810 ok(ret
, "CloseHandle error %d\n", GetLastError());
811 SetLastError(0xdeadbeef);
812 ret
= CloseHandle(mapping
);
813 ok(ret
, "CloseHandle error %d\n", GetLastError());
815 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
816 ok( !ret
, "memory is not accessible\n" );
818 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
819 ok(ret
, "VirtualQuery error %d\n", GetLastError());
820 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
821 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
822 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
823 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
824 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
825 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
826 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
828 SetLastError(0xdeadbeef);
829 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
831 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
833 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
834 if (map2
) CloseHandle(map2
); /* FIXME: remove once Wine is fixed */
835 SetLastError(0xdeadbeef);
836 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
837 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
839 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set error %d\n", GetLastError() );
840 SetLastError(0xdeadbeef);
841 ret
= CloseHandle(mapping
);
842 ok(ret
, "CloseHandle error %d\n", GetLastError());
844 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
845 ok( !ret
, "memory is not accessible\n" );
847 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
848 ok(ret
, "VirtualQuery error %d\n", GetLastError());
849 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
850 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
851 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
852 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
853 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
854 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
855 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
857 SetLastError(0xdeadbeef);
858 ret
= UnmapViewOfFile(ptr
);
859 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
861 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
862 ok( ret
, "memory is accessible\n" );
864 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
865 ok(ret
, "VirtualQuery error %d\n", GetLastError());
866 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
867 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
868 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
869 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
870 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
871 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
873 SetLastError(0xdeadbeef);
874 file
= CreateFileA(testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
875 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
876 SetFilePointer(file
, 4096, NULL
, FILE_BEGIN
);
879 SetLastError(0xdeadbeef);
880 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
881 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
882 SetLastError(0xdeadbeef);
883 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
884 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
885 SetLastError(0xdeadbeef);
886 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
887 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
888 SetLastError(0xdeadbeef);
889 ret
= CloseHandle(map2
);
890 ok(ret
, "CloseHandle error %d\n", GetLastError());
891 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
892 sizeof(section_info
), &info_size
);
893 ok( !status
, "NtQuerySection failed err %x\n", status
);
894 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
895 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
896 section_info
.Attributes
);
897 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
898 ok( section_info
.Size
.QuadPart
== MAPPING_SIZE
, "NtQuerySection wrong size %x%08x\n",
899 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
900 SetLastError(0xdeadbeef);
901 ret
= CloseHandle(mapping
);
902 ok(ret
, "CloseHandle error %d\n", GetLastError());
904 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
905 ok( !ret
, "memory is not accessible\n" );
907 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
908 ok(ret
, "VirtualQuery error %d\n", GetLastError());
909 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
910 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
911 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
912 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
913 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
914 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
915 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
917 SetLastError(0xdeadbeef);
918 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
920 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
922 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
924 SetLastError(0xdeadbeef);
925 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
926 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
928 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set error %d\n", GetLastError() );
929 SetLastError(0xdeadbeef);
930 ret
= CloseHandle(mapping
);
931 ok(ret
, "CloseHandle error %d\n", GetLastError());
933 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
934 ok( !ret
, "memory is not accessible\n" );
936 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
937 ok(ret
, "VirtualQuery error %d\n", GetLastError());
938 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
939 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
940 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
941 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
942 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
943 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
944 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
946 SetLastError(0xdeadbeef);
947 ret
= UnmapViewOfFile(ptr
);
948 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
950 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
951 ok( ret
, "memory is accessible\n" );
953 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
954 ok(ret
, "VirtualQuery error %d\n", GetLastError());
955 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
956 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
957 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
958 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
959 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
960 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
962 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 12288, NULL
);
963 ok( mapping
!= NULL
, "CreateFileMappingA failed with error %u\n", GetLastError() );
965 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 12288 );
966 ok( ptr
!= NULL
, "MapViewOfFile failed with error %u\n", GetLastError() );
968 ret
= UnmapViewOfFile( (char *)ptr
+ 100 );
969 ok( ret
, "UnmapViewOfFile failed with error %u\n", GetLastError() );
971 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 12288 );
972 ok( ptr
!= NULL
, "MapViewOfFile failed with error %u\n", GetLastError() );
974 ret
= UnmapViewOfFile( (char *)ptr
+ 4096 );
975 ok( ret
, "UnmapViewOfFile failed with error %u\n", GetLastError() );
977 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 12288 );
978 ok( ptr
!= NULL
, "MapViewOfFile failed with error %u\n", GetLastError() );
980 ret
= UnmapViewOfFile( (char *)ptr
+ 4096 + 100 );
981 ok( ret
, "UnmapViewOfFile failed with error %u\n", GetLastError() );
983 CloseHandle(mapping
);
985 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 36, NULL
);
986 ok( mapping
!= NULL
, "CreateFileMappingA failed with error %u\n", GetLastError() );
987 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
988 sizeof(section_info
), &info_size
);
989 ok( !status
, "NtQuerySection failed err %x\n", status
);
990 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
991 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
992 section_info
.Attributes
);
993 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
995 ok( section_info
.Size
.QuadPart
== 36, "NtQuerySection wrong size %x%08x\n",
996 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
997 CloseHandle(mapping
);
999 SetFilePointer(file
, 0x3456, NULL
, FILE_BEGIN
);
1001 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
1002 ok( mapping
!= NULL
, "CreateFileMappingA failed with error %u\n", GetLastError() );
1003 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
1004 sizeof(section_info
), &info_size
);
1005 ok( !status
, "NtQuerySection failed err %x\n", status
);
1006 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
1007 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
1008 section_info
.Attributes
);
1009 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
1011 ok( section_info
.Size
.QuadPart
== 0x3456, "NtQuerySection wrong size %x%08x\n",
1012 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
1013 CloseHandle(mapping
);
1015 map_size
.QuadPart
= 0x3457;
1016 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1017 &map_size
, PAGE_READONLY
, SEC_COMMIT
, file
);
1019 ok( status
== STATUS_SECTION_TOO_BIG
, "NtCreateSection failed %x\n", status
);
1020 if (!status
) CloseHandle( mapping
);
1021 map_size
.QuadPart
= 0x3452;
1022 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1023 &map_size
, PAGE_READONLY
, SEC_COMMIT
, file
);
1024 ok( !status
, "NtCreateSection failed %x\n", status
);
1025 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
, sizeof(section_info
), NULL
);
1026 ok( !status
, "NtQuerySection failed err %x\n", status
);
1027 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
1028 section_info
.Attributes
);
1029 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
1031 ok( section_info
.Size
.QuadPart
== 0x3452, "NtQuerySection wrong size %x%08x\n",
1032 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
1033 CloseHandle(mapping
);
1035 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1036 &map_size
, PAGE_READONLY
, SEC_COMMIT
, 0 );
1037 ok( !status
, "NtCreateSection failed %x\n", status
);
1038 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
, sizeof(section_info
), NULL
);
1039 ok( !status
, "NtQuerySection failed err %x\n", status
);
1040 ok( section_info
.Attributes
== SEC_COMMIT
, "NtQuerySection wrong attr %08x\n",
1041 section_info
.Attributes
);
1042 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
1043 ok( section_info
.Size
.QuadPart
== 0x4000, "NtQuerySection wrong size %x%08x\n",
1044 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
1045 CloseHandle(mapping
);
1048 DeleteFileA(testfile
);
1051 static void test_NtMapViewOfSection(void)
1055 static const char testfile
[] = "testfile.xxx";
1056 static const char data
[] = "test data for NtMapViewOfSection";
1057 char buffer
[sizeof(data
)];
1058 HANDLE file
, mapping
;
1061 DWORD status
, written
;
1062 SIZE_T size
, result
;
1063 LARGE_INTEGER offset
;
1065 if (!pNtMapViewOfSection
|| !pNtUnmapViewOfSection
)
1067 win_skip( "NtMapViewOfSection not available\n" );
1071 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1072 ok( file
!= INVALID_HANDLE_VALUE
, "Failed to create test file\n" );
1073 WriteFile( file
, data
, sizeof(data
), &written
, NULL
);
1074 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1075 SetEndOfFile( file
);
1077 /* read/write mapping */
1079 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1080 ok( mapping
!= 0, "CreateFileMapping failed\n" );
1082 hProcess
= create_target_process("sleep");
1083 ok(hProcess
!= NULL
, "Can't start process\n");
1087 offset
.QuadPart
= 0;
1088 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1089 ok( !status
, "NtMapViewOfSection failed status %x\n", status
);
1090 ok( !((ULONG_PTR
)ptr
& 0xffff), "returned memory %p is not aligned to 64k\n", ptr
);
1092 ret
= ReadProcessMemory( hProcess
, ptr
, buffer
, sizeof(buffer
), &result
);
1093 ok( ret
, "ReadProcessMemory failed\n" );
1094 ok( result
== sizeof(buffer
), "ReadProcessMemory didn't read all data (%lx)\n", result
);
1095 ok( !memcmp( buffer
, data
, sizeof(buffer
) ), "Wrong data read\n" );
1097 /* for some unknown reason NtMapViewOfSection fails with STATUS_NO_MEMORY when zero_bits != 0 ? */
1100 offset
.QuadPart
= 0;
1101 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1103 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1104 if (status
== STATUS_SUCCESS
)
1106 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1107 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1112 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1114 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1115 if (status
== STATUS_SUCCESS
)
1117 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1118 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1121 /* mapping at the same page conflicts */
1124 offset
.QuadPart
= 0;
1125 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1126 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1128 /* offset has to be aligned */
1131 offset
.QuadPart
= 1;
1132 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1133 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1135 /* ptr has to be aligned */
1136 ptr2
= (char *)ptr
+ 42;
1138 offset
.QuadPart
= 0;
1139 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1140 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1142 /* still not 64k aligned */
1143 ptr2
= (char *)ptr
+ 0x1000;
1145 offset
.QuadPart
= 0;
1146 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1147 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1149 /* zero_bits != 0 is not allowed when an address is set */
1150 ptr2
= (char *)ptr
+ 0x1000;
1152 offset
.QuadPart
= 0;
1153 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1154 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1156 ptr2
= (char *)ptr
+ 0x1000;
1158 offset
.QuadPart
= 0;
1159 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1160 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1162 ptr2
= (char *)ptr
+ 0x1001;
1164 offset
.QuadPart
= 0;
1165 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1166 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1168 ptr2
= (char *)ptr
+ 0x1000;
1170 offset
.QuadPart
= 1;
1171 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1172 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1174 if (sizeof(void *) == sizeof(int) && (!pIsWow64Process
||
1175 !pIsWow64Process( GetCurrentProcess(), &is_wow64
) || !is_wow64
))
1177 /* new memory region conflicts with previous mapping */
1180 offset
.QuadPart
= 0;
1181 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1182 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1183 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1185 ptr2
= (char *)ptr
+ 42;
1187 offset
.QuadPart
= 0;
1188 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1189 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1190 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1192 /* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
1193 ptr2
= (char *)ptr
+ 0x1000;
1195 offset
.QuadPart
= 0;
1196 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1197 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1198 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1199 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1200 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1201 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1202 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1204 /* the address is rounded down if not on a page boundary */
1205 ptr2
= (char *)ptr
+ 0x1001;
1207 offset
.QuadPart
= 0;
1208 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1209 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1210 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1211 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1212 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1213 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1214 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1216 ptr2
= (char *)ptr
+ 0x2000;
1218 offset
.QuadPart
= 0;
1219 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1220 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1221 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1222 ok( (char *)ptr2
== (char *)ptr
+ 0x2000,
1223 "expected address %p, got %p\n", (char *)ptr
+ 0x2000, ptr2
);
1224 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1225 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1229 ptr2
= (char *)ptr
+ 0x1000;
1231 offset
.QuadPart
= 0;
1232 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1233 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1235 ok( status
== STATUS_INVALID_PARAMETER_9
, "NtMapViewOfSection returned %x\n", status
);
1238 status
= pNtUnmapViewOfSection( hProcess
, ptr
);
1239 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1241 CloseHandle( mapping
);
1242 CloseHandle( file
);
1243 DeleteFileA( testfile
);
1245 TerminateProcess(hProcess
, 0);
1246 CloseHandle(hProcess
);
1249 static void test_NtAreMappedFilesTheSame(void)
1251 static const char testfile
[] = "testfile.xxx";
1252 HANDLE file
, file2
, mapping
, map2
;
1255 char path
[MAX_PATH
];
1257 if (!pNtAreMappedFilesTheSame
)
1259 win_skip( "NtAreMappedFilesTheSame not available\n" );
1263 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1264 NULL
, CREATE_ALWAYS
, 0, 0 );
1265 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1266 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1267 SetEndOfFile( file
);
1269 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1270 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1272 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1273 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1275 file2
= CreateFileA( testfile
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1276 NULL
, OPEN_EXISTING
, 0, 0 );
1277 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1279 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1280 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1281 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1282 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1283 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1284 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1285 UnmapViewOfFile( ptr2
);
1287 ptr2
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1288 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1289 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1290 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1291 UnmapViewOfFile( ptr2
);
1292 CloseHandle( map2
);
1294 map2
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1295 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1296 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1297 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1298 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1299 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1300 UnmapViewOfFile( ptr2
);
1301 CloseHandle( map2
);
1302 CloseHandle( file2
);
1304 status
= pNtAreMappedFilesTheSame( ptr
, ptr
);
1305 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1306 "NtAreMappedFilesTheSame returned %x\n", status
);
1308 status
= pNtAreMappedFilesTheSame( ptr
, (char *)ptr
+ 30 );
1309 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1310 "NtAreMappedFilesTheSame returned %x\n", status
);
1312 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1313 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1315 status
= pNtAreMappedFilesTheSame( ptr
, (void *)0xdeadbeef );
1316 ok( status
== STATUS_CONFLICTING_ADDRESSES
|| status
== STATUS_INVALID_ADDRESS
,
1317 "NtAreMappedFilesTheSame returned %x\n", status
);
1319 status
= pNtAreMappedFilesTheSame( ptr
, NULL
);
1320 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1322 status
= pNtAreMappedFilesTheSame( ptr
, (void *)GetProcessHeap() );
1323 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1325 status
= pNtAreMappedFilesTheSame( NULL
, NULL
);
1326 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1328 ptr2
= VirtualAlloc( NULL
, 0x10000, MEM_COMMIT
, PAGE_READWRITE
);
1329 ok( ptr2
!= NULL
, "VirtualAlloc error %u\n", GetLastError() );
1330 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1331 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1332 VirtualFree( ptr2
, 0, MEM_RELEASE
);
1334 UnmapViewOfFile( ptr
);
1335 CloseHandle( mapping
);
1336 CloseHandle( file
);
1338 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
1339 GetModuleHandleA("kernel32.dll") );
1340 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1341 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1342 GetModuleHandleA("kernel32.dll") );
1343 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1344 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1345 (char *)GetModuleHandleA("kernel32.dll") + 4096 );
1346 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1348 GetSystemDirectoryA( path
, MAX_PATH
);
1349 strcat( path
, "\\kernel32.dll" );
1350 file
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1351 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1353 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1354 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1355 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1356 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1357 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1358 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1359 UnmapViewOfFile( ptr
);
1360 CloseHandle( mapping
);
1362 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1363 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1364 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
1365 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1366 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1368 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1370 file2
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1371 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1372 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1373 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1374 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 0 );
1375 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1376 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1377 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1378 UnmapViewOfFile( ptr2
);
1379 CloseHandle( map2
);
1380 CloseHandle( file2
);
1382 UnmapViewOfFile( ptr
);
1383 CloseHandle( mapping
);
1385 CloseHandle( file
);
1386 DeleteFileA( testfile
);
1389 static void test_CreateFileMapping(void)
1391 HANDLE handle
, handle2
;
1393 /* test case sensitivity */
1395 SetLastError(0xdeadbeef);
1396 handle
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1397 "Wine Test Mapping");
1398 ok( handle
!= NULL
, "CreateFileMapping failed with error %u\n", GetLastError());
1399 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1401 SetLastError(0xdeadbeef);
1402 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1403 "Wine Test Mapping");
1404 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1405 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
1406 CloseHandle( handle2
);
1408 SetLastError(0xdeadbeef);
1409 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1410 "WINE TEST MAPPING");
1411 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1412 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1413 CloseHandle( handle2
);
1415 SetLastError(0xdeadbeef);
1416 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "Wine Test Mapping");
1417 ok( handle2
!= NULL
, "OpenFileMapping failed with error %d\n", GetLastError());
1418 CloseHandle( handle2
);
1420 SetLastError(0xdeadbeef);
1421 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "WINE TEST MAPPING");
1422 ok( !handle2
, "OpenFileMapping succeeded\n");
1423 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
1425 CloseHandle( handle
);
1428 static void test_IsBadReadPtr(void)
1431 void *ptr
= (void *)0xdeadbeef;
1434 ret
= IsBadReadPtr(NULL
, 0);
1435 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1437 ret
= IsBadReadPtr(NULL
, 1);
1438 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1440 ret
= IsBadReadPtr(ptr
, 0);
1441 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1443 ret
= IsBadReadPtr(ptr
, 1);
1444 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1446 ret
= IsBadReadPtr(&stackvar
, 0);
1447 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1449 ret
= IsBadReadPtr(&stackvar
, sizeof(char));
1450 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1453 static void test_IsBadWritePtr(void)
1456 void *ptr
= (void *)0xdeadbeef;
1459 ret
= IsBadWritePtr(NULL
, 0);
1460 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1462 ret
= IsBadWritePtr(NULL
, 1);
1463 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1465 ret
= IsBadWritePtr(ptr
, 0);
1466 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1468 ret
= IsBadWritePtr(ptr
, 1);
1469 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1471 ret
= IsBadWritePtr(&stackval
, 0);
1472 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1474 ret
= IsBadWritePtr(&stackval
, sizeof(char));
1475 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1478 static void test_IsBadCodePtr(void)
1481 void *ptr
= (void *)0xdeadbeef;
1484 ret
= IsBadCodePtr(NULL
);
1485 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1487 ret
= IsBadCodePtr(ptr
);
1488 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1490 ret
= IsBadCodePtr((void *)&stackval
);
1491 ok(ret
== FALSE
, "Expected IsBadCodePtr to return FALSE, got %d\n", ret
);
1494 static void test_write_watch(void)
1496 static const char pipename
[] = "\\\\.\\pipe\\test_write_watch_pipe";
1497 static const char testdata
[] = "Hello World";
1498 DWORD ret
, size
, old_prot
, num_bytes
;
1499 MEMORY_BASIC_INFORMATION info
;
1500 HANDLE readpipe
, writepipe
;
1501 OVERLAPPED overlapped
;
1508 if (!pGetWriteWatch
|| !pResetWriteWatch
)
1510 win_skip( "GetWriteWatch not supported\n" );
1515 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1517 (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
1519 win_skip( "MEM_WRITE_WATCH not supported\n" );
1522 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1523 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1524 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1525 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1526 ok( info
.AllocationProtect
== PAGE_READWRITE
, "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1527 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1528 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1529 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1530 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1533 SetLastError( 0xdeadbeef );
1534 ret
= pGetWriteWatch( 0, NULL
, size
, results
, &count
, &pagesize
);
1535 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1536 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
1537 broken( GetLastError() == 0xdeadbeef ), /* win98 */
1538 "wrong error %u\n", GetLastError() );
1540 SetLastError( 0xdeadbeef );
1541 ret
= pGetWriteWatch( 0, GetModuleHandleW(NULL
), size
, results
, &count
, &pagesize
);
1544 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1545 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1549 ok( count
== 0, "wrong count %lu\n", count
);
1552 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1553 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1554 ok( count
== 0, "wrong count %lu\n", count
);
1556 base
[pagesize
+ 1] = 0x44;
1559 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1560 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1561 ok( count
== 1, "wrong count %lu\n", count
);
1562 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1565 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1566 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1567 ok( count
== 1, "wrong count %lu\n", count
);
1568 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1571 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1572 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1573 ok( count
== 0, "wrong count %lu\n", count
);
1575 base
[2*pagesize
+ 3] = 0x11;
1576 base
[4*pagesize
+ 8] = 0x11;
1579 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1580 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1581 ok( count
== 2, "wrong count %lu\n", count
);
1582 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1583 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1586 ret
= pGetWriteWatch( 0, base
+ 3*pagesize
, 2*pagesize
, results
, &count
, &pagesize
);
1587 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1588 ok( count
== 1, "wrong count %lu\n", count
);
1589 ok( results
[0] == base
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1591 ret
= pResetWriteWatch( base
, 3*pagesize
);
1592 ok( !ret
, "pResetWriteWatch failed %u\n", GetLastError() );
1595 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1596 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1597 ok( count
== 1, "wrong count %lu\n", count
);
1598 ok( results
[0] == base
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1600 *(DWORD
*)(base
+ 2*pagesize
- 2) = 0xdeadbeef;
1603 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1604 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1605 ok( count
== 3, "wrong count %lu\n", count
);
1606 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1607 ok( results
[1] == base
+ 2*pagesize
, "wrong result %p\n", results
[1] );
1608 ok( results
[2] == base
+ 4*pagesize
, "wrong result %p\n", results
[2] );
1611 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1612 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1613 ok( count
== 1, "wrong count %lu\n", count
);
1614 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1617 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1618 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1619 ok( count
== 2, "wrong count %lu\n", count
);
1620 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1621 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1623 /* changing protections doesn't affect watches */
1625 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READONLY
, &old_prot
);
1626 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1627 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1629 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1630 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1631 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1632 ok( info
.RegionSize
== 3*pagesize
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1633 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1634 ok( info
.Protect
== PAGE_READONLY
, "wrong Protect 0x%x\n", info
.Protect
);
1636 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READWRITE
, &old_prot
);
1637 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1638 ok( old_prot
== PAGE_READONLY
, "wrong old prot %x\n", old_prot
);
1641 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1642 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1643 ok( count
== 2, "wrong count %lu\n", count
);
1644 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1645 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1647 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1648 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1649 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1650 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1651 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1652 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1654 /* ReadFile should trigger write watches */
1656 memset( &overlapped
, 0, sizeof(overlapped
) );
1657 overlapped
.hEvent
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1659 readpipe
= CreateNamedPipeA( pipename
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_INBOUND
,
1660 PIPE_TYPE_BYTE
| PIPE_WAIT
, 1, 1024, 1024,
1661 NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1662 ok( readpipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipeA failed %u\n", GetLastError() );
1664 success
= ConnectNamedPipe( readpipe
, &overlapped
);
1665 ok( !success
, "ConnectNamedPipe unexpectedly succeeded\n" );
1666 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1668 writepipe
= CreateFileA( pipename
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
1669 ok( writepipe
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %u\n", GetLastError() );
1671 ret
= WaitForSingleObject( overlapped
.hEvent
, 1000 );
1672 ok( ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", ret
);
1674 memset( base
, 0, size
);
1677 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1678 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1679 ok( count
== 16, "wrong count %lu\n", count
);
1681 success
= ReadFile( readpipe
, base
, size
, NULL
, &overlapped
);
1682 ok( !success
, "ReadFile unexpectedly succeeded\n" );
1683 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1686 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1687 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1688 ok( count
== 16, "wrong count %lu\n", count
);
1691 success
= WriteFile( writepipe
, testdata
, sizeof(testdata
), &num_bytes
, NULL
);
1692 ok( success
, "WriteFile failed %u\n", GetLastError() );
1693 ok( num_bytes
== sizeof(testdata
), "wrong number of bytes written\n" );
1696 success
= GetOverlappedResult( readpipe
, &overlapped
, &num_bytes
, TRUE
);
1697 todo_wine
ok( success
, "GetOverlappedResult failed %u\n", GetLastError() );
1698 todo_wine
ok( num_bytes
== sizeof(testdata
), "wrong number of bytes read\n" );
1699 todo_wine
ok( !memcmp( base
, testdata
, sizeof(testdata
)), "didn't receive expected data\n" );
1702 memset( results
, 0, sizeof(results
) );
1703 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1704 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1705 todo_wine
ok( count
== 1, "wrong count %lu\n", count
);
1706 todo_wine
ok( results
[0] == base
, "wrong result %p\n", results
[0] );
1708 CloseHandle( readpipe
);
1709 CloseHandle( writepipe
);
1710 CloseHandle( overlapped
.hEvent
);
1712 /* some invalid parameter tests */
1714 SetLastError( 0xdeadbeef );
1716 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1719 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1720 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1722 SetLastError( 0xdeadbeef );
1723 ret
= pGetWriteWatch( 0, base
, size
, results
, NULL
, &pagesize
);
1724 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1725 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1727 SetLastError( 0xdeadbeef );
1729 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, NULL
);
1730 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1731 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1733 SetLastError( 0xdeadbeef );
1735 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1736 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1737 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1739 SetLastError( 0xdeadbeef );
1741 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1742 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1743 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1745 SetLastError( 0xdeadbeef );
1747 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1748 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1749 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1751 SetLastError( 0xdeadbeef );
1753 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1754 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1755 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1757 SetLastError( 0xdeadbeef );
1759 ret
= pGetWriteWatch( 0, base
, size
* 2, results
, &count
, &pagesize
);
1760 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1761 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1763 SetLastError( 0xdeadbeef );
1765 ret
= pGetWriteWatch( 0, base
+ size
- pagesize
, pagesize
+ 1, results
, &count
, &pagesize
);
1766 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1767 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1769 SetLastError( 0xdeadbeef );
1770 ret
= pResetWriteWatch( base
, 0 );
1771 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1772 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1774 SetLastError( 0xdeadbeef );
1775 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1776 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1777 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1779 else /* win98 is completely different */
1781 SetLastError( 0xdeadbeef );
1783 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1784 ok( ret
== ERROR_INVALID_PARAMETER
, "GetWriteWatch succeeded %u\n", ret
);
1785 ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
1788 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1789 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1792 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1793 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1796 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1797 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1799 ret
= pResetWriteWatch( base
, 0 );
1800 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1802 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1803 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1806 VirtualFree( base
, 0, MEM_RELEASE
);
1808 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1809 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1810 VirtualFree( base
, 0, MEM_RELEASE
);
1812 base
= VirtualAlloc( 0, size
, MEM_WRITE_WATCH
, PAGE_READWRITE
);
1813 ok( !base
, "VirtualAlloc succeeded\n" );
1814 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1816 /* initial protect doesn't matter */
1818 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_NOACCESS
);
1819 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1820 base
= VirtualAlloc( base
, size
, MEM_COMMIT
, PAGE_NOACCESS
);
1821 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1824 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1825 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1826 ok( count
== 0, "wrong count %lu\n", count
);
1828 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_READWRITE
, &old_prot
);
1829 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1830 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
1832 base
[5*pagesize
+ 200] = 3;
1834 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_NOACCESS
, &old_prot
);
1835 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1836 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1839 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1840 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1841 ok( count
== 1, "wrong count %lu\n", count
);
1842 ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1844 ret
= VirtualFree( base
, size
, MEM_DECOMMIT
);
1845 ok( ret
, "VirtualFree failed %u\n", GetLastError() );
1848 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1849 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1850 ok( count
== 1 || broken(count
== 0), /* win98 */
1851 "wrong count %lu\n", count
);
1852 if (count
) ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1854 VirtualFree( base
, 0, MEM_RELEASE
);
1857 #if defined(__i386__) || defined(__x86_64__)
1859 static DWORD WINAPI
stack_commit_func( void *arg
)
1861 volatile char *p
= (char *)&p
;
1863 /* trigger all guard pages, to ensure that the pages are committed */
1864 while (p
>= (char *)NtCurrentTeb()->DeallocationStack
+ 4 * 0x1000)
1870 ok( arg
== (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg
);
1874 static void test_stack_commit(void)
1877 static const char code_call_on_stack
[] = {
1878 0x55, /* pushl %ebp */
1879 0x56, /* pushl %esi */
1880 0x89, 0xe6, /* movl %esp,%esi */
1881 0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */
1882 0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */
1883 0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */
1884 0x83, 0xe0, 0xf0, /* andl $~15,%eax */
1885 0x83, 0xe8, 0x0c, /* subl $12,%eax */
1886 0x89, 0xc4, /* movl %eax,%esp */
1887 0x52, /* pushl %edx */
1888 0x31, 0xed, /* xorl %ebp,%ebp */
1889 0xff, 0xd1, /* call *%ecx */
1890 0x89, 0xf4, /* movl %esi,%esp */
1891 0x5e, /* popl %esi */
1892 0x5d, /* popl %ebp */
1893 0xc2, 0x0c, 0x00 }; /* ret $12 */
1895 static const char code_call_on_stack
[] = {
1896 0x55, /* pushq %rbp */
1897 0x48, 0x89, 0xe5, /* movq %rsp,%rbp */
1898 /* %rcx - func, %rdx - arg, %r8 - stack */
1899 0x48, 0x87, 0xca, /* xchgq %rcx,%rdx */
1900 0x49, 0x83, 0xe0, 0xf0, /* andq $~15,%r8 */
1901 0x49, 0x83, 0xe8, 0x20, /* subq $0x20,%r8 */
1902 0x4c, 0x89, 0xc4, /* movq %r8,%rsp */
1903 0xff, 0xd2, /* callq *%rdx */
1904 0x48, 0x89, 0xec, /* movq %rbp,%rsp */
1905 0x5d, /* popq %rbp */
1908 DWORD (WINAPI
*call_on_stack
)( DWORD (WINAPI
*func
)(void *), void *arg
, void *stack
);
1909 void *old_stack
, *old_stack_base
, *old_stack_limit
;
1910 void *new_stack
, *new_stack_base
;
1913 call_on_stack
= VirtualAlloc( 0, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
1914 ok( call_on_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1915 memcpy( call_on_stack
, code_call_on_stack
, sizeof(code_call_on_stack
) );
1917 /* allocate a new stack, only the first guard page is committed */
1918 new_stack
= VirtualAlloc( 0, 0x400000, MEM_RESERVE
, PAGE_READWRITE
);
1919 ok( new_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1920 new_stack_base
= (char *)new_stack
+ 0x400000;
1921 VirtualAlloc( (char *)new_stack_base
- 0x1000, 0x1000, MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
1923 old_stack
= NtCurrentTeb()->DeallocationStack
;
1924 old_stack_base
= NtCurrentTeb()->Tib
.StackBase
;
1925 old_stack_limit
= NtCurrentTeb()->Tib
.StackLimit
;
1927 NtCurrentTeb()->DeallocationStack
= new_stack
;
1928 NtCurrentTeb()->Tib
.StackBase
= new_stack_base
;
1929 NtCurrentTeb()->Tib
.StackLimit
= new_stack_base
;
1931 result
= call_on_stack( stack_commit_func
, (void *)0xdeadbeef, new_stack_base
);
1933 NtCurrentTeb()->DeallocationStack
= old_stack
;
1934 NtCurrentTeb()->Tib
.StackBase
= old_stack_base
;
1935 NtCurrentTeb()->Tib
.StackLimit
= old_stack_limit
;
1937 ok( result
== 42, "expected 42, got %u\n", result
);
1939 VirtualFree( new_stack
, 0, MEM_RELEASE
);
1940 VirtualFree( call_on_stack
, 0, MEM_RELEASE
);
1943 #endif /* defined(__i386__) || defined(__x86_64__) */
1946 static LONG num_guard_page_calls
;
1948 static DWORD
guard_page_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
1949 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
1951 trace( "exception: %08x flags:%x addr:%p\n",
1952 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
);
1954 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
1955 ok( rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
, "ExceptionCode is %08x instead of %08x\n",
1956 rec
->ExceptionCode
, STATUS_GUARD_PAGE_VIOLATION
);
1958 InterlockedIncrement( &num_guard_page_calls
);
1959 *(int *)rec
->ExceptionInformation
[1] += 0x100;
1961 return ExceptionContinueExecution
;
1964 static void test_guard_page(void)
1966 EXCEPTION_REGISTRATION_RECORD frame
;
1967 MEMORY_BASIC_INFORMATION info
;
1968 DWORD ret
, size
, old_prot
;
1969 int *value
, old_value
;
1977 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
1978 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1979 value
= (int *)base
;
1981 /* verify info structure */
1982 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1983 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
1984 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1985 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1986 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1987 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1988 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
1989 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1991 /* put some initial value into the memory */
1992 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
1993 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1994 ok( old_prot
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong old prot %x\n", old_prot
);
1999 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2000 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2001 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2003 /* test behaviour of VirtualLock - first attempt should fail */
2004 SetLastError( 0xdeadbeef );
2005 success
= VirtualLock( base
, size
);
2006 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
2008 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
2010 success
= VirtualLock( base
, size
);
2012 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2015 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2016 success
= VirtualUnlock( base
, size
);
2017 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2020 /* check info structure again, PAGE_GUARD should be removed now */
2021 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2022 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
2023 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
2024 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
2025 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
2026 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
2028 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
2029 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
2031 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2032 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2034 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2036 /* test directly accessing the memory - we need to setup an exception handler first */
2037 frame
.Handler
= guard_page_handler
;
2038 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2039 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2041 InterlockedExchange( &num_guard_page_calls
, 0 );
2042 InterlockedExchange( &old_value
, *value
); /* exception handler increments value by 0x100 */
2044 ok( old_value
== 0x101, "memory block contains wrong value, expected 0x101, got 0x%x\n", old_value
);
2045 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2047 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2049 /* check info structure again, PAGE_GUARD should be removed now */
2050 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2051 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
2052 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
2054 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2055 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2056 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2058 /* test accessing second integer in memory */
2059 frame
.Handler
= guard_page_handler
;
2060 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2061 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2063 InterlockedExchange( &num_guard_page_calls
, 0 );
2064 old_value
= *(value
+ 1);
2065 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
2066 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
2067 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2069 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2071 success
= VirtualLock( base
, size
);
2072 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2075 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
2076 success
= VirtualUnlock( base
, size
);
2077 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2080 VirtualFree( base
, 0, MEM_RELEASE
);
2082 /* combined guard page / write watch tests */
2083 if (!pGetWriteWatch
|| !pResetWriteWatch
)
2085 win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" );
2089 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
| PAGE_GUARD
);
2090 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
2092 win_skip( "MEM_WRITE_WATCH not supported\n" );
2095 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2096 value
= (int *)base
;
2098 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2099 ok( ret
, "VirtualQuery failed %u\n", GetLastError() );
2100 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
2101 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
2102 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
2103 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
2104 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
2105 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
2108 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
2109 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2110 ok( count
== 0, "wrong count %lu\n", count
);
2112 /* writing to a page should trigger should trigger guard page, even if write watch is set */
2113 frame
.Handler
= guard_page_handler
;
2114 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2115 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2117 InterlockedExchange( &num_guard_page_calls
, 0 );
2120 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2122 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2125 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2126 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2127 ok( count
== 1, "wrong count %lu\n", count
);
2128 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2130 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2131 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2133 /* write watch is triggered from inside of the guard page handler */
2134 frame
.Handler
= guard_page_handler
;
2135 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2136 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2138 InterlockedExchange( &num_guard_page_calls
, 0 );
2139 old_value
= *(value
+ 1); /* doesn't trigger write watch */
2140 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
2141 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2142 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2144 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2147 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2148 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2149 ok( count
== 1, "wrong count %lu\n", count
);
2150 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2152 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2153 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2155 /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */
2156 SetLastError( 0xdeadbeef );
2157 success
= VirtualLock( base
, size
);
2158 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
2160 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
2163 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
2164 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2165 ok( count
== 0, "wrong count %lu\n", count
);
2167 success
= VirtualLock( base
, size
);
2169 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2172 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2173 success
= VirtualUnlock( base
, size
);
2174 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2178 results
[0] = (void *)0xdeadbeef;
2179 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2180 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2182 ok( count
== 1 || broken(count
== 0) /* Windows 8 */, "wrong count %lu\n", count
);
2184 ok( results
[0] == base
|| broken(results
[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results
[0] );
2186 VirtualFree( base
, 0, MEM_RELEASE
);
2189 static LONG num_execute_fault_calls
;
2191 static DWORD
execute_fault_seh_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
2192 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
2194 ULONG flags
= MEM_EXECUTE_OPTION_ENABLE
;
2197 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2198 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2199 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2201 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2202 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
|| rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
,
2203 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec
->ExceptionCode
);
2205 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &flags
, sizeof(flags
), NULL
);
2207 if (rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
)
2210 err
= IsProcessorFeaturePresent( PF_NX_ENABLED
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2211 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2212 (DWORD
)rec
->ExceptionInformation
[0], err
);
2214 InterlockedIncrement( &num_guard_page_calls
);
2216 else if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2221 err
= (flags
& MEM_EXECUTE_OPTION_DISABLE
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2222 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2223 (DWORD
)rec
->ExceptionInformation
[0], err
);
2225 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2226 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2227 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2229 InterlockedIncrement( &num_execute_fault_calls
);
2232 return ExceptionContinueExecution
;
2235 static LONG CALLBACK
execute_fault_vec_handler( EXCEPTION_POINTERS
*ExceptionInfo
)
2237 PEXCEPTION_RECORD rec
= ExceptionInfo
->ExceptionRecord
;
2241 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2242 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2243 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2245 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2246 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
,
2247 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec
->ExceptionCode
);
2249 if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2250 InterlockedIncrement( &num_execute_fault_calls
);
2252 if (rec
->ExceptionInformation
[0] == EXCEPTION_READ_FAULT
)
2253 return EXCEPTION_CONTINUE_SEARCH
;
2255 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2256 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2257 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
2259 return EXCEPTION_CONTINUE_EXECUTION
;
2262 static inline DWORD
send_message_excpt( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2264 EXCEPTION_REGISTRATION_RECORD frame
;
2267 frame
.Handler
= execute_fault_seh_handler
;
2268 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2269 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2271 InterlockedExchange( &num_guard_page_calls
, 0 );
2272 InterlockedExchange( &num_execute_fault_calls
, 0 );
2273 ret
= SendMessageA( hWnd
, uMsg
, wParam
, lParam
);
2275 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2280 static inline DWORD
call_proc_excpt( DWORD (CALLBACK
*code
)(void *), void *arg
)
2282 EXCEPTION_REGISTRATION_RECORD frame
;
2285 frame
.Handler
= execute_fault_seh_handler
;
2286 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2287 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2289 InterlockedExchange( &num_guard_page_calls
, 0 );
2290 InterlockedExchange( &num_execute_fault_calls
, 0 );
2293 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2298 static LRESULT CALLBACK
jmp_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2300 if (uMsg
== WM_USER
)
2303 return DefWindowProcA( hWnd
, uMsg
, wParam
, lParam
);
2306 static LRESULT CALLBACK
atl_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2308 DWORD arg
= (DWORD
)hWnd
;
2309 if (uMsg
== WM_USER
)
2310 ok( arg
== 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg
);
2312 ok( arg
!= 0x11223344, "arg is unexpectedly 0x11223344\n" );
2316 static DWORD CALLBACK
atl5_test_func( void )
2321 static void test_atl_thunk_emulation( ULONG dep_flags
)
2323 static const char code_jmp
[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
2324 static const char code_atl1
[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2325 static const char code_atl2
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2326 static const char code_atl3
[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1};
2327 static const char code_atl4
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
2328 static const char code_atl5
[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04};
2329 static const char cls_name
[] = "atl_thunk_class";
2330 DWORD ret
, size
, old_prot
;
2331 ULONG old_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2332 BOOL success
, restore_flags
= FALSE
;
2340 trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2342 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
), NULL
);
2343 if (old_flags
!= dep_flags
)
2345 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &dep_flags
, sizeof(dep_flags
) );
2346 if (ret
== STATUS_INVALID_INFO_CLASS
) /* Windows 2000 */
2348 win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2351 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2352 restore_flags
= TRUE
;
2356 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
2357 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2359 /* Check result of GetProcessDEPPolicy */
2360 if (!pGetProcessDEPPolicy
)
2361 win_skip( "GetProcessDEPPolicy not supported\n" );
2364 BOOL (WINAPI
*get_dep_policy
)(HANDLE
, LPDWORD
, PBOOL
) = (void *)base
;
2365 BOOL policy_permanent
= 0xdeadbeef;
2366 DWORD policy_flags
= 0xdeadbeef;
2368 /* GetProcessDEPPolicy crashes on Windows when a NULL pointer is passed.
2369 * Moreover this function has a bug on Windows 8, which has the effect that
2370 * policy_permanent is set to the content of the CL register instead of 0,
2371 * when the policy is not permanent. To detect that we use an assembler
2372 * wrapper to call the function. */
2374 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2375 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)pGetProcessDEPPolicy
- (DWORD_PTR
)(base
+ 10);
2377 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2378 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2380 success
= get_dep_policy( GetCurrentProcess(), &policy_flags
, &policy_permanent
);
2381 ok( success
, "GetProcessDEPPolicy failed %u\n", GetLastError() );
2384 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2385 ret
|= PROCESS_DEP_ENABLE
;
2386 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
)
2387 ret
|= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
;
2389 ok( policy_flags
== ret
, "expected policy flags %d, got %d\n", ret
, policy_flags
);
2390 ok( !policy_permanent
|| broken(policy_permanent
== 0x44),
2391 "expected policy permanent FALSE, got %d\n", policy_permanent
);
2394 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2395 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2397 /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
2398 * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
2399 * where it is active, so that application which depend on that still work properly.
2400 * We have no exception handler enabled yet, so give proper EXECUTE permissions to
2401 * prevent crashes while creating the window. */
2403 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2404 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2406 memset( &wc
, 0, sizeof(wc
) );
2407 wc
.cbSize
= sizeof(wc
);
2408 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2409 wc
.hInstance
= GetModuleHandleA( 0 );
2410 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2411 wc
.hbrBackground
= NULL
;
2412 wc
.lpszClassName
= cls_name
;
2413 wc
.lpfnWndProc
= (WNDPROC
)base
;
2414 success
= RegisterClassExA(&wc
) != 0;
2415 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2417 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2418 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2420 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2421 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2423 /* At first try with an instruction which is not recognized as proper ATL thunk
2424 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2425 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2427 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2428 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2430 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2431 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2432 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2433 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !IsProcessorFeaturePresent( PF_NX_ENABLED
))
2435 trace( "DEP hardware support is not available\n" );
2436 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2437 dep_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2439 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2441 trace( "DEP hardware support is available\n" );
2442 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2445 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2447 /* Now a bit more complicated, the page containing the code is protected with
2448 * PAGE_GUARD memory protection. */
2450 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2451 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2453 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2454 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2455 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2456 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2457 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2459 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2461 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2462 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2463 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2464 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2466 /* Now test with a proper ATL thunk instruction. */
2468 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2469 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2471 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2472 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2474 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2475 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2477 /* Try executing with PAGE_READWRITE protection. */
2479 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2480 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2482 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2483 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2484 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2485 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2486 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2488 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2490 /* Now a bit more complicated, the page containing the code is protected with
2491 * PAGE_GUARD memory protection. */
2493 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2494 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2496 /* the same, but with PAGE_GUARD set */
2497 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2498 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2499 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2500 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2501 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2503 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2505 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2506 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2507 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2508 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2510 /* The following test shows that on Windows, even a vectored exception handler
2511 * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */
2513 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !(dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2515 if (pRtlAddVectoredExceptionHandler
&& pRtlRemoveVectoredExceptionHandler
)
2517 PVOID vectored_handler
;
2519 success
= VirtualProtect( base
, size
, PAGE_NOACCESS
, &old_prot
);
2520 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2522 vectored_handler
= pRtlAddVectoredExceptionHandler( TRUE
, &execute_fault_vec_handler
);
2523 ok( vectored_handler
!= 0, "RtlAddVectoredExceptionHandler failed\n" );
2525 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2527 pRtlRemoveVectoredExceptionHandler( vectored_handler
);
2529 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2530 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2533 win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" );
2536 /* Test alternative ATL thunk instructions. */
2538 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2539 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 10);
2541 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2542 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2544 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2545 /* FIXME: we don't check the content of the register ECX yet */
2546 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2547 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2548 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2549 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2551 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2553 memcpy( base
, code_atl3
, sizeof(code_atl3
) );
2554 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2556 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2557 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2559 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2560 /* FIXME: we don't check the content of the registers ECX/EDX yet */
2561 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2562 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2563 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2564 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2566 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2568 memcpy( base
, code_atl4
, sizeof(code_atl4
) );
2569 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2571 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2572 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2574 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2575 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2576 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2577 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2578 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2579 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2580 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2581 ok( num_execute_fault_calls
== 0 || broken(num_execute_fault_calls
== 1) /* Windows XP */,
2582 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2584 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2586 memcpy( base
, code_atl5
, sizeof(code_atl5
) );
2588 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2589 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2591 ret
= (DWORD_PTR
)atl5_test_func
;
2592 ret
= call_proc_excpt( (void *)base
, &ret
- 1 );
2593 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2594 ok( ret
== 44, "call returned wrong result, expected 44, got %d\n", ret
);
2595 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2596 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2597 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2598 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2599 ok( num_execute_fault_calls
== 0 || broken(num_execute_fault_calls
== 1) /* Windows XP */,
2600 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2602 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2604 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2606 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2607 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2609 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2610 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2612 DestroyWindow( hWnd
);
2614 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2615 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2617 VirtualFree( base
, 0, MEM_RELEASE
);
2619 /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */
2621 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
2622 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
2624 win_skip( "MEM_WRITE_WATCH not supported\n" );
2627 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2630 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2631 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2632 ok( count
== 0, "wrong count %lu\n", count
);
2634 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2635 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2638 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2639 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2640 ok( count
== 1, "wrong count %lu\n", count
);
2641 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2643 /* Create a new window class and associated Window (see above) */
2645 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2646 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2648 memset( &wc
, 0, sizeof(wc
) );
2649 wc
.cbSize
= sizeof(wc
);
2650 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2651 wc
.hInstance
= GetModuleHandleA( 0 );
2652 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2653 wc
.hbrBackground
= NULL
;
2654 wc
.lpszClassName
= cls_name
;
2655 wc
.lpfnWndProc
= (WNDPROC
)base
;
2656 success
= RegisterClassExA(&wc
) != 0;
2657 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2659 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2660 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2662 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2663 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2666 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2667 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2668 ok( count
== 0, "wrong count %lu\n", count
);
2670 /* At first try with an instruction which is not recognized as proper ATL thunk
2671 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2672 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2674 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2675 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2677 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2678 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2679 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2680 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2681 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2683 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2686 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2687 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2688 ok( count
== 0, "wrong count %lu\n", count
);
2690 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2691 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2692 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2693 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2695 /* Now a bit more complicated, the page containing the code is protected with
2696 * PAGE_GUARD memory protection. */
2698 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2699 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2701 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2702 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2703 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2704 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2705 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2707 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2709 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2710 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2711 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2712 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2715 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2716 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2717 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2719 /* Now test with a proper ATL thunk instruction. */
2721 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2722 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2725 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2726 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2727 ok( count
== 1, "wrong count %lu\n", count
);
2728 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2730 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2731 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2733 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2734 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2736 /* Try executing with PAGE_READWRITE protection. */
2738 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2739 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2741 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2742 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2743 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2744 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2745 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2747 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2750 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2751 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2752 ok( count
== 0, "wrong count %lu\n", count
);
2754 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2755 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2756 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2757 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2758 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2760 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2762 /* Now a bit more complicated, the page containing the code is protected with
2763 * PAGE_GUARD memory protection. */
2765 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2766 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2768 /* the same, but with PAGE_GUARD set */
2769 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2770 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2771 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2772 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2773 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2775 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2777 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2778 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2779 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2780 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2783 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2784 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2785 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2787 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2789 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2790 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2793 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2794 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2795 ok( count
== 1, "wrong count %lu\n", count
);
2796 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2798 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2799 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2801 DestroyWindow( hWnd
);
2803 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2804 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2806 VirtualFree( base
, 0, MEM_RELEASE
);
2811 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
) );
2812 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2816 #endif /* __i386__ */
2818 static void test_VirtualProtect(void)
2820 static const struct test_data
2822 DWORD prot_set
, prot_get
;
2825 { 0, 0 }, /* 0x00 */
2826 { PAGE_NOACCESS
, PAGE_NOACCESS
}, /* 0x01 */
2827 { PAGE_READONLY
, PAGE_READONLY
}, /* 0x02 */
2828 { PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x03 */
2829 { PAGE_READWRITE
, PAGE_READWRITE
}, /* 0x04 */
2830 { PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x05 */
2831 { PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x06 */
2832 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x07 */
2833 { PAGE_WRITECOPY
, 0 }, /* 0x08 */
2834 { PAGE_WRITECOPY
| PAGE_NOACCESS
, 0 }, /* 0x09 */
2835 { PAGE_WRITECOPY
| PAGE_READONLY
, 0 }, /* 0x0a */
2836 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, 0 }, /* 0x0b */
2837 { PAGE_WRITECOPY
| PAGE_READWRITE
, 0 }, /* 0x0c */
2838 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x0d */
2839 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x0e */
2840 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x0f */
2842 { PAGE_EXECUTE
, PAGE_EXECUTE
}, /* 0x10 */
2843 { PAGE_EXECUTE_READ
, PAGE_EXECUTE_READ
}, /* 0x20 */
2844 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x30 */
2845 { PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
2846 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0x50 */
2847 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0x60 */
2848 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x70 */
2849 { PAGE_EXECUTE_WRITECOPY
, 0 }, /* 0x80 */
2850 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, 0 }, /* 0x90 */
2851 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, 0 }, /* 0xa0 */
2852 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0xb0 */
2853 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, 0 }, /* 0xc0 */
2854 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0xd0 */
2855 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0xe0 */
2856 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 } /* 0xf0 */
2859 DWORD ret
, old_prot
, rw_prot
, exec_prot
, i
, j
;
2860 MEMORY_BASIC_INFORMATION info
;
2867 trace("system page size %#x\n", si
.dwPageSize
);
2869 SetLastError(0xdeadbeef);
2870 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_RESERVE
| MEM_COMMIT
, PAGE_NOACCESS
);
2871 ok(base
!= NULL
, "VirtualAlloc failed %d\n", GetLastError());
2873 SetLastError(0xdeadbeef);
2874 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_READONLY
, NULL
);
2875 ok(!ret
, "VirtualProtect should fail\n");
2876 ok(GetLastError() == ERROR_NOACCESS
, "expected ERROR_NOACCESS, got %d\n", GetLastError());
2877 old_prot
= 0xdeadbeef;
2878 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2879 ok(ret
, "VirtualProtect failed %d\n", GetLastError());
2880 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2883 size
= si
.dwPageSize
;
2884 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_READONLY
, NULL
);
2885 ok(status
== STATUS_ACCESS_VIOLATION
, "NtProtectVirtualMemory should fail, got %08x\n", status
);
2887 size
= si
.dwPageSize
;
2888 old_prot
= 0xdeadbeef;
2889 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_NOACCESS
, &old_prot
);
2890 ok(status
== STATUS_SUCCESS
, "NtProtectVirtualMemory should succeed, got %08x\n", status
);
2891 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2893 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
2895 SetLastError(0xdeadbeef);
2896 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2897 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2898 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2899 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2900 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
2901 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2902 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2903 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2904 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2906 old_prot
= 0xdeadbeef;
2907 SetLastError(0xdeadbeef);
2908 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot_set
, &old_prot
);
2911 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2912 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
2914 SetLastError(0xdeadbeef);
2915 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2916 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2917 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2918 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2919 ok(info
.Protect
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_get
);
2920 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2921 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2922 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2923 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2927 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
2928 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
2931 old_prot
= 0xdeadbeef;
2932 SetLastError(0xdeadbeef);
2933 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2934 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2936 ok(old_prot
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_get
);
2938 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
2943 for (i
= 0; i
<= 4; i
++)
2947 for (j
= 0; j
<= 4; j
++)
2949 DWORD prot
= exec_prot
| rw_prot
;
2951 SetLastError(0xdeadbeef);
2952 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, prot
);
2953 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
2955 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
2956 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2960 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
2962 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
2963 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2967 ok(ptr
!= NULL
, "VirtualAlloc(%02x) error %d\n", prot
, GetLastError());
2968 ok(ptr
== base
, "expected %p, got %p\n", base
, ptr
);
2972 SetLastError(0xdeadbeef);
2973 ret
= VirtualProtect(base
, si
.dwPageSize
, prot
, &old_prot
);
2974 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
2976 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
2977 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2981 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
2983 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
2984 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2987 ok(ret
, "VirtualProtect(%02x) error %d\n", prot
, GetLastError());
2993 exec_prot
= 1 << (i
+ 4);
2996 VirtualFree(base
, 0, MEM_RELEASE
);
2999 static BOOL
is_mem_writable(DWORD prot
)
3001 switch (prot
& 0xff)
3003 case PAGE_READWRITE
:
3004 case PAGE_WRITECOPY
:
3005 case PAGE_EXECUTE_READWRITE
:
3006 case PAGE_EXECUTE_WRITECOPY
:
3014 static void test_VirtualAlloc_protection(void)
3016 static const struct test_data
3022 { 0, FALSE
}, /* 0x00 */
3023 { PAGE_NOACCESS
, TRUE
}, /* 0x01 */
3024 { PAGE_READONLY
, TRUE
}, /* 0x02 */
3025 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x03 */
3026 { PAGE_READWRITE
, TRUE
}, /* 0x04 */
3027 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x05 */
3028 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x06 */
3029 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x07 */
3030 { PAGE_WRITECOPY
, FALSE
}, /* 0x08 */
3031 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
}, /* 0x09 */
3032 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
}, /* 0x0a */
3033 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
}, /* 0x0b */
3034 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
}, /* 0x0c */
3035 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x0d */
3036 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x0e */
3037 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x0f */
3039 { PAGE_EXECUTE
, TRUE
}, /* 0x10 */
3040 { PAGE_EXECUTE_READ
, TRUE
}, /* 0x20 */
3041 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x30 */
3042 { PAGE_EXECUTE_READWRITE
, TRUE
}, /* 0x40 */
3043 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0x50 */
3044 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0x60 */
3045 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x70 */
3046 { PAGE_EXECUTE_WRITECOPY
, FALSE
}, /* 0x80 */
3047 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
}, /* 0x90 */
3048 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xa0 */
3049 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0xb0 */
3050 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
}, /* 0xc0 */
3051 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0xd0 */
3052 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xe0 */
3053 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
} /* 0xf0 */
3057 MEMORY_BASIC_INFORMATION info
;
3061 trace("system page size %#x\n", si
.dwPageSize
);
3063 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3065 SetLastError(0xdeadbeef);
3066 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3070 ok(base
!= NULL
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3072 SetLastError(0xdeadbeef);
3073 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3074 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3075 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3076 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3077 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3078 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3079 ok(info
.AllocationProtect
== td
[i
].prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, td
[i
].prot
);
3080 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3081 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
3083 if (is_mem_writable(info
.Protect
))
3087 SetLastError(0xdeadbeef);
3088 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3089 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3090 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3093 SetLastError(0xdeadbeef);
3094 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3095 ok(ptr
== base
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3097 VirtualFree(base
, 0, MEM_RELEASE
);
3101 ok(!base
, "%d: VirtualAlloc should fail\n", i
);
3102 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3107 static void test_CreateFileMapping_protection(void)
3109 static const struct test_data
3113 DWORD prot_after_write
;
3116 { 0, FALSE
, 0 }, /* 0x00 */
3117 { PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x01 */
3118 { PAGE_READONLY
, TRUE
, PAGE_READONLY
}, /* 0x02 */
3119 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x03 */
3120 { PAGE_READWRITE
, TRUE
, PAGE_READWRITE
}, /* 0x04 */
3121 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x05 */
3122 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x06 */
3123 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x07 */
3124 { PAGE_WRITECOPY
, TRUE
, PAGE_READWRITE
}, /* 0x08 */
3125 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x09 */
3126 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0a */
3127 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0b */
3128 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0x0c */
3129 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0d */
3130 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0e */
3131 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0f */
3133 { PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE
}, /* 0x10 */
3134 { PAGE_EXECUTE_READ
, TRUE
, PAGE_EXECUTE_READ
}, /* 0x20 */
3135 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE_READ
}, /* 0x30 */
3136 { PAGE_EXECUTE_READWRITE
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
3137 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x50 */
3138 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0x60 */
3139 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x70 */
3140 { PAGE_EXECUTE_WRITECOPY
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x80 */
3141 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x90 */
3142 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xa0 */
3143 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xb0 */
3144 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0xc0 */
3145 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xd0 */
3146 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xe0 */
3147 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
} /* 0xf0 */
3150 DWORD ret
, i
, alloc_prot
, prot
, old_prot
;
3151 MEMORY_BASIC_INFORMATION info
;
3153 char temp_path
[MAX_PATH
];
3154 char file_name
[MAX_PATH
];
3156 BOOL page_exec_supported
= TRUE
;
3159 trace("system page size %#x\n", si
.dwPageSize
);
3161 GetTempPathA(MAX_PATH
, temp_path
);
3162 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3164 SetLastError(0xdeadbeef);
3165 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3166 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3167 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3168 SetEndOfFile(hfile
);
3170 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3172 SetLastError(0xdeadbeef);
3173 hmap
= CreateFileMappingW(hfile
, NULL
, td
[i
].prot
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3179 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, td
[i
].prot
, GetLastError());
3180 /* NT4 and win2k don't support EXEC on file mappings */
3181 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3183 page_exec_supported
= FALSE
;
3184 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3187 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3188 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3190 page_exec_supported
= FALSE
;
3191 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3195 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, td
[i
].prot
, GetLastError());
3197 base
= MapViewOfFile(hmap
, FILE_MAP_READ
, 0, 0, 0);
3198 ok(base
!= NULL
, "%d: MapViewOfFile failed %d\n", i
, GetLastError());
3200 SetLastError(0xdeadbeef);
3201 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3202 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3203 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3204 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3205 ok(info
.Protect
== PAGE_READONLY
, "%d: got %#x != expected PAGE_READONLY\n", i
, info
.Protect
);
3206 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3207 ok(info
.AllocationProtect
== PAGE_READONLY
, "%d: %#x != PAGE_READONLY\n", i
, info
.AllocationProtect
);
3208 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3209 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3211 if (is_mem_writable(info
.Protect
))
3215 SetLastError(0xdeadbeef);
3216 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3217 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3218 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3221 SetLastError(0xdeadbeef);
3222 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3223 ok(!ptr
, "%d: VirtualAlloc(%02x) should fail\n", i
, td
[i
].prot
);
3224 /* FIXME: remove once Wine is fixed */
3225 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3226 ok(GetLastError() == ERROR_ACCESS_DENIED
, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i
, GetLastError());
3228 SetLastError(0xdeadbeef);
3229 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3230 if (td
[i
].prot
== PAGE_READONLY
|| td
[i
].prot
== PAGE_WRITECOPY
)
3231 ok(ret
, "%d: VirtualProtect(%02x) error %d\n", i
, td
[i
].prot
, GetLastError());
3234 ok(!ret
, "%d: VirtualProtect(%02x) should fail\n", i
, td
[i
].prot
);
3235 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3238 UnmapViewOfFile(base
);
3243 ok(!hmap
, "%d: CreateFileMapping should fail\n", i
);
3244 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3248 if (page_exec_supported
) alloc_prot
= PAGE_EXECUTE_READWRITE
;
3249 else alloc_prot
= PAGE_READWRITE
;
3250 SetLastError(0xdeadbeef);
3251 hmap
= CreateFileMappingW(hfile
, NULL
, alloc_prot
, 0, si
.dwPageSize
, NULL
);
3252 ok(hmap
!= 0, "%d: CreateFileMapping error %d\n", i
, GetLastError());
3254 SetLastError(0xdeadbeef);
3255 base
= MapViewOfFile(hmap
, FILE_MAP_READ
| FILE_MAP_WRITE
| (page_exec_supported
? FILE_MAP_EXECUTE
: 0), 0, 0, 0);
3256 ok(base
!= NULL
, "MapViewOfFile failed %d\n", GetLastError());
3258 old_prot
= 0xdeadbeef;
3259 SetLastError(0xdeadbeef);
3260 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3261 ok(ret
, "VirtualProtect error %d\n", GetLastError());
3262 ok(old_prot
== alloc_prot
, "got %#x != expected %#x\n", old_prot
, alloc_prot
);
3264 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3266 SetLastError(0xdeadbeef);
3267 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3268 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3269 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3270 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3271 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
3272 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3273 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3274 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3275 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3277 old_prot
= 0xdeadbeef;
3278 SetLastError(0xdeadbeef);
3279 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3280 if (td
[i
].success
|| td
[i
].prot
== PAGE_NOACCESS
|| td
[i
].prot
== PAGE_EXECUTE
)
3284 /* win2k and XP don't support EXEC on file mappings */
3285 if (td
[i
].prot
== PAGE_EXECUTE
)
3287 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3290 /* NT4 and win2k don't support EXEC on file mappings */
3291 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3293 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3296 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3297 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3299 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3304 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3305 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
3308 /* looks strange but Windows doesn't do this for PAGE_WRITECOPY */
3309 if (prot
== PAGE_EXECUTE_WRITECOPY
) prot
= PAGE_EXECUTE_READWRITE
;
3311 SetLastError(0xdeadbeef);
3312 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3313 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3314 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3315 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3316 /* FIXME: remove the condition below once Wine is fixed */
3317 todo_wine_if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3318 ok(info
.Protect
== prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, prot
);
3319 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3320 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3321 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3322 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3324 if (is_mem_writable(info
.Protect
))
3328 SetLastError(0xdeadbeef);
3329 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3330 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3331 /* FIXME: remove the condition below once Wine is fixed */
3332 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3333 ok(info
.Protect
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_after_write
);
3338 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
3339 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3343 old_prot
= 0xdeadbeef;
3344 SetLastError(0xdeadbeef);
3345 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3346 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3347 /* FIXME: remove the condition below once Wine is fixed */
3348 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3349 ok(old_prot
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_after_write
);
3352 UnmapViewOfFile(base
);
3356 DeleteFileA(file_name
);
3359 #define ACCESS_READ 0x01
3360 #define ACCESS_WRITE 0x02
3361 #define ACCESS_EXECUTE 0x04
3362 #define ACCESS_WRITECOPY 0x08
3364 static DWORD
page_prot_to_access(DWORD prot
)
3368 case PAGE_READWRITE
:
3369 return ACCESS_READ
| ACCESS_WRITE
;
3372 case PAGE_EXECUTE_READ
:
3373 return ACCESS_READ
| ACCESS_EXECUTE
;
3375 case PAGE_EXECUTE_READWRITE
:
3376 return ACCESS_READ
| ACCESS_WRITE
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3378 case PAGE_EXECUTE_WRITECOPY
:
3379 return ACCESS_READ
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3384 case PAGE_WRITECOPY
:
3392 static BOOL
is_compatible_protection(DWORD map_prot
, DWORD view_prot
, DWORD prot
)
3394 DWORD map_access
, view_access
, prot_access
;
3396 map_access
= page_prot_to_access(map_prot
);
3397 view_access
= page_prot_to_access(view_prot
);
3398 prot_access
= page_prot_to_access(prot
);
3400 if (view_access
== prot_access
) return TRUE
;
3401 if (!view_access
) return FALSE
;
3403 if ((view_access
& prot_access
) != prot_access
) return FALSE
;
3404 if ((map_access
& prot_access
) == prot_access
) return TRUE
;
3409 static DWORD
map_prot_to_access(DWORD prot
)
3413 case PAGE_READWRITE
:
3414 case PAGE_EXECUTE_READWRITE
:
3415 return SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3417 case PAGE_WRITECOPY
:
3419 case PAGE_EXECUTE_READ
:
3420 case PAGE_EXECUTE_WRITECOPY
:
3421 return SECTION_MAP_READ
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3427 static BOOL
is_compatible_access(DWORD map_prot
, DWORD view_prot
)
3429 DWORD access
= map_prot_to_access(map_prot
);
3430 if (!view_prot
) view_prot
= SECTION_MAP_READ
;
3431 return (view_prot
& access
) == view_prot
;
3434 static void *map_view_of_file(HANDLE handle
, DWORD access
)
3437 LARGE_INTEGER offset
;
3443 if (!pNtMapViewOfSection
) return NULL
;
3446 offset
.u
.LowPart
= 0;
3447 offset
.u
.HighPart
= 0;
3449 exec
= access
& FILE_MAP_EXECUTE
;
3450 access
&= ~FILE_MAP_EXECUTE
;
3452 if (access
== FILE_MAP_COPY
)
3455 protect
= PAGE_EXECUTE_WRITECOPY
;
3457 protect
= PAGE_WRITECOPY
;
3459 else if (access
& FILE_MAP_WRITE
)
3462 protect
= PAGE_EXECUTE_READWRITE
;
3464 protect
= PAGE_READWRITE
;
3466 else if (access
& FILE_MAP_READ
)
3469 protect
= PAGE_EXECUTE_READ
;
3471 protect
= PAGE_READONLY
;
3473 else protect
= PAGE_NOACCESS
;
3476 status
= pNtMapViewOfSection(handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
3477 &count
, 1 /* ViewShare */, 0, protect
);
3480 /* for simplicity */
3481 SetLastError(ERROR_ACCESS_DENIED
);
3487 static void test_mapping(void)
3489 static const DWORD page_prot
[] =
3491 PAGE_NOACCESS
, PAGE_READONLY
, PAGE_READWRITE
, PAGE_WRITECOPY
,
3492 PAGE_EXECUTE_READ
, PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_WRITECOPY
3499 { 0, PAGE_NOACCESS
}, /* 0x00 */
3500 { FILE_MAP_COPY
, PAGE_WRITECOPY
}, /* 0x01 */
3501 { FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x02 */
3502 { FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x03 */
3503 { FILE_MAP_READ
, PAGE_READONLY
}, /* 0x04 */
3504 { FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x05 */
3505 { FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x06 */
3506 { FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x07 */
3507 { SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x08 */
3508 { SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x09 */
3509 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0a */
3510 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0b */
3511 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_READONLY
}, /* 0x0c */
3512 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x0d */
3513 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0e */
3514 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0f */
3515 { FILE_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x20 */
3516 { FILE_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_EXECUTE_WRITECOPY
}, /* 0x21 */
3517 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x22 */
3518 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x23 */
3519 { FILE_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x24 */
3520 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x25 */
3521 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x26 */
3522 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x27 */
3523 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x28 */
3524 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x29 */
3525 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2a */
3526 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x2b */
3527 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x2c */
3528 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x2d */
3529 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2e */
3530 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
} /* 0x2f */
3532 void *base
, *nt_base
, *ptr
;
3533 DWORD i
, j
, k
, ret
, old_prot
, prev_prot
;
3535 char temp_path
[MAX_PATH
];
3536 char file_name
[MAX_PATH
];
3538 MEMORY_BASIC_INFORMATION info
, nt_info
;
3541 trace("system page size %#x\n", si
.dwPageSize
);
3543 GetTempPathA(MAX_PATH
, temp_path
);
3544 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3546 SetLastError(0xdeadbeef);
3547 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3548 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3549 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3550 SetEndOfFile(hfile
);
3552 for (i
= 0; i
< sizeof(page_prot
)/sizeof(page_prot
[0]); i
++)
3554 SetLastError(0xdeadbeef);
3555 hmap
= CreateFileMappingW(hfile
, NULL
, page_prot
[i
] | SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3557 if (page_prot
[i
] == PAGE_NOACCESS
)
3561 ok(!hmap
, "CreateFileMapping(PAGE_NOACCESS) should fail\n");
3562 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3564 /* A trick to create a not accessible mapping */
3565 SetLastError(0xdeadbeef);
3566 hmap
= CreateFileMappingW(hfile
, NULL
, PAGE_READWRITE
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3567 ok(hmap
!= 0, "CreateFileMapping(PAGE_READWRITE) error %d\n", GetLastError());
3568 SetLastError(0xdeadbeef);
3569 ret
= DuplicateHandle(GetCurrentProcess(), hmap
, GetCurrentProcess(), &hmap2
, 0, FALSE
, 0);
3570 ok(ret
, "DuplicateHandle error %d\n", GetLastError());
3577 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, page_prot
[i
], GetLastError());
3579 /* NT4 and win2k don't support EXEC on file mappings */
3580 if (page_prot
[i
] == PAGE_EXECUTE_READ
|| page_prot
[i
] == PAGE_EXECUTE_READWRITE
)
3582 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3585 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3586 if (page_prot
[i
] == PAGE_EXECUTE_WRITECOPY
)
3588 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3593 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, page_prot
[i
], GetLastError());
3595 for (j
= 0; j
< sizeof(view
)/sizeof(view
[0]); j
++)
3597 nt_base
= map_view_of_file(hmap
, view
[j
].access
);
3600 SetLastError(0xdeadbeef);
3601 ret
= VirtualQuery(nt_base
, &nt_info
, sizeof(nt_info
));
3602 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3603 UnmapViewOfFile(nt_base
);
3606 SetLastError(0xdeadbeef);
3607 base
= MapViewOfFile(hmap
, view
[j
].access
, 0, 0, 0);
3609 /* Vista+ supports FILE_MAP_EXECUTE properly, earlier versions don't */
3610 ok(!nt_base
== !base
||
3611 broken((view
[j
].access
& FILE_MAP_EXECUTE
) && !nt_base
!= !base
),
3612 "%d: (%04x/%04x) NT %p kernel %p\n", j
, page_prot
[i
], view
[j
].access
, nt_base
, base
);
3614 if (!is_compatible_access(page_prot
[i
], view
[j
].access
))
3616 ok(!base
, "%d: MapViewOfFile(%04x/%04x) should fail\n", j
, page_prot
[i
], view
[j
].access
);
3617 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %d\n", GetLastError());
3621 /* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */
3622 if (!base
&& (view
[j
].access
& FILE_MAP_EXECUTE
))
3624 ok(broken(!base
), "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3628 ok(base
!= NULL
, "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3630 SetLastError(0xdeadbeef);
3631 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3632 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3633 ok(info
.BaseAddress
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.BaseAddress
, base
);
3634 ok(info
.RegionSize
== si
.dwPageSize
, "%d: (%04x) got %#lx != expected %#x\n", j
, view
[j
].access
, info
.RegionSize
, si
.dwPageSize
);
3635 ok(info
.Protect
== view
[j
].prot
||
3636 broken(view
[j
].prot
== PAGE_EXECUTE_READ
&& info
.Protect
== PAGE_READONLY
) || /* win2k */
3637 broken(view
[j
].prot
== PAGE_EXECUTE_READWRITE
&& info
.Protect
== PAGE_READWRITE
) || /* win2k */
3638 broken(view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3639 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.Protect
, view
[j
].prot
);
3640 ok(info
.AllocationBase
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.AllocationBase
, base
);
3641 ok(info
.AllocationProtect
== info
.Protect
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.AllocationProtect
, info
.Protect
);
3642 ok(info
.State
== MEM_COMMIT
, "%d: (%04x) got %#x, expected MEM_COMMIT\n", j
, view
[j
].access
, info
.State
);
3643 ok(info
.Type
== MEM_MAPPED
, "%d: (%04x) got %#x, expected MEM_MAPPED\n", j
, view
[j
].access
, info
.Type
);
3645 if (nt_base
&& base
)
3647 ok(nt_info
.RegionSize
== info
.RegionSize
, "%d: (%04x) got %#lx != expected %#lx\n", j
, view
[j
].access
, nt_info
.RegionSize
, info
.RegionSize
);
3648 ok(nt_info
.Protect
== info
.Protect
/* Vista+ */ ||
3649 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3650 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Protect
, info
.Protect
);
3651 ok(nt_info
.AllocationProtect
== info
.AllocationProtect
/* Vista+ */ ||
3652 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3653 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.AllocationProtect
, info
.AllocationProtect
);
3654 ok(nt_info
.State
== info
.State
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.State
, info
.State
);
3655 ok(nt_info
.Type
== info
.Type
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Type
, info
.Type
);
3658 prev_prot
= info
.Protect
;
3660 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3662 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3663 SetLastError(0xdeadbeef);
3664 old_prot
= 0xdeadbeef;
3665 ret
= VirtualProtect(base
, si
.dwPageSize
, page_prot
[k
], &old_prot
);
3666 if (is_compatible_protection(page_prot
[i
], view
[j
].prot
, page_prot
[k
]))
3668 /* win2k and XP don't support EXEC on file mappings */
3669 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE
)
3671 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3674 /* NT4 and win2k don't support EXEC on file mappings */
3675 if (!ret
&& (page_prot
[k
] == PAGE_EXECUTE_READ
|| page_prot
[k
] == PAGE_EXECUTE_READWRITE
))
3677 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3680 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3681 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE_WRITECOPY
)
3683 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n");
3686 /* win2k and XP don't support PAGE_EXECUTE_WRITECOPY views properly */
3687 if (!ret
&& view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
)
3689 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY view properly\n");
3693 ok(ret
, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3694 ok(old_prot
== prev_prot
, "got %#x, expected %#x\n", old_prot
, prev_prot
);
3695 prev_prot
= page_prot
[k
];
3699 /* NT4 doesn't fail on incompatible map and view */
3702 ok(broken(ret
), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3703 skip("Incompatible map and view are not properly handled on this platform\n");
3704 break; /* NT4 won't pass remaining tests */
3707 ok(!ret
, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3708 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3712 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3714 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3715 SetLastError(0xdeadbeef);
3716 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, page_prot
[k
]);
3717 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", page_prot
[k
]);
3718 /* FIXME: remove once Wine is fixed */
3719 todo_wine_if (page_prot
[k
] == PAGE_WRITECOPY
|| page_prot
[k
] == PAGE_EXECUTE_WRITECOPY
)
3720 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3723 UnmapViewOfFile(base
);
3730 DeleteFileA(file_name
);
3733 static void test_shared_memory(BOOL is_child
)
3738 SetLastError(0xdeadbef);
3739 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c");
3740 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3742 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3744 SetLastError(0xdeadbef);
3745 p
= MapViewOfFile(mapping
, FILE_MAP_READ
|FILE_MAP_WRITE
, 0, 0, 4096);
3746 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3750 ok(*p
== 0x1a2b3c4d, "expected 0x1a2b3c4d in child, got %#x\n", *p
);
3755 char cmdline
[MAX_PATH
];
3756 PROCESS_INFORMATION pi
;
3757 STARTUPINFOA si
= { sizeof(si
) };
3762 winetest_get_mainargs(&argv
);
3763 sprintf(cmdline
, "\"%s\" virtual sharedmem", argv
[0]);
3764 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3765 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3766 winetest_wait_child_process(pi
.hProcess
);
3767 CloseHandle(pi
.hThread
);
3768 CloseHandle(pi
.hProcess
);
3772 CloseHandle(mapping
);
3775 static void test_shared_memory_ro(BOOL is_child
, DWORD child_access
)
3780 SetLastError(0xdeadbef);
3781 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c_ro");
3782 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3784 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3786 SetLastError(0xdeadbef);
3787 p
= MapViewOfFile(mapping
, is_child
? child_access
: FILE_MAP_READ
, 0, 0, 4096);
3788 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3797 char cmdline
[MAX_PATH
];
3798 PROCESS_INFORMATION pi
;
3799 STARTUPINFOA si
= { sizeof(si
) };
3802 winetest_get_mainargs(&argv
);
3803 sprintf(cmdline
, "\"%s\" virtual sharedmemro %x", argv
[0], child_access
);
3804 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3805 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3806 winetest_wait_child_process(pi
.hProcess
);
3807 CloseHandle(pi
.hThread
);
3808 CloseHandle(pi
.hProcess
);
3810 if(child_access
& FILE_MAP_WRITE
)
3811 ok(*p
== 0xdeadbeef, "*p = %x, expected 0xdeadbeef\n", *p
);
3813 ok(!*p
, "*p = %x, expected 0\n", *p
);
3817 CloseHandle(mapping
);
3824 argc
= winetest_get_mainargs( &argv
);
3828 if (!strcmp(argv
[2], "sleep"))
3830 Sleep(5000); /* spawned process runs for at most 5 seconds */
3833 if (!strcmp(argv
[2], "sharedmem"))
3835 test_shared_memory(TRUE
);
3838 if (!strcmp(argv
[2], "sharedmemro"))
3840 test_shared_memory_ro(TRUE
, strtol(argv
[3], NULL
, 16));
3847 mem
= VirtualAlloc(NULL
, 1<<20, MEM_COMMIT
|MEM_RESERVE
,
3848 PAGE_EXECUTE_READWRITE
);
3849 ok(mem
!= NULL
, "VirtualAlloc failed %u\n", GetLastError());
3850 if (mem
== NULL
) break;
3851 ret
= VirtualFree(mem
, 0, MEM_RELEASE
);
3852 ok(ret
, "VirtualFree failed %u\n", GetLastError());
3858 hkernel32
= GetModuleHandleA("kernel32.dll");
3859 hntdll
= GetModuleHandleA("ntdll.dll");
3861 pVirtualAllocEx
= (void *) GetProcAddress(hkernel32
, "VirtualAllocEx");
3862 pVirtualFreeEx
= (void *) GetProcAddress(hkernel32
, "VirtualFreeEx");
3863 pGetWriteWatch
= (void *) GetProcAddress(hkernel32
, "GetWriteWatch");
3864 pResetWriteWatch
= (void *) GetProcAddress(hkernel32
, "ResetWriteWatch");
3865 pGetProcessDEPPolicy
= (void *)GetProcAddress( hkernel32
, "GetProcessDEPPolicy" );
3866 pIsWow64Process
= (void *)GetProcAddress( hkernel32
, "IsWow64Process" );
3867 pNtAreMappedFilesTheSame
= (void *)GetProcAddress( hntdll
, "NtAreMappedFilesTheSame" );
3868 pNtCreateSection
= (void *)GetProcAddress( hntdll
, "NtCreateSection" );
3869 pNtMapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtMapViewOfSection" );
3870 pNtUnmapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtUnmapViewOfSection" );
3871 pNtQuerySection
= (void *)GetProcAddress( hntdll
, "NtQuerySection" );
3872 pRtlAddVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlAddVectoredExceptionHandler" );
3873 pRtlRemoveVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlRemoveVectoredExceptionHandler" );
3874 pNtProtectVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtProtectVirtualMemory" );
3875 pNtAllocateVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtAllocateVirtualMemory" );
3876 pNtFreeVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtFreeVirtualMemory" );
3878 test_shared_memory(FALSE
);
3879 test_shared_memory_ro(FALSE
, FILE_MAP_READ
|FILE_MAP_WRITE
);
3880 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
);
3881 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
|FILE_MAP_WRITE
);
3883 test_CreateFileMapping_protection();
3884 test_VirtualAlloc_protection();
3885 test_VirtualProtect();
3886 test_VirtualAllocEx();
3887 test_VirtualAlloc();
3888 test_MapViewOfFile();
3889 test_NtMapViewOfSection();
3890 test_NtAreMappedFilesTheSame();
3891 test_CreateFileMapping();
3892 test_IsBadReadPtr();
3893 test_IsBadWritePtr();
3894 test_IsBadCodePtr();
3896 #if defined(__i386__) || defined(__x86_64__)
3897 test_stack_commit();
3901 /* The following tests should be executed as a last step, and in exactly this
3902 * order, since ATL thunk emulation cannot be enabled anymore on Windows. */
3903 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE
);
3904 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
);
3905 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
| MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
);