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
29 #include "wine/winternl.h"
32 #include "wine/exception.h"
33 #include "wine/test.h"
36 #define MAPPING_SIZE 0x100000
38 static HINSTANCE hkernel32
, hntdll
;
39 static LPVOID (WINAPI
*pVirtualAllocEx
)(HANDLE
, LPVOID
, SIZE_T
, DWORD
, DWORD
);
40 static BOOL (WINAPI
*pVirtualFreeEx
)(HANDLE
, LPVOID
, SIZE_T
, DWORD
);
41 static UINT (WINAPI
*pGetWriteWatch
)(DWORD
,LPVOID
,SIZE_T
,LPVOID
*,ULONG_PTR
*,ULONG
*);
42 static UINT (WINAPI
*pResetWriteWatch
)(LPVOID
,SIZE_T
);
43 static NTSTATUS (WINAPI
*pNtAreMappedFilesTheSame
)(PVOID
,PVOID
);
44 static NTSTATUS (WINAPI
*pNtMapViewOfSection
)(HANDLE
, HANDLE
, PVOID
*, ULONG
, SIZE_T
, const LARGE_INTEGER
*, SIZE_T
*, ULONG
, ULONG
, ULONG
);
45 static DWORD (WINAPI
*pNtUnmapViewOfSection
)(HANDLE
, PVOID
);
46 static struct _TEB
* (WINAPI
*pNtCurrentTeb
)(void);
47 static PVOID (WINAPI
*pRtlAddVectoredExceptionHandler
)(ULONG
, PVECTORED_EXCEPTION_HANDLER
);
48 static ULONG (WINAPI
*pRtlRemoveVectoredExceptionHandler
)(PVOID
);
49 static BOOL (WINAPI
*pGetProcessDEPPolicy
)(HANDLE
, LPDWORD
, PBOOL
);
50 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
51 static NTSTATUS (WINAPI
*pNtQuerySection
)(HANDLE
, int, PVOID
, ULONG
, PULONG
);
52 static NTSTATUS (WINAPI
*pNtProtectVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
, ULONG
*);
53 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG
, SIZE_T
*, ULONG
, ULONG
);
54 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
56 /* ############################### */
58 static UINT_PTR page_mask
= 0xfff;
59 #define ROUND_SIZE(addr,size) \
60 (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
62 static PIMAGE_NT_HEADERS
image_nt_header(HMODULE module
)
64 IMAGE_NT_HEADERS
*ret
= NULL
;
65 IMAGE_DOS_HEADER
*dos
= (IMAGE_DOS_HEADER
*)module
;
67 if (dos
->e_magic
== IMAGE_DOS_SIGNATURE
)
69 ret
= (IMAGE_NT_HEADERS
*)((char *)dos
+ dos
->e_lfanew
);
70 if (ret
->Signature
!= IMAGE_NT_SIGNATURE
) ret
= NULL
;
75 static HANDLE
create_target_process(const char *arg
)
78 char cmdline
[MAX_PATH
];
79 PROCESS_INFORMATION pi
;
81 STARTUPINFOA si
= { 0 };
84 winetest_get_mainargs( &argv
);
85 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], arg
);
86 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
87 ok(ret
, "error: %u\n", GetLastError());
88 ret
= CloseHandle(pi
.hThread
);
89 ok(ret
, "error %u\n", GetLastError());
93 static void test_VirtualAllocEx(void)
95 const unsigned int alloc_size
= 1<<15;
97 SIZE_T bytes_written
= 0, bytes_read
= 0, i
;
101 MEMORY_BASIC_INFORMATION info
;
104 /* not exported in all windows-versions */
105 if ((!pVirtualAllocEx
) || (!pVirtualFreeEx
)) {
106 win_skip("Virtual{Alloc,Free}Ex not available\n");
110 hProcess
= create_target_process("sleep");
111 ok(hProcess
!= NULL
, "Can't start process\n");
113 SetLastError(0xdeadbeef);
114 addr1
= pVirtualAllocEx(hProcess
, NULL
, alloc_size
, MEM_COMMIT
,
115 PAGE_EXECUTE_READWRITE
);
116 if (!addr1
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
118 win_skip("VirtualAllocEx not implemented\n");
119 TerminateProcess(hProcess
, 0);
120 CloseHandle(hProcess
);
124 src
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
125 dst
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
126 for (i
= 0; i
< alloc_size
; i
++)
129 ok(addr1
!= NULL
, "VirtualAllocEx error %u\n", GetLastError());
130 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
131 ok(b
&& (bytes_written
== alloc_size
), "%lu bytes written\n",
133 b
= ReadProcessMemory(hProcess
, addr1
, dst
, alloc_size
, &bytes_read
);
134 ok(b
&& (bytes_read
== alloc_size
), "%lu bytes read\n", bytes_read
);
135 ok(!memcmp(src
, dst
, alloc_size
), "Data from remote process differs\n");
137 /* test invalid source buffers */
139 b
= VirtualProtect( src
+ 0x2000, 0x2000, PAGE_NOACCESS
, &old_prot
);
140 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
141 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
142 ok( !b
, "WriteProcessMemory succeeded\n" );
143 ok( GetLastError() == ERROR_NOACCESS
||
144 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
145 "wrong error %u\n", GetLastError() );
146 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
147 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
148 ok( !b
, "ReadProcessMemory succeeded\n" );
149 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
150 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
152 b
= VirtualProtect( src
, 0x2000, PAGE_NOACCESS
, &old_prot
);
153 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
154 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
155 ok( !b
, "WriteProcessMemory succeeded\n" );
156 ok( GetLastError() == ERROR_NOACCESS
||
157 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
158 "wrong error %u\n", GetLastError() );
159 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
160 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
161 ok( !b
, "ReadProcessMemory succeeded\n" );
162 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
163 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
165 b
= pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
);
166 ok(b
!= 0, "VirtualFreeEx, error %u\n", GetLastError());
168 VirtualFree( src
, 0, MEM_RELEASE
);
169 VirtualFree( dst
, 0, MEM_RELEASE
);
172 * The following tests parallel those in test_VirtualAlloc()
175 SetLastError(0xdeadbeef);
176 addr1
= pVirtualAllocEx(hProcess
, 0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
177 ok(addr1
== NULL
, "VirtualAllocEx should fail on zero-sized allocation\n");
178 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* NT */ ||
179 GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, /* Win9x */
180 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
182 addr1
= pVirtualAllocEx(hProcess
, 0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
183 ok(addr1
!= NULL
, "VirtualAllocEx failed\n");
185 /* test a not committed memory */
186 memset(&info
, 'q', sizeof(info
));
187 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
), "VirtualQueryEx failed\n");
188 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
189 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
190 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
191 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
192 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
193 /* NT reports Protect == 0 for a not committed memory block */
194 ok(info
.Protect
== 0 /* NT */ ||
195 info
.Protect
== PAGE_NOACCESS
, /* Win9x */
196 "%x != PAGE_NOACCESS\n", info
.Protect
);
197 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
199 SetLastError(0xdeadbeef);
200 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
201 "VirtualProtectEx should fail on a not committed memory\n");
202 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
203 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
204 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
206 addr2
= pVirtualAllocEx(hProcess
, addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
207 ok(addr1
== addr2
, "VirtualAllocEx failed\n");
209 /* test a committed memory */
210 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
),
211 "VirtualQueryEx failed\n");
212 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
213 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
214 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
215 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
216 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
217 /* this time NT reports PAGE_NOACCESS as well */
218 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
219 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
221 /* this should fail, since not the whole range is committed yet */
222 SetLastError(0xdeadbeef);
223 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
224 "VirtualProtectEx should fail on a not committed memory\n");
225 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
226 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
227 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
230 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtectEx failed\n");
231 ok(old_prot
== PAGE_NOACCESS
, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
234 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtectEx failed\n");
235 ok(old_prot
== PAGE_READONLY
, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
237 ok(!pVirtualFreeEx(hProcess
, addr1
, 0x10000, 0),
238 "VirtualFreeEx should fail with type 0\n");
239 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
240 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
242 ok(pVirtualFreeEx(hProcess
, addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFreeEx failed\n");
244 /* if the type is MEM_RELEASE, size must be 0 */
245 ok(!pVirtualFreeEx(hProcess
, addr1
, 1, MEM_RELEASE
),
246 "VirtualFreeEx should fail\n");
247 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
248 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
250 ok(pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
), "VirtualFreeEx failed\n");
252 TerminateProcess(hProcess
, 0);
253 CloseHandle(hProcess
);
256 static void test_VirtualAlloc(void)
260 MEMORY_BASIC_INFORMATION info
;
264 SetLastError(0xdeadbeef);
265 addr1
= VirtualAlloc(0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
266 ok(addr1
== NULL
, "VirtualAlloc should fail on zero-sized allocation\n");
267 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* NT */ ||
268 GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, /* Win9x */
269 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
271 addr1
= VirtualAlloc(0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
272 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
274 /* test a not committed memory */
275 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
276 "VirtualQuery failed\n");
277 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
278 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
279 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
280 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
281 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
282 /* NT reports Protect == 0 for a not committed memory block */
283 ok(info
.Protect
== 0 /* NT */ ||
284 info
.Protect
== PAGE_NOACCESS
, /* Win9x */
285 "%x != PAGE_NOACCESS\n", info
.Protect
);
286 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
288 SetLastError(0xdeadbeef);
289 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
290 "VirtualProtect should fail on a not committed memory\n");
291 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
292 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
293 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
295 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
296 ok(addr1
== addr2
, "VirtualAlloc failed\n");
298 /* test a committed memory */
299 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
300 "VirtualQuery failed\n");
301 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
302 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
303 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
304 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
305 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
306 /* this time NT reports PAGE_NOACCESS as well */
307 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
308 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
310 /* this should fail, since not the whole range is committed yet */
311 SetLastError(0xdeadbeef);
312 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
313 "VirtualProtect should fail on a not committed memory\n");
314 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* NT */ ||
315 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x */
316 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
318 ok(VirtualProtect(addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtect failed\n");
319 ok(old_prot
== PAGE_NOACCESS
,
320 "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
322 ok(VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtect failed\n");
323 ok(old_prot
== PAGE_READONLY
,
324 "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
326 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
327 "VirtualQuery failed\n");
328 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
329 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
330 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
331 memset( addr1
, 0x55, 20 );
332 ok( *(DWORD
*)addr1
== 0x55555555, "wrong data %x\n", *(DWORD
*)addr1
);
334 addr2
= VirtualAlloc( addr1
, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
335 ok( addr2
== addr1
|| broken( !addr2
&& GetLastError() == ERROR_INVALID_PARAMETER
), /* win9x */
336 "VirtualAlloc failed err %u\n", GetLastError() );
337 ok( *(DWORD
*)addr1
== 0x55555555 || *(DWORD
*)addr1
== 0, "wrong data %x\n", *(DWORD
*)addr1
);
340 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
341 "VirtualQuery failed\n");
342 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
343 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
344 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
346 addr2
= VirtualAlloc( (char *)addr1
+ 0x1000, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
347 ok( (char *)addr2
== (char *)addr1
+ 0x1000, "VirtualAlloc failed\n" );
349 ok(VirtualQuery(addr2
, &info
, sizeof(info
)) == sizeof(info
),
350 "VirtualQuery failed\n");
351 ok(info
.RegionSize
== 0xf000, "%lx != 0xf000\n", info
.RegionSize
);
352 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
353 ok(info
.Protect
== 0, "%x != 0\n", info
.Protect
);
355 addr2
= VirtualAlloc( (char *)addr1
+ 0xf000, 0x2000, MEM_RESET
, PAGE_NOACCESS
);
356 ok( !addr2
, "VirtualAlloc failed\n" );
357 ok( GetLastError() == ERROR_INVALID_ADDRESS
, "wrong error %u\n", GetLastError() );
360 /* invalid protection values */
361 SetLastError(0xdeadbeef);
362 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_RESERVE
, 0);
363 ok(!addr2
, "VirtualAlloc succeeded\n");
364 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
366 SetLastError(0xdeadbeef);
367 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_COMMIT
, 0);
368 ok(!addr2
, "VirtualAlloc succeeded\n");
369 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
371 SetLastError(0xdeadbeef);
372 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_READONLY
| PAGE_EXECUTE
);
373 ok(!addr2
, "VirtualAlloc succeeded\n");
374 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
376 SetLastError(0xdeadbeef);
377 ok(!VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
| PAGE_EXECUTE_WRITECOPY
, &old_prot
),
378 "VirtualProtect succeeded\n");
379 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
381 SetLastError(0xdeadbeef);
382 ok(!VirtualProtect(addr1
, 0x1000, 0, &old_prot
), "VirtualProtect succeeded\n");
383 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
385 SetLastError(0xdeadbeef);
386 ok(!VirtualFree(addr1
, 0x10000, 0), "VirtualFree should fail with type 0\n");
387 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
388 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
390 SetLastError(0xdeadbeef);
391 ok(!VirtualFree(addr1
, 0, MEM_FREE
), "VirtualFree should fail with type MEM_FREE\n");
392 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
393 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
395 ok(VirtualFree(addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFree failed\n");
397 /* if the type is MEM_RELEASE, size must be 0 */
398 ok(!VirtualFree(addr1
, 1, MEM_RELEASE
), "VirtualFree should fail\n");
399 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
400 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
402 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
404 /* memory returned by VirtualAlloc should be aligned to 64k */
405 addr1
= VirtualAlloc(0, 0x2000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
406 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
407 ok(!((ULONG_PTR
)addr1
& 0xffff), "returned memory %p is not aligned to 64k\n", addr1
);
408 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
409 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
410 ok(addr2
== addr1
, "VirtualAlloc returned %p, expected %p\n", addr2
, addr1
);
412 /* allocation conflicts because of 64k align */
414 addr2
= (char *)addr1
+ 0x1000;
415 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
,
416 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
417 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
419 /* it should conflict, even when zero_bits is explicitly set */
421 addr2
= (char *)addr1
+ 0x1000;
422 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 12, &size
,
423 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
425 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
426 if (status
== STATUS_SUCCESS
) ok(VirtualFree(addr2
, 0, MEM_RELEASE
), "VirtualFree failed\n");
428 /* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
429 SetLastError(0xdeadbeef);
430 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_RESERVE
| MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
431 ok(!addr2
, "VirtualAlloc unexpectedly succeeded\n");
432 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
434 /* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
436 addr2
= (char *)addr1
+ 0x1000;
437 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
, MEM_RESERVE
|
438 MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
440 ok(status
== STATUS_INVALID_PARAMETER_5
, "NtAllocateVirtualMemory returned %08x\n", status
);
442 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
445 static void test_MapViewOfFile(void)
447 static const char testfile
[] = "testfile.xxx";
449 HANDLE file
, mapping
, map2
;
450 void *ptr
, *ptr2
, *addr
;
451 MEMORY_BASIC_INFORMATION info
;
454 SetLastError(0xdeadbeef);
455 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
456 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
457 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
458 SetEndOfFile( file
);
460 /* read/write mapping */
462 SetLastError(0xdeadbeef);
463 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
464 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
466 SetLastError(0xdeadbeef);
467 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
468 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAPE_READ error %u\n", GetLastError() );
469 UnmapViewOfFile( ptr
);
471 /* this fails on win9x but succeeds on NT */
472 SetLastError(0xdeadbeef);
473 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
474 if (ptr
) UnmapViewOfFile( ptr
);
475 else ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
477 SetLastError(0xdeadbeef);
478 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
479 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
480 UnmapViewOfFile( ptr
);
482 SetLastError(0xdeadbeef);
483 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
484 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
485 UnmapViewOfFile( ptr
);
487 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
488 FILE_MAP_READ
|FILE_MAP_WRITE
, FALSE
, 0 );
489 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
490 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
491 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
492 UnmapViewOfFile( ptr
);
495 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
496 FILE_MAP_READ
, FALSE
, 0 );
497 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
498 SetLastError(0xdeadbeef);
499 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
502 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
504 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
, 0, FALSE
, 0 );
505 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
506 SetLastError(0xdeadbeef);
507 ptr
= MapViewOfFile( map2
, 0, 0, 0, 4096 );
508 ok( !ptr
, "MapViewOfFile succeeded\n" );
509 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
511 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
512 FILE_MAP_READ
, FALSE
, 0 );
513 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
514 ptr
= MapViewOfFile( map2
, 0, 0, 0, 4096 );
515 ok( ptr
!= NULL
, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
517 else win_skip( "no access checks on win9x\n" );
519 UnmapViewOfFile( ptr
);
521 CloseHandle( mapping
);
523 /* read-only mapping */
525 SetLastError(0xdeadbeef);
526 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
527 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
529 SetLastError(0xdeadbeef);
530 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
531 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
532 UnmapViewOfFile( ptr
);
534 /* this fails on win9x but succeeds on NT */
535 SetLastError(0xdeadbeef);
536 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
537 if (ptr
) UnmapViewOfFile( ptr
);
538 else ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
540 SetLastError(0xdeadbeef);
541 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
542 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
543 UnmapViewOfFile( ptr
);
545 SetLastError(0xdeadbeef);
546 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
547 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
548 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
549 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
550 CloseHandle( mapping
);
552 /* copy-on-write mapping */
554 SetLastError(0xdeadbeef);
555 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
556 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
558 SetLastError(0xdeadbeef);
559 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
560 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
561 UnmapViewOfFile( ptr
);
563 SetLastError(0xdeadbeef);
564 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
565 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
566 UnmapViewOfFile( ptr
);
568 SetLastError(0xdeadbeef);
569 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
570 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
571 UnmapViewOfFile( ptr
);
573 SetLastError(0xdeadbeef);
574 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
575 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
576 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
577 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
578 CloseHandle( mapping
);
580 /* no access mapping */
582 SetLastError(0xdeadbeef);
583 mapping
= CreateFileMappingA( file
, NULL
, PAGE_NOACCESS
, 0, 4096, NULL
);
584 /* fails on NT but succeeds on win9x */
585 if (!mapping
) ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
588 SetLastError(0xdeadbeef);
589 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
590 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
591 UnmapViewOfFile( ptr
);
593 SetLastError(0xdeadbeef);
594 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
595 ok( !ptr
, "MapViewOfFile FILE_MAP_COPY succeeded\n" );
596 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
598 SetLastError(0xdeadbeef);
599 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
600 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
601 UnmapViewOfFile( ptr
);
603 SetLastError(0xdeadbeef);
604 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
605 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
606 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
608 CloseHandle( mapping
);
613 /* now try read-only file */
615 SetLastError(0xdeadbeef);
616 file
= CreateFileA( testfile
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0 );
617 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
619 SetLastError(0xdeadbeef);
620 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
621 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
622 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
623 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
625 SetLastError(0xdeadbeef);
626 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
627 ok( mapping
!= 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
628 CloseHandle( mapping
);
630 SetLastError(0xdeadbeef);
631 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
632 ok( mapping
!= 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
633 CloseHandle( mapping
);
636 /* now try no access file */
638 SetLastError(0xdeadbeef);
639 file
= CreateFileA( testfile
, 0, 0, NULL
, OPEN_EXISTING
, 0, 0 );
640 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
642 SetLastError(0xdeadbeef);
643 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
644 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
645 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
646 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
648 SetLastError(0xdeadbeef);
649 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
650 ok( !mapping
, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
651 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
652 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
654 SetLastError(0xdeadbeef);
655 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
656 ok( !mapping
, "CreateFileMapping PAGE_READONLY succeeded\n" );
657 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
658 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
661 DeleteFileA( testfile
);
663 SetLastError(0xdeadbeef);
665 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, name
);
666 /* nt4 doesn't have Local\\ */
667 if (!file
&& GetLastError() == ERROR_PATH_NOT_FOUND
)
670 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, name
);
672 ok( file
!= 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
674 SetLastError(0xdeadbeef);
675 mapping
= OpenFileMappingA( FILE_MAP_READ
, FALSE
, name
);
676 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
677 SetLastError(0xdeadbeef);
678 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
682 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
683 SetLastError(0xdeadbeef);
684 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
685 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
686 SetLastError(0xdeadbeef);
687 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
688 ok( size
== sizeof(info
),
689 "VirtualQuery error %u\n", GetLastError() );
690 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
691 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
692 ok( info
.AllocationProtect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.AllocationProtect
);
693 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
694 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
695 ok( info
.Protect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.Protect
);
697 else win_skip( "no access checks on win9x\n" );
698 UnmapViewOfFile( ptr
);
699 CloseHandle( mapping
);
701 SetLastError(0xdeadbeef);
702 mapping
= OpenFileMappingA( FILE_MAP_WRITE
, FALSE
, name
);
703 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
704 SetLastError(0xdeadbeef);
705 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
709 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
710 SetLastError(0xdeadbeef);
711 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
712 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
713 SetLastError(0xdeadbeef);
714 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
715 ok( size
== sizeof(info
),
716 "VirtualQuery error %u\n", GetLastError() );
717 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
718 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
719 ok( info
.AllocationProtect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.AllocationProtect
);
720 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
721 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
722 ok( info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
724 else win_skip( "no access checks on win9x\n" );
725 UnmapViewOfFile( ptr
);
726 CloseHandle( mapping
);
730 /* read/write mapping with SEC_RESERVE */
731 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
| SEC_RESERVE
, 0, MAPPING_SIZE
, NULL
);
732 ok(mapping
!= INVALID_HANDLE_VALUE
, "CreateFileMappingA failed with error %d\n", GetLastError());
734 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
735 ok(ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
737 ptr2
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
738 /* on NT ptr != ptr2 but on Win9x ptr == ptr2 */
739 ok(ptr2
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
740 trace("mapping same section resulted in views %p and %p\n", ptr
, ptr2
);
742 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
743 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
744 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
745 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
746 ok(info
.RegionSize
== MAPPING_SIZE
, "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
747 ok(info
.State
== MEM_RESERVE
, "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
748 if (info
.Type
== MEM_PRIVATE
) /* win9x is different for uncommitted mappings */
750 ok(info
.AllocationProtect
== PAGE_NOACCESS
,
751 "AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info
.AllocationProtect
);
752 ok(info
.Protect
== PAGE_NOACCESS
,
753 "Protect should have been PAGE_NOACCESS instead of 0x%x\n", info
.Protect
);
757 ok(info
.AllocationProtect
== PAGE_READWRITE
,
758 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
759 ok(info
.Protect
== 0, "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
760 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
765 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
766 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
767 ok(info
.BaseAddress
== ptr2
,
768 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
769 ok(info
.AllocationBase
== ptr2
,
770 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
771 ok(info
.AllocationProtect
== PAGE_READWRITE
,
772 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
773 ok(info
.RegionSize
== MAPPING_SIZE
,
774 "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
775 ok(info
.State
== MEM_RESERVE
,
776 "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
777 ok(info
.Protect
== 0,
778 "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
779 ok(info
.Type
== MEM_MAPPED
,
780 "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
783 ptr
= VirtualAlloc(ptr
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
784 ok(ptr
!= NULL
, "VirtualAlloc failed with error %d\n", GetLastError());
786 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
787 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
788 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
789 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
790 ok(info
.RegionSize
== 0x10000, "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
791 ok(info
.State
== MEM_COMMIT
, "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
792 ok(info
.Protect
== PAGE_READONLY
, "Protect should have been PAGE_READONLY instead of 0x%x\n", info
.Protect
);
793 if (info
.Type
== MEM_PRIVATE
) /* win9x is different for uncommitted mappings */
795 ok(info
.AllocationProtect
== PAGE_NOACCESS
,
796 "AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info
.AllocationProtect
);
800 ok(info
.AllocationProtect
== PAGE_READWRITE
,
801 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
802 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
805 /* shows that the VirtualAlloc above affects the mapping, not just the
806 * virtual memory in this process - it also affects all other processes
807 * with a view of the mapping, but that isn't tested here */
810 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
811 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
812 ok(info
.BaseAddress
== ptr2
,
813 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
814 ok(info
.AllocationBase
== ptr2
,
815 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
816 ok(info
.AllocationProtect
== PAGE_READWRITE
,
817 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
818 ok(info
.RegionSize
== 0x10000,
819 "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
820 ok(info
.State
== MEM_COMMIT
,
821 "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
822 ok(info
.Protect
== PAGE_READWRITE
,
823 "Protect should have been PAGE_READWRITE instead of 0x%x\n", info
.Protect
);
824 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
827 addr
= VirtualAlloc( ptr
, MAPPING_SIZE
, MEM_RESET
, PAGE_READONLY
);
828 ok( addr
== ptr
|| broken(!addr
&& GetLastError() == ERROR_INVALID_PARAMETER
), /* win9x */
829 "VirtualAlloc failed with error %u\n", GetLastError() );
831 ret
= VirtualFree( ptr
, 0x10000, MEM_DECOMMIT
);
832 ok( !ret
|| broken(ret
) /* win9x */, "VirtualFree succeeded\n" );
834 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "VirtualFree failed with %u\n", GetLastError() );
836 ret
= UnmapViewOfFile(ptr2
);
837 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
838 ret
= UnmapViewOfFile(ptr
);
839 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
840 CloseHandle(mapping
);
842 addr
= VirtualAlloc(NULL
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
843 ok( addr
!= NULL
, "VirtualAlloc failed with error %u\n", GetLastError() );
845 SetLastError(0xdeadbeef);
846 ok( !UnmapViewOfFile(addr
), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
847 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
848 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
849 SetLastError(0xdeadbeef);
850 ok( !UnmapViewOfFile((char *)addr
+ 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
851 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
852 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
853 SetLastError(0xdeadbeef);
854 ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
855 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
856 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
858 ok( VirtualFree(addr
, 0, MEM_RELEASE
), "VirtualFree failed\n" );
860 /* close named mapping handle without unmapping */
862 SetLastError(0xdeadbeef);
863 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
864 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
865 SetLastError(0xdeadbeef);
866 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
867 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
868 SetLastError(0xdeadbeef);
869 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
870 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
871 SetLastError(0xdeadbeef);
872 ret
= CloseHandle(map2
);
873 ok(ret
, "CloseHandle error %d\n", GetLastError());
874 SetLastError(0xdeadbeef);
875 ret
= CloseHandle(mapping
);
876 ok(ret
, "CloseHandle error %d\n", GetLastError());
878 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
879 ok( !ret
, "memory is not accessible\n" );
881 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
882 ok(ret
, "VirtualQuery error %d\n", GetLastError());
883 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
884 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
885 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
886 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
887 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
888 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
889 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
891 SetLastError(0xdeadbeef);
892 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
894 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
896 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
897 if (map2
) CloseHandle(map2
); /* FIXME: remove once Wine is fixed */
898 SetLastError(0xdeadbeef);
899 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
900 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
902 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set error %d\n", GetLastError() );
903 SetLastError(0xdeadbeef);
904 ret
= CloseHandle(mapping
);
905 ok(ret
, "CloseHandle error %d\n", GetLastError());
907 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
908 ok( !ret
, "memory is not accessible\n" );
910 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
911 ok(ret
, "VirtualQuery error %d\n", GetLastError());
912 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
913 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
914 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
915 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
916 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
917 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
918 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
920 SetLastError(0xdeadbeef);
921 ret
= UnmapViewOfFile(ptr
);
922 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
924 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
925 ok( ret
, "memory is accessible\n" );
927 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
928 ok(ret
, "VirtualQuery error %d\n", GetLastError());
929 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
930 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
931 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
932 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
933 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
934 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
936 SetLastError(0xdeadbeef);
937 file
= CreateFileA(testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
938 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
939 SetFilePointer(file
, 4096, NULL
, FILE_BEGIN
);
942 SetLastError(0xdeadbeef);
943 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
944 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
945 SetLastError(0xdeadbeef);
946 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
947 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
948 SetLastError(0xdeadbeef);
949 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
950 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
951 SetLastError(0xdeadbeef);
952 ret
= CloseHandle(map2
);
953 ok(ret
, "CloseHandle error %d\n", GetLastError());
954 SetLastError(0xdeadbeef);
955 ret
= CloseHandle(mapping
);
956 ok(ret
, "CloseHandle error %d\n", GetLastError());
958 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
959 ok( !ret
, "memory is not accessible\n" );
961 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
962 ok(ret
, "VirtualQuery error %d\n", GetLastError());
963 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
964 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
965 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
966 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
967 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
968 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
969 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
971 SetLastError(0xdeadbeef);
972 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
974 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
976 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
978 SetLastError(0xdeadbeef);
979 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
980 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
982 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set error %d\n", GetLastError() );
983 SetLastError(0xdeadbeef);
984 ret
= CloseHandle(mapping
);
985 ok(ret
, "CloseHandle error %d\n", GetLastError());
987 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
988 ok( !ret
, "memory is not accessible\n" );
990 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
991 ok(ret
, "VirtualQuery error %d\n", GetLastError());
992 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
993 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
994 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
995 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
996 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
997 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
998 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
1000 SetLastError(0xdeadbeef);
1001 ret
= UnmapViewOfFile(ptr
);
1002 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
1004 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
1005 ok( ret
, "memory is accessible\n" );
1007 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
1008 ok(ret
, "VirtualQuery error %d\n", GetLastError());
1009 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
1010 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
1011 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
1012 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
1013 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
1014 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
1017 DeleteFileA(testfile
);
1020 static void test_NtMapViewOfSection(void)
1024 static const char testfile
[] = "testfile.xxx";
1025 static const char data
[] = "test data for NtMapViewOfSection";
1026 char buffer
[sizeof(data
)];
1027 HANDLE file
, mapping
;
1030 DWORD status
, written
;
1031 SIZE_T size
, result
;
1032 LARGE_INTEGER offset
;
1034 if (!pNtMapViewOfSection
|| !pNtUnmapViewOfSection
)
1036 win_skip( "NtMapViewOfSection not available\n" );
1040 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1041 ok( file
!= INVALID_HANDLE_VALUE
, "Failed to create test file\n" );
1042 WriteFile( file
, data
, sizeof(data
), &written
, NULL
);
1043 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1044 SetEndOfFile( file
);
1046 /* read/write mapping */
1048 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1049 ok( mapping
!= 0, "CreateFileMapping failed\n" );
1051 hProcess
= create_target_process("sleep");
1052 ok(hProcess
!= NULL
, "Can't start process\n");
1056 offset
.QuadPart
= 0;
1057 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1058 ok( !status
, "NtMapViewOfSection failed status %x\n", status
);
1059 ok( !((ULONG_PTR
)ptr
& 0xffff), "returned memory %p is not aligned to 64k\n", ptr
);
1061 ret
= ReadProcessMemory( hProcess
, ptr
, buffer
, sizeof(buffer
), &result
);
1062 ok( ret
, "ReadProcessMemory failed\n" );
1063 ok( result
== sizeof(buffer
), "ReadProcessMemory didn't read all data (%lx)\n", result
);
1064 ok( !memcmp( buffer
, data
, sizeof(buffer
) ), "Wrong data read\n" );
1066 /* for some unknown reason NtMapViewOfSection fails with STATUS_NO_MEMORY when zero_bits != 0 ? */
1069 offset
.QuadPart
= 0;
1070 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1072 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1073 if (status
== STATUS_SUCCESS
)
1075 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1076 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1081 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1083 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1084 if (status
== STATUS_SUCCESS
)
1086 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1087 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1090 /* mapping at the same page conflicts */
1093 offset
.QuadPart
= 0;
1094 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1095 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1097 /* offset has to be aligned */
1100 offset
.QuadPart
= 1;
1101 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1102 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1104 /* ptr has to be aligned */
1105 ptr2
= (char *)ptr
+ 42;
1107 offset
.QuadPart
= 0;
1108 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1109 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1111 /* still not 64k aligned */
1112 ptr2
= (char *)ptr
+ 0x1000;
1114 offset
.QuadPart
= 0;
1115 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1116 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1118 /* zero_bits != 0 is not allowed when an address is set */
1119 ptr2
= (char *)ptr
+ 0x1000;
1121 offset
.QuadPart
= 0;
1122 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1123 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1125 ptr2
= (char *)ptr
+ 0x1000;
1127 offset
.QuadPart
= 0;
1128 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1129 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1131 ptr2
= (char *)ptr
+ 0x1001;
1133 offset
.QuadPart
= 0;
1134 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1135 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1137 ptr2
= (char *)ptr
+ 0x1000;
1139 offset
.QuadPart
= 1;
1140 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1141 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1143 if (sizeof(void *) == sizeof(int) && (!pIsWow64Process
||
1144 !pIsWow64Process( GetCurrentProcess(), &is_wow64
) || !is_wow64
))
1146 /* new memory region conflicts with previous mapping */
1149 offset
.QuadPart
= 0;
1150 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1151 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1152 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1154 ptr2
= (char *)ptr
+ 42;
1156 offset
.QuadPart
= 0;
1157 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1158 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1159 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1161 /* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
1162 ptr2
= (char *)ptr
+ 0x1000;
1164 offset
.QuadPart
= 0;
1165 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1166 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1167 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1168 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1169 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1170 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1171 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1173 /* the address is rounded down if not on a page boundary */
1174 ptr2
= (char *)ptr
+ 0x1001;
1176 offset
.QuadPart
= 0;
1177 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1178 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1179 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1180 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1181 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1182 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1183 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1185 ptr2
= (char *)ptr
+ 0x2000;
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_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1191 ok( (char *)ptr2
== (char *)ptr
+ 0x2000,
1192 "expected address %p, got %p\n", (char *)ptr
+ 0x2000, ptr2
);
1193 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1194 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1198 ptr2
= (char *)ptr
+ 0x1000;
1200 offset
.QuadPart
= 0;
1201 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1202 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1204 ok( status
== STATUS_INVALID_PARAMETER_9
, "NtMapViewOfSection returned %x\n", status
);
1207 status
= pNtUnmapViewOfSection( hProcess
, ptr
);
1208 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1210 CloseHandle( mapping
);
1211 CloseHandle( file
);
1212 DeleteFileA( testfile
);
1214 TerminateProcess(hProcess
, 0);
1215 CloseHandle(hProcess
);
1218 static void test_NtAreMappedFilesTheSame(void)
1220 static const char testfile
[] = "testfile.xxx";
1221 HANDLE file
, file2
, mapping
, map2
;
1224 char path
[MAX_PATH
];
1226 if (!pNtAreMappedFilesTheSame
)
1228 win_skip( "NtAreMappedFilesTheSame not available\n" );
1232 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1233 NULL
, CREATE_ALWAYS
, 0, 0 );
1234 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1235 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1236 SetEndOfFile( file
);
1238 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1239 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1241 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1242 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1244 file2
= CreateFileA( testfile
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1245 NULL
, OPEN_EXISTING
, 0, 0 );
1246 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1248 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1249 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1250 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1251 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1252 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1253 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1254 UnmapViewOfFile( ptr2
);
1256 ptr2
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1257 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1258 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1259 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1260 UnmapViewOfFile( ptr2
);
1261 CloseHandle( map2
);
1263 map2
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1264 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1265 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1266 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1267 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1268 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1269 UnmapViewOfFile( ptr2
);
1270 CloseHandle( map2
);
1271 CloseHandle( file2
);
1273 status
= pNtAreMappedFilesTheSame( ptr
, ptr
);
1274 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1275 "NtAreMappedFilesTheSame returned %x\n", status
);
1277 status
= pNtAreMappedFilesTheSame( ptr
, (char *)ptr
+ 30 );
1278 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1279 "NtAreMappedFilesTheSame returned %x\n", status
);
1281 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1282 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1284 status
= pNtAreMappedFilesTheSame( ptr
, (void *)0xdeadbeef );
1285 ok( status
== STATUS_CONFLICTING_ADDRESSES
|| status
== STATUS_INVALID_ADDRESS
,
1286 "NtAreMappedFilesTheSame returned %x\n", status
);
1288 status
= pNtAreMappedFilesTheSame( ptr
, NULL
);
1289 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1291 status
= pNtAreMappedFilesTheSame( ptr
, (void *)GetProcessHeap() );
1292 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1294 status
= pNtAreMappedFilesTheSame( NULL
, NULL
);
1295 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1297 ptr2
= VirtualAlloc( NULL
, 0x10000, MEM_COMMIT
, PAGE_READWRITE
);
1298 ok( ptr2
!= NULL
, "VirtualAlloc error %u\n", GetLastError() );
1299 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1300 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1301 VirtualFree( ptr2
, 0, MEM_RELEASE
);
1303 UnmapViewOfFile( ptr
);
1304 CloseHandle( mapping
);
1305 CloseHandle( file
);
1307 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
1308 GetModuleHandleA("kernel32.dll") );
1309 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1310 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1311 GetModuleHandleA("kernel32.dll") );
1312 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1313 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1314 (char *)GetModuleHandleA("kernel32.dll") + 4096 );
1315 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1317 GetSystemDirectoryA( path
, MAX_PATH
);
1318 strcat( path
, "\\kernel32.dll" );
1319 file
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1320 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1322 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1323 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1324 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1325 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1326 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1327 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1328 UnmapViewOfFile( ptr
);
1329 CloseHandle( mapping
);
1331 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1332 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1333 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
1334 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1335 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1337 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1339 file2
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1340 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1341 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1342 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1343 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 0 );
1344 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1345 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1346 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1347 UnmapViewOfFile( ptr2
);
1348 CloseHandle( map2
);
1349 CloseHandle( file2
);
1351 UnmapViewOfFile( ptr
);
1352 CloseHandle( mapping
);
1354 CloseHandle( file
);
1355 DeleteFileA( testfile
);
1358 static void test_CreateFileMapping(void)
1360 HANDLE handle
, handle2
;
1362 /* test case sensitivity */
1364 SetLastError(0xdeadbeef);
1365 handle
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1366 "Wine Test Mapping");
1367 ok( handle
!= NULL
, "CreateFileMapping failed with error %u\n", GetLastError());
1368 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1370 SetLastError(0xdeadbeef);
1371 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1372 "Wine Test Mapping");
1373 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1374 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
1375 CloseHandle( handle2
);
1377 SetLastError(0xdeadbeef);
1378 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1379 "WINE TEST MAPPING");
1380 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1381 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1382 CloseHandle( handle2
);
1384 SetLastError(0xdeadbeef);
1385 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "Wine Test Mapping");
1386 ok( handle2
!= NULL
, "OpenFileMapping failed with error %d\n", GetLastError());
1387 CloseHandle( handle2
);
1389 SetLastError(0xdeadbeef);
1390 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "WINE TEST MAPPING");
1391 ok( !handle2
, "OpenFileMapping succeeded\n");
1392 ok( GetLastError() == ERROR_FILE_NOT_FOUND
|| GetLastError() == ERROR_INVALID_NAME
/* win9x */,
1393 "wrong error %u\n", GetLastError());
1395 CloseHandle( handle
);
1398 static void test_IsBadReadPtr(void)
1401 void *ptr
= (void *)0xdeadbeef;
1404 ret
= IsBadReadPtr(NULL
, 0);
1405 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1407 ret
= IsBadReadPtr(NULL
, 1);
1408 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1410 ret
= IsBadReadPtr(ptr
, 0);
1411 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1413 ret
= IsBadReadPtr(ptr
, 1);
1414 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1416 ret
= IsBadReadPtr(&stackvar
, 0);
1417 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1419 ret
= IsBadReadPtr(&stackvar
, sizeof(char));
1420 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1423 static void test_IsBadWritePtr(void)
1426 void *ptr
= (void *)0xdeadbeef;
1429 ret
= IsBadWritePtr(NULL
, 0);
1430 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1432 ret
= IsBadWritePtr(NULL
, 1);
1433 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1435 ret
= IsBadWritePtr(ptr
, 0);
1436 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1438 ret
= IsBadWritePtr(ptr
, 1);
1439 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1441 ret
= IsBadWritePtr(&stackval
, 0);
1442 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1444 ret
= IsBadWritePtr(&stackval
, sizeof(char));
1445 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1448 static void test_IsBadCodePtr(void)
1451 void *ptr
= (void *)0xdeadbeef;
1454 ret
= IsBadCodePtr(NULL
);
1455 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1457 ret
= IsBadCodePtr(ptr
);
1458 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1460 ret
= IsBadCodePtr((void *)&stackval
);
1461 ok(ret
== FALSE
, "Expected IsBadCodePtr to return FALSE, got %d\n", ret
);
1464 static void test_write_watch(void)
1466 static const char pipename
[] = "\\\\.\\pipe\\test_write_watch_pipe";
1467 static const char testdata
[] = "Hello World";
1468 DWORD ret
, size
, old_prot
, num_bytes
;
1469 MEMORY_BASIC_INFORMATION info
;
1470 HANDLE readpipe
, writepipe
;
1471 OVERLAPPED overlapped
;
1478 if (!pGetWriteWatch
|| !pResetWriteWatch
)
1480 win_skip( "GetWriteWatch not supported\n" );
1485 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1487 (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
1489 win_skip( "MEM_WRITE_WATCH not supported\n" );
1492 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1493 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1494 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1495 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1496 ok( info
.AllocationProtect
== PAGE_READWRITE
, "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1497 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1498 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1499 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1500 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1503 SetLastError( 0xdeadbeef );
1504 ret
= pGetWriteWatch( 0, NULL
, size
, results
, &count
, &pagesize
);
1505 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1506 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
1507 broken( GetLastError() == 0xdeadbeef ), /* win98 */
1508 "wrong error %u\n", GetLastError() );
1510 SetLastError( 0xdeadbeef );
1511 ret
= pGetWriteWatch( 0, GetModuleHandleW(NULL
), size
, results
, &count
, &pagesize
);
1514 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1515 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1519 ok( count
== 0, "wrong count %lu\n", count
);
1522 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1523 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1524 ok( count
== 0, "wrong count %lu\n", count
);
1526 base
[pagesize
+ 1] = 0x44;
1529 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1530 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1531 ok( count
== 1, "wrong count %lu\n", count
);
1532 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1535 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1536 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1537 ok( count
== 1, "wrong count %lu\n", count
);
1538 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1541 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1542 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1543 ok( count
== 0, "wrong count %lu\n", count
);
1545 base
[2*pagesize
+ 3] = 0x11;
1546 base
[4*pagesize
+ 8] = 0x11;
1549 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1550 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1551 ok( count
== 2, "wrong count %lu\n", count
);
1552 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1553 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1556 ret
= pGetWriteWatch( 0, base
+ 3*pagesize
, 2*pagesize
, results
, &count
, &pagesize
);
1557 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1558 ok( count
== 1, "wrong count %lu\n", count
);
1559 ok( results
[0] == base
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1561 ret
= pResetWriteWatch( base
, 3*pagesize
);
1562 ok( !ret
, "pResetWriteWatch failed %u\n", GetLastError() );
1565 ret
= pGetWriteWatch( 0, 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
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1570 *(DWORD
*)(base
+ 2*pagesize
- 2) = 0xdeadbeef;
1573 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1574 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1575 ok( count
== 3, "wrong count %lu\n", count
);
1576 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1577 ok( results
[1] == base
+ 2*pagesize
, "wrong result %p\n", results
[1] );
1578 ok( results
[2] == base
+ 4*pagesize
, "wrong result %p\n", results
[2] );
1581 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1582 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1583 ok( count
== 1, "wrong count %lu\n", count
);
1584 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1587 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1588 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1589 ok( count
== 2, "wrong count %lu\n", count
);
1590 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1591 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1593 /* changing protections doesn't affect watches */
1595 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READONLY
, &old_prot
);
1596 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1597 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1599 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1600 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1601 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1602 ok( info
.RegionSize
== 3*pagesize
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1603 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1604 ok( info
.Protect
== PAGE_READONLY
, "wrong Protect 0x%x\n", info
.Protect
);
1606 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READWRITE
, &old_prot
);
1607 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1608 ok( old_prot
== PAGE_READONLY
, "wrong old prot %x\n", old_prot
);
1611 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1612 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1613 ok( count
== 2, "wrong count %lu\n", count
);
1614 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1615 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1617 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1618 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1619 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1620 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1621 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1622 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1624 /* ReadFile should trigger write watches */
1626 memset( &overlapped
, 0, sizeof(overlapped
) );
1627 overlapped
.hEvent
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1629 readpipe
= CreateNamedPipeA( pipename
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_INBOUND
,
1630 PIPE_TYPE_BYTE
| PIPE_WAIT
, 1, 1024, 1024,
1631 NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1632 ok( readpipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipeA failed %u\n", GetLastError() );
1634 success
= ConnectNamedPipe( readpipe
, &overlapped
);
1635 ok( !success
, "ConnectNamedPipe unexpectedly succeeded\n" );
1636 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1638 writepipe
= CreateFileA( pipename
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
1639 ok( writepipe
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %u\n", GetLastError() );
1641 ret
= WaitForSingleObject( overlapped
.hEvent
, 1000 );
1642 ok( ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", ret
);
1644 memset( base
, 0, size
);
1647 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1648 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1649 ok( count
== 16, "wrong count %lu\n", count
);
1651 success
= ReadFile( readpipe
, base
, size
, NULL
, &overlapped
);
1652 ok( !success
, "ReadFile unexpectedly succeeded\n" );
1653 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1656 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1657 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1658 ok( count
== 16, "wrong count %lu\n", count
);
1661 success
= WriteFile( writepipe
, testdata
, sizeof(testdata
), &num_bytes
, NULL
);
1662 ok( success
, "WriteFile failed %u\n", GetLastError() );
1663 ok( num_bytes
== sizeof(testdata
), "wrong number of bytes written\n" );
1666 success
= GetOverlappedResult( readpipe
, &overlapped
, &num_bytes
, TRUE
);
1667 ok( success
, "GetOverlappedResult failed %u\n", GetLastError() );
1668 ok( num_bytes
== sizeof(testdata
), "wrong number of bytes read\n" );
1669 ok( !memcmp( base
, testdata
, sizeof(testdata
)), "didn't receive expected data\n" );
1672 memset( results
, 0, sizeof(results
) );
1673 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1674 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1675 todo_wine
ok( count
== 1, "wrong count %lu\n", count
);
1676 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
1678 CloseHandle( readpipe
);
1679 CloseHandle( writepipe
);
1680 CloseHandle( overlapped
.hEvent
);
1682 /* some invalid parameter tests */
1684 SetLastError( 0xdeadbeef );
1686 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1689 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1690 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1692 SetLastError( 0xdeadbeef );
1693 ret
= pGetWriteWatch( 0, base
, size
, results
, NULL
, &pagesize
);
1694 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1695 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1697 SetLastError( 0xdeadbeef );
1699 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, NULL
);
1700 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1701 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1703 SetLastError( 0xdeadbeef );
1705 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1706 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1707 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1709 SetLastError( 0xdeadbeef );
1711 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1712 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1713 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1715 SetLastError( 0xdeadbeef );
1717 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1718 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1719 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1721 SetLastError( 0xdeadbeef );
1723 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1724 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1725 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1727 SetLastError( 0xdeadbeef );
1729 ret
= pGetWriteWatch( 0, base
, size
* 2, results
, &count
, &pagesize
);
1730 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1731 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1733 SetLastError( 0xdeadbeef );
1735 ret
= pGetWriteWatch( 0, base
+ size
- pagesize
, pagesize
+ 1, results
, &count
, &pagesize
);
1736 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1737 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1739 SetLastError( 0xdeadbeef );
1740 ret
= pResetWriteWatch( base
, 0 );
1741 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1742 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1744 SetLastError( 0xdeadbeef );
1745 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1746 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1747 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1749 else /* win98 is completely different */
1751 SetLastError( 0xdeadbeef );
1753 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1754 ok( ret
== ERROR_INVALID_PARAMETER
, "GetWriteWatch succeeded %u\n", ret
);
1755 ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
1758 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1759 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1762 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1763 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1766 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1767 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1769 ret
= pResetWriteWatch( base
, 0 );
1770 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1772 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1773 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1776 VirtualFree( base
, 0, MEM_RELEASE
);
1778 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1779 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1780 VirtualFree( base
, 0, MEM_RELEASE
);
1782 base
= VirtualAlloc( 0, size
, MEM_WRITE_WATCH
, PAGE_READWRITE
);
1783 ok( !base
, "VirtualAlloc succeeded\n" );
1784 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1786 /* initial protect doesn't matter */
1788 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_NOACCESS
);
1789 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1790 base
= VirtualAlloc( base
, size
, MEM_COMMIT
, PAGE_NOACCESS
);
1791 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1794 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1795 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1796 ok( count
== 0, "wrong count %lu\n", count
);
1798 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_READWRITE
, &old_prot
);
1799 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1800 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
1802 base
[5*pagesize
+ 200] = 3;
1804 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_NOACCESS
, &old_prot
);
1805 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1806 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1809 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1810 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1811 ok( count
== 1, "wrong count %lu\n", count
);
1812 ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1814 ret
= VirtualFree( base
, size
, MEM_DECOMMIT
);
1815 ok( ret
, "VirtualFree failed %u\n", GetLastError() );
1818 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1819 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1820 ok( count
== 1 || broken(count
== 0), /* win98 */
1821 "wrong count %lu\n", count
);
1822 if (count
) ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1824 VirtualFree( base
, 0, MEM_RELEASE
);
1829 static DWORD num_guard_page_calls
;
1831 static DWORD
guard_page_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
1832 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
1834 trace( "exception: %08x flags:%x addr:%p\n",
1835 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
);
1837 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
1838 ok( rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
, "ExceptionCode is %08x instead of %08x\n",
1839 rec
->ExceptionCode
, STATUS_GUARD_PAGE_VIOLATION
);
1841 num_guard_page_calls
++;
1842 *(int *)rec
->ExceptionInformation
[1] += 0x100;
1844 return ExceptionContinueExecution
;
1847 static void test_guard_page(void)
1849 EXCEPTION_REGISTRATION_RECORD frame
;
1850 MEMORY_BASIC_INFORMATION info
;
1851 DWORD ret
, size
, old_prot
;
1852 int *value
, old_value
;
1861 win_skip( "NtCurrentTeb not supported\n" );
1866 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
1867 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1868 value
= (int *)base
;
1870 /* verify info structure */
1871 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1872 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
1873 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1874 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1875 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1876 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1877 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
1878 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1880 /* put some initial value into the memory */
1881 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
1882 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1883 ok( old_prot
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong old prot %x\n", old_prot
);
1888 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
1889 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1890 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1892 /* test behaviour of VirtualLock - first attempt should fail */
1893 SetLastError( 0xdeadbeef );
1894 success
= VirtualLock( base
, size
);
1895 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
1897 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
1899 success
= VirtualLock( base
, size
);
1901 ok( success
, "VirtualLock failed %u\n", GetLastError() );
1904 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
1905 success
= VirtualUnlock( base
, size
);
1906 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
1909 /* check info structure again, PAGE_GUARD should be removed now */
1910 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1911 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
1912 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1913 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1914 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1915 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1917 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1918 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1920 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
1921 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1923 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1925 /* test directly accessing the memory - we need to setup an exception handler first */
1926 frame
.Handler
= guard_page_handler
;
1927 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
1928 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
1930 num_guard_page_calls
= 0;
1931 old_value
= *value
; /* exception handler increments value by 0x100 */
1933 ok( old_value
== 0x101, "memory block contains wrong value, expected 0x101, got 0x%x\n", old_value
);
1934 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
1936 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
1938 /* check info structure again, PAGE_GUARD should be removed now */
1939 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1940 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
1941 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1943 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
1944 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
1945 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1947 /* test accessing second integer in memory */
1948 frame
.Handler
= guard_page_handler
;
1949 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
1950 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
1952 num_guard_page_calls
= 0;
1953 old_value
= *(value
+ 1);
1954 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
1955 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
1956 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
1958 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
1960 success
= VirtualLock( base
, size
);
1961 ok( success
, "VirtualLock failed %u\n", GetLastError() );
1964 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
1965 success
= VirtualUnlock( base
, size
);
1966 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
1969 VirtualFree( base
, 0, MEM_RELEASE
);
1971 /* combined guard page / write watch tests */
1972 if (!pGetWriteWatch
|| !pResetWriteWatch
)
1974 win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" );
1978 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
| PAGE_GUARD
);
1979 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
1981 win_skip( "MEM_WRITE_WATCH not supported\n" );
1984 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1985 value
= (int *)base
;
1987 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1988 ok( ret
, "VirtualQuery failed %u\n", GetLastError() );
1989 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1990 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1991 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1992 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1993 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
1994 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1997 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1998 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1999 ok( count
== 0, "wrong count %lu\n", count
);
2001 /* writing to a page should trigger should trigger guard page, even if write watch is set */
2002 frame
.Handler
= guard_page_handler
;
2003 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
2004 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2006 num_guard_page_calls
= 0;
2009 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2011 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2014 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2015 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2016 ok( count
== 1, "wrong count %lu\n", count
);
2017 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2019 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2020 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2022 /* write watch is triggered from inside of the guard page handler */
2023 frame
.Handler
= guard_page_handler
;
2024 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
2025 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2027 num_guard_page_calls
= 0;
2028 old_value
= *(value
+ 1); /* doesn't trigger write watch */
2029 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
2030 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2031 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2033 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2036 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2037 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2038 ok( count
== 1, "wrong count %lu\n", count
);
2039 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2041 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2042 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2044 /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */
2045 SetLastError( 0xdeadbeef );
2046 success
= VirtualLock( base
, size
);
2047 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
2049 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
2052 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
2053 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2054 ok( count
== 0, "wrong count %lu\n", count
);
2056 success
= VirtualLock( base
, size
);
2058 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2061 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2062 success
= VirtualUnlock( base
, size
);
2063 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2067 results
[0] = (void *)0xdeadbeef;
2068 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2069 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2071 ok( count
== 1 || broken(count
== 0) /* Windows 8 */, "wrong count %lu\n", count
);
2073 ok( results
[0] == base
|| broken(results
[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results
[0] );
2075 VirtualFree( base
, 0, MEM_RELEASE
);
2078 static DWORD WINAPI
stack_commit_func( void *arg
)
2080 volatile char *p
= (char *)&p
;
2082 /* trigger all guard pages, to ensure that the pages are committed */
2083 while (p
>= (char *)pNtCurrentTeb()->DeallocationStack
+ 3 * 0x1000)
2089 ok( arg
== (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg
);
2093 static void test_stack_commit(void)
2095 static const char code_call_on_stack
[] = {
2096 0x55, /* pushl %ebp */
2097 0x56, /* pushl %esi */
2098 0x89, 0xe6, /* movl %esp,%esi */
2099 0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */
2100 0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */
2101 0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */
2102 0x83, 0xe0, 0xf0, /* andl $~15,%eax */
2103 0x83, 0xe8, 0x0c, /* subl $12,%eax */
2104 0x89, 0xc4, /* movl %eax,%esp */
2105 0x52, /* pushl %edx */
2106 0x31, 0xed, /* xorl %ebp,%ebp */
2107 0xff, 0xd1, /* call *%ecx */
2108 0x89, 0xf4, /* movl %esi,%esp */
2109 0x5e, /* popl %esi */
2110 0x5d, /* popl %ebp */
2111 0xc2, 0x0c, 0x00 }; /* ret $12 */
2113 DWORD (WINAPI
*call_on_stack
)( DWORD (WINAPI
*func
)(void *), void *arg
, void *stack
);
2114 void *old_stack
, *old_stack_base
, *old_stack_limit
;
2115 void *new_stack
, *new_stack_base
;
2120 win_skip( "NtCurrentTeb not supported\n" );
2124 call_on_stack
= VirtualAlloc( 0, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
2125 ok( call_on_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2126 memcpy( call_on_stack
, code_call_on_stack
, sizeof(code_call_on_stack
) );
2128 /* allocate a new stack, only the first guard page is committed */
2129 new_stack
= VirtualAlloc( 0, 0x400000, MEM_RESERVE
, PAGE_READWRITE
);
2130 ok( new_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2131 new_stack_base
= (char *)new_stack
+ 0x400000;
2132 VirtualAlloc( (char *)new_stack_base
- 0x1000, 0x1000, MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
2134 old_stack
= pNtCurrentTeb()->DeallocationStack
;
2135 old_stack_base
= pNtCurrentTeb()->Tib
.StackBase
;
2136 old_stack_limit
= pNtCurrentTeb()->Tib
.StackLimit
;
2138 pNtCurrentTeb()->DeallocationStack
= new_stack
;
2139 pNtCurrentTeb()->Tib
.StackBase
= new_stack_base
;
2140 pNtCurrentTeb()->Tib
.StackLimit
= new_stack_base
;
2142 result
= call_on_stack( stack_commit_func
, (void *)0xdeadbeef, new_stack_base
);
2143 ok( result
== 42, "expected 42, got %u\n", result
);
2145 pNtCurrentTeb()->DeallocationStack
= old_stack
;
2146 pNtCurrentTeb()->Tib
.StackBase
= old_stack_base
;
2147 pNtCurrentTeb()->Tib
.StackLimit
= old_stack_limit
;
2149 VirtualFree( new_stack
, 0, MEM_RELEASE
);
2150 VirtualFree( call_on_stack
, 0, MEM_RELEASE
);
2153 DWORD num_execute_fault_calls
;
2155 static DWORD
execute_fault_seh_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
2156 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
2158 ULONG flags
= MEM_EXECUTE_OPTION_ENABLE
;
2161 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2162 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2163 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2165 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2166 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
|| rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
,
2167 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec
->ExceptionCode
);
2169 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &flags
, sizeof(flags
), NULL
);
2171 if (rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
)
2174 err
= IsProcessorFeaturePresent( PF_NX_ENABLED
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2175 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2176 (DWORD
)rec
->ExceptionInformation
[0], err
);
2178 num_guard_page_calls
++;
2180 else if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2185 err
= (flags
& MEM_EXECUTE_OPTION_DISABLE
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2186 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2187 (DWORD
)rec
->ExceptionInformation
[0], err
);
2189 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2190 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2191 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2193 num_execute_fault_calls
++;
2196 return ExceptionContinueExecution
;
2199 static LONG CALLBACK
execute_fault_vec_handler( EXCEPTION_POINTERS
*ExceptionInfo
)
2201 PEXCEPTION_RECORD rec
= ExceptionInfo
->ExceptionRecord
;
2205 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2206 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2207 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2209 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2210 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
,
2211 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec
->ExceptionCode
);
2213 if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2214 num_execute_fault_calls
++;
2216 if (rec
->ExceptionInformation
[0] == EXCEPTION_READ_FAULT
)
2217 return EXCEPTION_CONTINUE_SEARCH
;
2219 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2220 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2221 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
2223 return EXCEPTION_CONTINUE_EXECUTION
;
2226 static inline DWORD
send_message_excpt( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2228 EXCEPTION_REGISTRATION_RECORD frame
;
2231 frame
.Handler
= execute_fault_seh_handler
;
2232 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
2233 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2235 num_guard_page_calls
= num_execute_fault_calls
= 0;
2236 ret
= SendMessageA( hWnd
, uMsg
, wParam
, lParam
);
2238 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2243 static inline DWORD
call_proc_excpt( DWORD (CALLBACK
*code
)(void *), void *arg
)
2245 EXCEPTION_REGISTRATION_RECORD frame
;
2248 frame
.Handler
= execute_fault_seh_handler
;
2249 frame
.Prev
= pNtCurrentTeb()->Tib
.ExceptionList
;
2250 pNtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2252 num_guard_page_calls
= num_execute_fault_calls
= 0;
2255 pNtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2260 static LRESULT CALLBACK
jmp_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2262 if (uMsg
== WM_USER
)
2265 return DefWindowProcA( hWnd
, uMsg
, wParam
, lParam
);
2268 static LRESULT CALLBACK
atl_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2270 DWORD arg
= (DWORD
)hWnd
;
2271 if (uMsg
== WM_USER
)
2272 ok( arg
== 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg
);
2274 ok( arg
!= 0x11223344, "arg is unexpectedly 0x11223344\n" );
2278 static DWORD CALLBACK
atl5_test_func( void )
2283 static void test_atl_thunk_emulation( ULONG dep_flags
)
2285 static const char code_jmp
[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
2286 static const char code_atl1
[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2287 static const char code_atl2
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2288 static const char code_atl3
[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1};
2289 static const char code_atl4
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
2290 static const char code_atl5
[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04};
2291 static const char cls_name
[] = "atl_thunk_class";
2292 DWORD ret
, size
, old_prot
;
2293 ULONG old_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2294 BOOL success
, restore_flags
= FALSE
;
2304 win_skip( "NtCurrentTeb not supported\n" );
2308 trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2310 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
), NULL
);
2311 if (old_flags
!= dep_flags
)
2313 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &dep_flags
, sizeof(dep_flags
) );
2314 if (ret
== STATUS_INVALID_INFO_CLASS
) /* Windows 2000 */
2316 win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2319 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2320 restore_flags
= TRUE
;
2324 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
2325 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2327 /* Check result of GetProcessDEPPolicy */
2328 if (!pGetProcessDEPPolicy
)
2329 win_skip( "GetProcessDEPPolicy not supported\n" );
2332 BOOL (WINAPI
*get_dep_policy
)(HANDLE
, LPDWORD
, PBOOL
) = (void *)base
;
2333 BOOL policy_permanent
= 0xdeadbeef;
2334 DWORD policy_flags
= 0xdeadbeef;
2336 /* GetProcessDEPPolicy crashes on Windows when a NULL pointer is passed.
2337 * Moreover this function has a bug on Windows 8, which has the effect that
2338 * policy_permanent is set to the content of the CL register instead of 0,
2339 * when the policy is not permanent. To detect that we use an assembler
2340 * wrapper to call the function. */
2342 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2343 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)pGetProcessDEPPolicy
- (DWORD_PTR
)(base
+ 10);
2345 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2346 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2348 success
= get_dep_policy( GetCurrentProcess(), &policy_flags
, &policy_permanent
);
2349 ok( success
, "GetProcessDEPPolicy failed %u\n", GetLastError() );
2352 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2353 ret
|= PROCESS_DEP_ENABLE
;
2354 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
)
2355 ret
|= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
;
2357 ok( policy_flags
== ret
, "expected policy flags %d, got %d\n", ret
, policy_flags
);
2358 ok( !policy_permanent
|| broken(policy_permanent
== 0x44),
2359 "expected policy permanent FALSE, got %d\n", policy_permanent
);
2362 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2363 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2365 /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
2366 * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
2367 * where it is active, so that application which depend on that still work properly.
2368 * We have no exception handler enabled yet, so give proper EXECUTE permissions to
2369 * prevent crashes while creating the window. */
2371 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2372 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2374 memset( &wc
, 0, sizeof(wc
) );
2375 wc
.cbSize
= sizeof(wc
);
2376 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2377 wc
.hInstance
= GetModuleHandleA( 0 );
2378 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2379 wc
.hbrBackground
= NULL
;
2380 wc
.lpszClassName
= cls_name
;
2381 wc
.lpfnWndProc
= (WNDPROC
)base
;
2382 success
= RegisterClassExA(&wc
) != 0;
2383 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2385 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2386 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2388 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2389 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2391 /* At first try with an instruction which is not recognized as proper ATL thunk
2392 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2393 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2395 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2396 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2398 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2399 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2400 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2401 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !IsProcessorFeaturePresent( PF_NX_ENABLED
))
2403 trace( "DEP hardware support is not available\n" );
2404 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2405 dep_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2407 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2409 trace( "DEP hardware support is available\n" );
2410 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2413 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2415 /* Now a bit more complicated, the page containing the code is protected with
2416 * PAGE_GUARD memory protection. */
2418 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2419 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2421 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2422 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2423 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2424 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2425 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2427 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2429 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2430 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2431 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2432 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2434 /* Now test with a proper ATL thunk instruction. */
2436 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2437 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2439 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2440 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2442 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2443 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2445 /* Try executing with PAGE_READWRITE protection. */
2447 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2448 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2450 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2451 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2452 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2453 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2454 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2456 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2458 /* Now a bit more complicated, the page containing the code is protected with
2459 * PAGE_GUARD memory protection. */
2461 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2462 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2464 /* the same, but with PAGE_GUARD set */
2465 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2466 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2467 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2468 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2469 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2471 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2473 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2474 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2475 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2476 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2478 /* The following test shows that on Windows, even a vectored exception handler
2479 * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */
2481 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !(dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2483 if (pRtlAddVectoredExceptionHandler
&& pRtlRemoveVectoredExceptionHandler
)
2485 PVOID vectored_handler
;
2487 success
= VirtualProtect( base
, size
, PAGE_NOACCESS
, &old_prot
);
2488 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2490 vectored_handler
= pRtlAddVectoredExceptionHandler( TRUE
, &execute_fault_vec_handler
);
2491 ok( vectored_handler
!= 0, "RtlAddVectoredExceptionHandler failed\n" );
2493 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2495 pRtlRemoveVectoredExceptionHandler( vectored_handler
);
2497 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2498 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2501 win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" );
2504 /* Test alternative ATL thunk instructions. */
2506 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2507 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 10);
2509 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2510 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2512 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2513 /* FIXME: we don't check the content of the register ECX yet */
2514 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2515 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2516 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2517 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2519 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2521 memcpy( base
, code_atl3
, sizeof(code_atl3
) );
2522 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2524 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2525 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2527 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2528 /* FIXME: we don't check the content of the registers ECX/EDX yet */
2529 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2530 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2531 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2532 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2534 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2536 memcpy( base
, code_atl4
, sizeof(code_atl4
) );
2537 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2539 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2540 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2542 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2543 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2544 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2545 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2546 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2547 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2548 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2549 ok( num_execute_fault_calls
== 0 || broken(num_execute_fault_calls
== 1) /* Windows XP */,
2550 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2552 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2554 memcpy( base
, code_atl5
, sizeof(code_atl5
) );
2556 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2557 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2559 ret
= (DWORD_PTR
)atl5_test_func
;
2560 ret
= call_proc_excpt( (void *)base
, &ret
- 1 );
2561 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2562 ok( ret
== 44, "call returned wrong result, expected 44, got %d\n", ret
);
2563 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2564 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2565 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2566 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2567 ok( num_execute_fault_calls
== 0 || broken(num_execute_fault_calls
== 1) /* Windows XP */,
2568 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2570 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2572 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2574 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2575 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2577 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2578 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2580 DestroyWindow( hWnd
);
2582 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2583 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2585 VirtualFree( base
, 0, MEM_RELEASE
);
2587 /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */
2589 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
2590 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
2592 win_skip( "MEM_WRITE_WATCH not supported\n" );
2595 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2598 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2599 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2600 ok( count
== 0, "wrong count %lu\n", count
);
2602 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2603 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2606 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2607 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2608 ok( count
== 1, "wrong count %lu\n", count
);
2609 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2611 /* Create a new window class and associcated Window (see above) */
2613 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2614 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2616 memset( &wc
, 0, sizeof(wc
) );
2617 wc
.cbSize
= sizeof(wc
);
2618 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2619 wc
.hInstance
= GetModuleHandleA( 0 );
2620 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2621 wc
.hbrBackground
= NULL
;
2622 wc
.lpszClassName
= cls_name
;
2623 wc
.lpfnWndProc
= (WNDPROC
)base
;
2624 success
= RegisterClassExA(&wc
) != 0;
2625 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2627 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2628 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2630 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2631 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2634 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2635 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2636 ok( count
== 0, "wrong count %lu\n", count
);
2638 /* At first try with an instruction which is not recognized as proper ATL thunk
2639 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2640 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2642 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2643 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2645 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2646 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2647 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2648 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2649 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2651 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2654 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2655 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2656 ok( count
== 0, "wrong count %lu\n", count
);
2658 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2659 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2660 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2661 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2663 /* Now a bit more complicated, the page containing the code is protected with
2664 * PAGE_GUARD memory protection. */
2666 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2667 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2669 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2670 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2671 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2672 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2673 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2675 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
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 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2683 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2684 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2685 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2687 /* Now test with a proper ATL thunk instruction. */
2689 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2690 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2693 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2694 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2695 ok( count
== 1, "wrong count %lu\n", count
);
2696 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2698 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2699 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2701 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2702 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2704 /* Try executing with PAGE_READWRITE protection. */
2706 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2707 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2709 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2710 ok( ret
== 43, "call returned wrong result, expected 43, 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 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2713 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2715 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2718 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2719 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2720 ok( count
== 0, "wrong count %lu\n", count
);
2722 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2723 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2724 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2725 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2726 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2728 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2730 /* Now a bit more complicated, the page containing the code is protected with
2731 * PAGE_GUARD memory protection. */
2733 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2734 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2736 /* the same, but with PAGE_GUARD set */
2737 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2738 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2739 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2740 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2741 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2743 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2745 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2746 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2747 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2748 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2751 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2752 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2753 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2755 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2757 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2758 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2761 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2762 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2763 ok( count
== 1, "wrong count %lu\n", count
);
2764 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2766 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2767 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2769 DestroyWindow( hWnd
);
2771 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2772 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2774 VirtualFree( base
, 0, MEM_RELEASE
);
2779 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
) );
2780 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2784 #endif /* __i386__ */
2786 static void test_VirtualProtect(void)
2788 static const struct test_data
2790 DWORD prot_set
, prot_get
;
2793 { 0, 0 }, /* 0x00 */
2794 { PAGE_NOACCESS
, PAGE_NOACCESS
}, /* 0x01 */
2795 { PAGE_READONLY
, PAGE_READONLY
}, /* 0x02 */
2796 { PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x03 */
2797 { PAGE_READWRITE
, PAGE_READWRITE
}, /* 0x04 */
2798 { PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x05 */
2799 { PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x06 */
2800 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x07 */
2801 { PAGE_WRITECOPY
, 0 }, /* 0x08 */
2802 { PAGE_WRITECOPY
| PAGE_NOACCESS
, 0 }, /* 0x09 */
2803 { PAGE_WRITECOPY
| PAGE_READONLY
, 0 }, /* 0x0a */
2804 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, 0 }, /* 0x0b */
2805 { PAGE_WRITECOPY
| PAGE_READWRITE
, 0 }, /* 0x0c */
2806 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x0d */
2807 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x0e */
2808 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x0f */
2810 { PAGE_EXECUTE
, PAGE_EXECUTE
}, /* 0x10 */
2811 { PAGE_EXECUTE_READ
, PAGE_EXECUTE_READ
}, /* 0x20 */
2812 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x30 */
2813 { PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
2814 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0x50 */
2815 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0x60 */
2816 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x70 */
2817 { PAGE_EXECUTE_WRITECOPY
, 0 }, /* 0x80 */
2818 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, 0 }, /* 0x90 */
2819 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, 0 }, /* 0xa0 */
2820 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0xb0 */
2821 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, 0 }, /* 0xc0 */
2822 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0xd0 */
2823 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0xe0 */
2824 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 } /* 0xf0 */
2827 DWORD ret
, old_prot
, rw_prot
, exec_prot
, i
, j
;
2828 MEMORY_BASIC_INFORMATION info
;
2835 trace("system page size %#x\n", si
.dwPageSize
);
2837 SetLastError(0xdeadbeef);
2838 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_RESERVE
| MEM_COMMIT
, PAGE_NOACCESS
);
2839 ok(base
!= NULL
, "VirtualAlloc failed %d\n", GetLastError());
2841 SetLastError(0xdeadbeef);
2842 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_READONLY
, NULL
);
2843 ok(!ret
, "VirtualProtect should fail\n");
2844 ok(GetLastError() == ERROR_NOACCESS
, "expected ERROR_NOACCESS, got %d\n", GetLastError());
2845 old_prot
= 0xdeadbeef;
2846 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2847 ok(ret
, "VirtualProtect failed %d\n", GetLastError());
2848 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2851 size
= si
.dwPageSize
;
2852 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_READONLY
, NULL
);
2853 ok(status
== STATUS_ACCESS_VIOLATION
, "NtProtectVirtualMemory should fail, got %08x\n", status
);
2855 size
= si
.dwPageSize
;
2856 old_prot
= 0xdeadbeef;
2857 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_NOACCESS
, &old_prot
);
2858 ok(status
== STATUS_SUCCESS
, "NtProtectVirtualMemory should succeed, got %08x\n", status
);
2859 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2861 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
2863 SetLastError(0xdeadbeef);
2864 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2865 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2866 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2867 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2868 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
2869 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2870 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2871 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2872 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2874 old_prot
= 0xdeadbeef;
2875 SetLastError(0xdeadbeef);
2876 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot_set
, &old_prot
);
2879 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2880 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
2882 SetLastError(0xdeadbeef);
2883 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2884 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2885 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2886 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2887 ok(info
.Protect
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_get
);
2888 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2889 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2890 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2891 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2895 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
2896 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
2899 old_prot
= 0xdeadbeef;
2900 SetLastError(0xdeadbeef);
2901 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2902 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2904 ok(old_prot
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_get
);
2906 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
2911 for (i
= 0; i
<= 4; i
++)
2915 for (j
= 0; j
<= 4; j
++)
2917 DWORD prot
= exec_prot
| rw_prot
;
2919 SetLastError(0xdeadbeef);
2920 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, prot
);
2921 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
2923 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
2924 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2928 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
2930 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
2931 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2935 ok(ptr
!= NULL
, "VirtualAlloc(%02x) error %d\n", prot
, GetLastError());
2936 ok(ptr
== base
, "expected %p, got %p\n", base
, ptr
);
2940 SetLastError(0xdeadbeef);
2941 ret
= VirtualProtect(base
, si
.dwPageSize
, prot
, &old_prot
);
2942 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
2944 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
2945 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2949 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
2951 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
2952 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2955 ok(ret
, "VirtualProtect(%02x) error %d\n", prot
, GetLastError());
2961 exec_prot
= 1 << (i
+ 4);
2964 VirtualFree(base
, 0, MEM_RELEASE
);
2967 static BOOL
is_mem_writable(DWORD prot
)
2969 switch (prot
& 0xff)
2971 case PAGE_READWRITE
:
2972 case PAGE_WRITECOPY
:
2973 case PAGE_EXECUTE_READWRITE
:
2974 case PAGE_EXECUTE_WRITECOPY
:
2982 static void test_VirtualAlloc_protection(void)
2984 static const struct test_data
2990 { 0, FALSE
}, /* 0x00 */
2991 { PAGE_NOACCESS
, TRUE
}, /* 0x01 */
2992 { PAGE_READONLY
, TRUE
}, /* 0x02 */
2993 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x03 */
2994 { PAGE_READWRITE
, TRUE
}, /* 0x04 */
2995 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x05 */
2996 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x06 */
2997 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x07 */
2998 { PAGE_WRITECOPY
, FALSE
}, /* 0x08 */
2999 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
}, /* 0x09 */
3000 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
}, /* 0x0a */
3001 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
}, /* 0x0b */
3002 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
}, /* 0x0c */
3003 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x0d */
3004 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x0e */
3005 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x0f */
3007 { PAGE_EXECUTE
, TRUE
}, /* 0x10 */
3008 { PAGE_EXECUTE_READ
, TRUE
}, /* 0x20 */
3009 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x30 */
3010 { PAGE_EXECUTE_READWRITE
, TRUE
}, /* 0x40 */
3011 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0x50 */
3012 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0x60 */
3013 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x70 */
3014 { PAGE_EXECUTE_WRITECOPY
, FALSE
}, /* 0x80 */
3015 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
}, /* 0x90 */
3016 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xa0 */
3017 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0xb0 */
3018 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
}, /* 0xc0 */
3019 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0xd0 */
3020 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xe0 */
3021 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
} /* 0xf0 */
3025 MEMORY_BASIC_INFORMATION info
;
3029 trace("system page size %#x\n", si
.dwPageSize
);
3031 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3033 SetLastError(0xdeadbeef);
3034 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3038 ok(base
!= NULL
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3040 SetLastError(0xdeadbeef);
3041 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3042 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3043 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3044 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3045 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3046 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3047 ok(info
.AllocationProtect
== td
[i
].prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, td
[i
].prot
);
3048 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3049 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
3051 if (is_mem_writable(info
.Protect
))
3055 SetLastError(0xdeadbeef);
3056 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3057 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3058 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3061 SetLastError(0xdeadbeef);
3062 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3063 ok(ptr
== base
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3065 VirtualFree(base
, 0, MEM_RELEASE
);
3069 ok(!base
, "%d: VirtualAlloc should fail\n", i
);
3070 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3075 static void test_CreateFileMapping_protection(void)
3077 static const struct test_data
3081 DWORD prot_after_write
;
3084 { 0, FALSE
, 0 }, /* 0x00 */
3085 { PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x01 */
3086 { PAGE_READONLY
, TRUE
, PAGE_READONLY
}, /* 0x02 */
3087 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x03 */
3088 { PAGE_READWRITE
, TRUE
, PAGE_READWRITE
}, /* 0x04 */
3089 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x05 */
3090 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x06 */
3091 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x07 */
3092 { PAGE_WRITECOPY
, TRUE
, PAGE_READWRITE
}, /* 0x08 */
3093 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x09 */
3094 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0a */
3095 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0b */
3096 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0x0c */
3097 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0d */
3098 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0e */
3099 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0f */
3101 { PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE
}, /* 0x10 */
3102 { PAGE_EXECUTE_READ
, TRUE
, PAGE_EXECUTE_READ
}, /* 0x20 */
3103 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE_READ
}, /* 0x30 */
3104 { PAGE_EXECUTE_READWRITE
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
3105 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x50 */
3106 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0x60 */
3107 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x70 */
3108 { PAGE_EXECUTE_WRITECOPY
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x80 */
3109 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x90 */
3110 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xa0 */
3111 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xb0 */
3112 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0xc0 */
3113 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xd0 */
3114 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xe0 */
3115 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
} /* 0xf0 */
3118 DWORD ret
, i
, alloc_prot
, prot
, old_prot
;
3119 MEMORY_BASIC_INFORMATION info
;
3121 char temp_path
[MAX_PATH
];
3122 char file_name
[MAX_PATH
];
3124 BOOL page_exec_supported
= TRUE
;
3127 trace("system page size %#x\n", si
.dwPageSize
);
3129 GetTempPathA(MAX_PATH
, temp_path
);
3130 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3132 SetLastError(0xdeadbeef);
3133 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3134 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3135 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3136 SetEndOfFile(hfile
);
3138 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3140 SetLastError(0xdeadbeef);
3141 hmap
= CreateFileMappingW(hfile
, NULL
, td
[i
].prot
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3147 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, td
[i
].prot
, GetLastError());
3148 /* NT4 and win2k don't support EXEC on file mappings */
3149 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3151 page_exec_supported
= FALSE
;
3152 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3155 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3156 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3158 page_exec_supported
= FALSE
;
3159 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3163 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, td
[i
].prot
, GetLastError());
3165 base
= MapViewOfFile(hmap
, FILE_MAP_READ
, 0, 0, 0);
3166 ok(base
!= NULL
, "%d: MapViewOfFile failed %d\n", i
, GetLastError());
3168 SetLastError(0xdeadbeef);
3169 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3170 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3171 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3172 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3173 ok(info
.Protect
== PAGE_READONLY
, "%d: got %#x != expected PAGE_READONLY\n", i
, info
.Protect
);
3174 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3175 ok(info
.AllocationProtect
== PAGE_READONLY
, "%d: %#x != PAGE_READONLY\n", i
, info
.AllocationProtect
);
3176 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3177 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3179 if (is_mem_writable(info
.Protect
))
3183 SetLastError(0xdeadbeef);
3184 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3185 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3186 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3189 SetLastError(0xdeadbeef);
3190 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3191 ok(!ptr
, "%d: VirtualAlloc(%02x) should fail\n", i
, td
[i
].prot
);
3192 /* FIXME: remove once Wine is fixed */
3193 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3194 ok(GetLastError() == ERROR_ACCESS_DENIED
, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i
, GetLastError());
3196 SetLastError(0xdeadbeef);
3197 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3198 if (td
[i
].prot
== PAGE_READONLY
|| td
[i
].prot
== PAGE_WRITECOPY
)
3199 ok(ret
, "%d: VirtualProtect(%02x) error %d\n", i
, td
[i
].prot
, GetLastError());
3202 ok(!ret
, "%d: VirtualProtect(%02x) should fail\n", i
, td
[i
].prot
);
3203 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3206 UnmapViewOfFile(base
);
3211 ok(!hmap
, "%d: CreateFileMapping should fail\n", i
);
3212 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3216 if (page_exec_supported
) alloc_prot
= PAGE_EXECUTE_READWRITE
;
3217 else alloc_prot
= PAGE_READWRITE
;
3218 SetLastError(0xdeadbeef);
3219 hmap
= CreateFileMappingW(hfile
, NULL
, alloc_prot
, 0, si
.dwPageSize
, NULL
);
3220 ok(hmap
!= 0, "%d: CreateFileMapping error %d\n", i
, GetLastError());
3222 SetLastError(0xdeadbeef);
3223 base
= MapViewOfFile(hmap
, FILE_MAP_READ
| FILE_MAP_WRITE
| (page_exec_supported
? FILE_MAP_EXECUTE
: 0), 0, 0, 0);
3224 ok(base
!= NULL
, "MapViewOfFile failed %d\n", GetLastError());
3226 old_prot
= 0xdeadbeef;
3227 SetLastError(0xdeadbeef);
3228 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3229 ok(ret
, "VirtualProtect error %d\n", GetLastError());
3230 ok(old_prot
== alloc_prot
, "got %#x != expected %#x\n", old_prot
, alloc_prot
);
3232 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3234 SetLastError(0xdeadbeef);
3235 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3236 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3237 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3238 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3239 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
3240 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3241 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3242 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3243 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3245 old_prot
= 0xdeadbeef;
3246 SetLastError(0xdeadbeef);
3247 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3248 if (td
[i
].success
|| td
[i
].prot
== PAGE_NOACCESS
|| td
[i
].prot
== PAGE_EXECUTE
)
3252 /* win2k and XP don't support EXEC on file mappings */
3253 if (td
[i
].prot
== PAGE_EXECUTE
)
3255 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3258 /* NT4 and win2k don't support EXEC on file mappings */
3259 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3261 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3264 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3265 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3267 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3272 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3273 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
3276 /* looks strange but Windows doesn't do this for PAGE_WRITECOPY */
3277 if (prot
== PAGE_EXECUTE_WRITECOPY
) prot
= PAGE_EXECUTE_READWRITE
;
3279 SetLastError(0xdeadbeef);
3280 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3281 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3282 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3283 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3284 /* FIXME: remove the condition below once Wine is fixed */
3285 todo_wine_if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3286 ok(info
.Protect
== prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, prot
);
3287 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3288 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3289 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3290 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3292 if (is_mem_writable(info
.Protect
))
3296 SetLastError(0xdeadbeef);
3297 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3298 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3299 ok(info
.Protect
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_after_write
);
3304 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
3305 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3309 old_prot
= 0xdeadbeef;
3310 SetLastError(0xdeadbeef);
3311 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3312 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3313 ok(old_prot
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_after_write
);
3316 UnmapViewOfFile(base
);
3320 DeleteFileA(file_name
);
3323 #define ACCESS_READ 0x01
3324 #define ACCESS_WRITE 0x02
3325 #define ACCESS_EXECUTE 0x04
3326 #define ACCESS_WRITECOPY 0x08
3328 static DWORD
page_prot_to_access(DWORD prot
)
3332 case PAGE_READWRITE
:
3333 return ACCESS_READ
| ACCESS_WRITE
;
3336 case PAGE_EXECUTE_READ
:
3337 return ACCESS_READ
| ACCESS_EXECUTE
;
3339 case PAGE_EXECUTE_READWRITE
:
3340 return ACCESS_READ
| ACCESS_WRITE
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3342 case PAGE_EXECUTE_WRITECOPY
:
3343 return ACCESS_READ
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3348 case PAGE_WRITECOPY
:
3356 static BOOL
is_compatible_protection(DWORD map_prot
, DWORD view_prot
, DWORD prot
)
3358 DWORD map_access
, view_access
, prot_access
;
3360 map_access
= page_prot_to_access(map_prot
);
3361 view_access
= page_prot_to_access(view_prot
);
3362 prot_access
= page_prot_to_access(prot
);
3364 if (view_access
== prot_access
) return TRUE
;
3365 if (!view_access
) return FALSE
;
3367 if ((view_access
& prot_access
) != prot_access
) return FALSE
;
3368 if ((map_access
& prot_access
) == prot_access
) return TRUE
;
3373 static DWORD
map_prot_to_access(DWORD prot
)
3377 case PAGE_READWRITE
:
3378 case PAGE_EXECUTE_READWRITE
:
3379 return SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3381 case PAGE_WRITECOPY
:
3383 case PAGE_EXECUTE_READ
:
3384 case PAGE_EXECUTE_WRITECOPY
:
3385 return SECTION_MAP_READ
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3391 static BOOL
is_compatible_access(DWORD map_prot
, DWORD view_prot
)
3393 DWORD access
= map_prot_to_access(map_prot
);
3394 if (!view_prot
) view_prot
= SECTION_MAP_READ
;
3395 return (view_prot
& access
) == view_prot
;
3398 static void *map_view_of_file(HANDLE handle
, DWORD access
)
3401 LARGE_INTEGER offset
;
3407 if (!pNtMapViewOfSection
) return NULL
;
3410 offset
.u
.LowPart
= 0;
3411 offset
.u
.HighPart
= 0;
3413 exec
= access
& FILE_MAP_EXECUTE
;
3414 access
&= ~FILE_MAP_EXECUTE
;
3416 if (access
== FILE_MAP_COPY
)
3419 protect
= PAGE_EXECUTE_WRITECOPY
;
3421 protect
= PAGE_WRITECOPY
;
3423 else if (access
& FILE_MAP_WRITE
)
3426 protect
= PAGE_EXECUTE_READWRITE
;
3428 protect
= PAGE_READWRITE
;
3430 else if (access
& FILE_MAP_READ
)
3433 protect
= PAGE_EXECUTE_READ
;
3435 protect
= PAGE_READONLY
;
3437 else protect
= PAGE_NOACCESS
;
3440 status
= pNtMapViewOfSection(handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
3441 &count
, 1 /* ViewShare */, 0, protect
);
3444 /* for simplicity */
3445 SetLastError(ERROR_ACCESS_DENIED
);
3451 static void test_mapping(void)
3453 static const DWORD page_prot
[] =
3455 PAGE_NOACCESS
, PAGE_READONLY
, PAGE_READWRITE
, PAGE_WRITECOPY
,
3456 PAGE_EXECUTE_READ
, PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_WRITECOPY
3463 { 0, PAGE_NOACCESS
}, /* 0x00 */
3464 { FILE_MAP_COPY
, PAGE_WRITECOPY
}, /* 0x01 */
3465 { FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x02 */
3466 { FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x03 */
3467 { FILE_MAP_READ
, PAGE_READONLY
}, /* 0x04 */
3468 { FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x05 */
3469 { FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x06 */
3470 { FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x07 */
3471 { SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x08 */
3472 { SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x09 */
3473 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0a */
3474 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0b */
3475 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_READONLY
}, /* 0x0c */
3476 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x0d */
3477 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0e */
3478 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0f */
3479 { FILE_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x20 */
3480 { FILE_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_EXECUTE_WRITECOPY
}, /* 0x21 */
3481 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x22 */
3482 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x23 */
3483 { FILE_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x24 */
3484 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x25 */
3485 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x26 */
3486 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x27 */
3487 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x28 */
3488 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x29 */
3489 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2a */
3490 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x2b */
3491 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x2c */
3492 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x2d */
3493 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2e */
3494 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
} /* 0x2f */
3496 void *base
, *nt_base
, *ptr
;
3497 DWORD i
, j
, k
, ret
, old_prot
, prev_prot
;
3499 char temp_path
[MAX_PATH
];
3500 char file_name
[MAX_PATH
];
3502 MEMORY_BASIC_INFORMATION info
, nt_info
;
3505 trace("system page size %#x\n", si
.dwPageSize
);
3507 GetTempPathA(MAX_PATH
, temp_path
);
3508 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3510 SetLastError(0xdeadbeef);
3511 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3512 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3513 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3514 SetEndOfFile(hfile
);
3516 for (i
= 0; i
< sizeof(page_prot
)/sizeof(page_prot
[0]); i
++)
3518 SetLastError(0xdeadbeef);
3519 hmap
= CreateFileMappingW(hfile
, NULL
, page_prot
[i
] | SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3521 if (page_prot
[i
] == PAGE_NOACCESS
)
3525 ok(!hmap
, "CreateFileMapping(PAGE_NOACCESS) should fail\n");
3526 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3528 /* A trick to create a not accessible mapping */
3529 SetLastError(0xdeadbeef);
3530 hmap
= CreateFileMappingW(hfile
, NULL
, PAGE_READWRITE
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3531 ok(hmap
!= 0, "CreateFileMapping(PAGE_READWRITE) error %d\n", GetLastError());
3532 SetLastError(0xdeadbeef);
3533 ret
= DuplicateHandle(GetCurrentProcess(), hmap
, GetCurrentProcess(), &hmap2
, 0, FALSE
, 0);
3534 ok(ret
, "DuplicateHandle error %d\n", GetLastError());
3541 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, page_prot
[i
], GetLastError());
3543 /* NT4 and win2k don't support EXEC on file mappings */
3544 if (page_prot
[i
] == PAGE_EXECUTE_READ
|| page_prot
[i
] == PAGE_EXECUTE_READWRITE
)
3546 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3549 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3550 if (page_prot
[i
] == PAGE_EXECUTE_WRITECOPY
)
3552 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3557 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, page_prot
[i
], GetLastError());
3559 for (j
= 0; j
< sizeof(view
)/sizeof(view
[0]); j
++)
3561 nt_base
= map_view_of_file(hmap
, view
[j
].access
);
3564 SetLastError(0xdeadbeef);
3565 ret
= VirtualQuery(nt_base
, &nt_info
, sizeof(nt_info
));
3566 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3567 UnmapViewOfFile(nt_base
);
3570 SetLastError(0xdeadbeef);
3571 base
= MapViewOfFile(hmap
, view
[j
].access
, 0, 0, 0);
3573 /* Vista+ supports FILE_MAP_EXECUTE properly, earlier versions don't */
3574 ok(!nt_base
== !base
||
3575 broken((view
[j
].access
& FILE_MAP_EXECUTE
) && !nt_base
!= !base
),
3576 "%d: (%04x/%04x) NT %p kernel %p\n", j
, page_prot
[i
], view
[j
].access
, nt_base
, base
);
3578 if (!is_compatible_access(page_prot
[i
], view
[j
].access
))
3580 ok(!base
, "%d: MapViewOfFile(%04x/%04x) should fail\n", j
, page_prot
[i
], view
[j
].access
);
3581 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %d\n", GetLastError());
3585 /* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */
3586 if (!base
&& (view
[j
].access
& FILE_MAP_EXECUTE
))
3588 ok(broken(!base
), "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3592 ok(base
!= NULL
, "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3594 SetLastError(0xdeadbeef);
3595 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3596 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3597 ok(info
.BaseAddress
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.BaseAddress
, base
);
3598 ok(info
.RegionSize
== si
.dwPageSize
, "%d: (%04x) got %#lx != expected %#x\n", j
, view
[j
].access
, info
.RegionSize
, si
.dwPageSize
);
3599 ok(info
.Protect
== view
[j
].prot
||
3600 broken(view
[j
].prot
== PAGE_EXECUTE_READ
&& info
.Protect
== PAGE_READONLY
) || /* win2k */
3601 broken(view
[j
].prot
== PAGE_EXECUTE_READWRITE
&& info
.Protect
== PAGE_READWRITE
) || /* win2k */
3602 broken(view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3603 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.Protect
, view
[j
].prot
);
3604 ok(info
.AllocationBase
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.AllocationBase
, base
);
3605 ok(info
.AllocationProtect
== info
.Protect
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.AllocationProtect
, info
.Protect
);
3606 ok(info
.State
== MEM_COMMIT
, "%d: (%04x) got %#x, expected MEM_COMMIT\n", j
, view
[j
].access
, info
.State
);
3607 ok(info
.Type
== MEM_MAPPED
, "%d: (%04x) got %#x, expected MEM_MAPPED\n", j
, view
[j
].access
, info
.Type
);
3609 if (nt_base
&& base
)
3611 ok(nt_info
.RegionSize
== info
.RegionSize
, "%d: (%04x) got %#lx != expected %#lx\n", j
, view
[j
].access
, nt_info
.RegionSize
, info
.RegionSize
);
3612 ok(nt_info
.Protect
== info
.Protect
/* Vista+ */ ||
3613 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3614 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Protect
, info
.Protect
);
3615 ok(nt_info
.AllocationProtect
== info
.AllocationProtect
/* Vista+ */ ||
3616 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3617 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.AllocationProtect
, info
.AllocationProtect
);
3618 ok(nt_info
.State
== info
.State
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.State
, info
.State
);
3619 ok(nt_info
.Type
== info
.Type
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Type
, info
.Type
);
3622 prev_prot
= info
.Protect
;
3624 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3626 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3627 SetLastError(0xdeadbeef);
3628 old_prot
= 0xdeadbeef;
3629 ret
= VirtualProtect(base
, si
.dwPageSize
, page_prot
[k
], &old_prot
);
3630 if (is_compatible_protection(page_prot
[i
], view
[j
].prot
, page_prot
[k
]))
3632 /* win2k and XP don't support EXEC on file mappings */
3633 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE
)
3635 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3638 /* NT4 and win2k don't support EXEC on file mappings */
3639 if (!ret
&& (page_prot
[k
] == PAGE_EXECUTE_READ
|| page_prot
[k
] == PAGE_EXECUTE_READWRITE
))
3641 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3644 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3645 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE_WRITECOPY
)
3647 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n");
3650 /* win2k and XP don't support PAGE_EXECUTE_WRITECOPY views properly */
3651 if (!ret
&& view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
)
3653 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY view properly\n");
3657 ok(ret
, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3658 ok(old_prot
== prev_prot
, "got %#x, expected %#x\n", old_prot
, prev_prot
);
3659 prev_prot
= page_prot
[k
];
3663 /* NT4 doesn't fail on incompatible map and view */
3666 ok(broken(ret
), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3667 skip("Incompatible map and view are not properly handled on this platform\n");
3668 break; /* NT4 won't pass remaining tests */
3671 ok(!ret
, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3672 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3676 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3678 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3679 SetLastError(0xdeadbeef);
3680 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, page_prot
[k
]);
3681 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", page_prot
[k
]);
3682 /* FIXME: remove once Wine is fixed */
3683 todo_wine_if (page_prot
[k
] == PAGE_WRITECOPY
|| page_prot
[k
] == PAGE_EXECUTE_WRITECOPY
)
3684 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3687 UnmapViewOfFile(base
);
3694 DeleteFileA(file_name
);
3697 static void test_shared_memory(BOOL is_child
)
3702 SetLastError(0xdeadbef);
3703 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c");
3704 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3706 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3708 SetLastError(0xdeadbef);
3709 p
= MapViewOfFile(mapping
, FILE_MAP_READ
|FILE_MAP_WRITE
, 0, 0, 4096);
3710 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3714 ok(*p
== 0x1a2b3c4d, "expected 0x1a2b3c4d in child, got %#x\n", *p
);
3719 char cmdline
[MAX_PATH
];
3720 PROCESS_INFORMATION pi
;
3721 STARTUPINFOA si
= { sizeof(si
) };
3726 winetest_get_mainargs(&argv
);
3727 sprintf(cmdline
, "\"%s\" virtual sharedmem", argv
[0]);
3728 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3729 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3730 winetest_wait_child_process(pi
.hProcess
);
3731 CloseHandle(pi
.hThread
);
3732 CloseHandle(pi
.hProcess
);
3736 CloseHandle(mapping
);
3739 static void test_shared_memory_ro(BOOL is_child
, DWORD child_access
)
3744 SetLastError(0xdeadbef);
3745 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c_ro");
3746 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3748 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3750 SetLastError(0xdeadbef);
3751 p
= MapViewOfFile(mapping
, is_child
? child_access
: FILE_MAP_READ
, 0, 0, 4096);
3752 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3761 char cmdline
[MAX_PATH
];
3762 PROCESS_INFORMATION pi
;
3763 STARTUPINFOA si
= { sizeof(si
) };
3766 winetest_get_mainargs(&argv
);
3767 sprintf(cmdline
, "\"%s\" virtual sharedmemro %x", argv
[0], child_access
);
3768 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3769 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3770 winetest_wait_child_process(pi
.hProcess
);
3771 CloseHandle(pi
.hThread
);
3772 CloseHandle(pi
.hProcess
);
3774 if(child_access
& FILE_MAP_WRITE
)
3775 ok(*p
== 0xdeadbeef, "*p = %x, expected 0xdeadbeef\n", *p
);
3777 ok(!*p
, "*p = %x, expected 0\n", *p
);
3781 CloseHandle(mapping
);
3784 static void test_NtQuerySection(void)
3786 char path
[MAX_PATH
];
3787 HANDLE file
, mapping
;
3792 SECTION_BASIC_INFORMATION basic
;
3793 SECTION_IMAGE_INFORMATION image
;
3796 IMAGE_NT_HEADERS
*nt
;
3798 SIZE_T fsize
, image_size
;
3801 if (!pNtQuerySection
)
3803 win_skip("NtQuerySection is not available\n");
3808 page_mask
= si
.dwPageSize
- 1;
3810 GetSystemDirectoryA(path
, sizeof(path
));
3811 strcat(path
, "\\kernel32.dll");
3813 SetLastError(0xdeadbef);
3814 file
= CreateFileA(path
, GENERIC_READ
|GENERIC_EXECUTE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
3815 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError());
3817 fsize
= GetFileSize(file
, NULL
);
3819 SetLastError(0xdeadbef);
3820 mapping
= CreateFileMappingA(file
, NULL
, PAGE_EXECUTE_READ
, 0, 0, NULL
);
3821 /* NT4 and win2k don't support EXEC on file mappings */
3823 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
3824 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
3826 status
= pNtQuerySection(mapping
, SectionBasicInformation
, NULL
, sizeof(info
), &ret
);
3827 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status
);
3829 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, 0, NULL
);
3830 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3832 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, 0, &ret
);
3833 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3835 memset(&info
, 0x55, sizeof(info
));
3837 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3838 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3839 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3840 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3842 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
3844 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3846 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
.basic
), &ret
);
3847 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3849 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
), &ret
);
3850 ok(status
== STATUS_SECTION_NOT_IMAGE
, "expected STATUS_SECTION_NOT_IMAGE, got %#x\n", status
);
3852 SetLastError(0xdeadbef);
3853 p
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
3854 ok(p
!= NULL
, "MapViewOfFile error %u\n", GetLastError());
3856 nt
= image_nt_header(p
);
3857 image_size
= ROUND_SIZE(p
, nt
->OptionalHeader
.SizeOfImage
);
3859 memset(&info
, 0x55, sizeof(info
));
3861 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3862 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3863 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3864 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3866 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
3868 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3871 CloseHandle(mapping
);
3873 SetLastError(0xdeadbef);
3874 mapping
= CreateFileMappingA(file
, NULL
, PAGE_EXECUTE_READ
|SEC_IMAGE
, 0, 0, NULL
);
3875 /* NT4 and win2k don't support EXEC on file mappings */
3877 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
|SEC_IMAGE
, 0, 0, NULL
);
3878 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
3880 memset(&info
, 0x55, sizeof(info
));
3882 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3883 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3884 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3885 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3887 ok(info
.basic
.Attributes
== (SEC_FILE
|SEC_IMAGE
), "expected SEC_FILE|SEC_IMAGE, got %#x\n", info
.basic
.Attributes
);
3888 ok(info
.basic
.Size
.QuadPart
== image_size
, "expected %#lx, got %#x/%08x\n", image_size
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3890 status
= pNtQuerySection(mapping
, SectionImageInformation
, NULL
, sizeof(info
), &ret
);
3891 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status
);
3893 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, 0, NULL
);
3894 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3896 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, 0, &ret
);
3897 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3899 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
.basic
), &ret
);
3900 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3902 SetLastError(0xdeadbef);
3903 p
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
3904 ok(p
!= NULL
, "MapViewOfFile error %u\n", GetLastError());
3906 nt
= image_nt_header(p
);
3908 memset(&info
, 0x55, sizeof(info
));
3910 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
), &ret
);
3911 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3912 ok(ret
== sizeof(info
.image
), "wrong returned size %u\n", ret
);
3913 ok((ULONG_PTR
)info
.image
.TransferAddress
== nt
->OptionalHeader
.ImageBase
+ nt
->OptionalHeader
.AddressOfEntryPoint
,
3914 "expected %#lx, got %p\n", (SIZE_T
)(nt
->OptionalHeader
.ImageBase
+ nt
->OptionalHeader
.AddressOfEntryPoint
), info
.image
.TransferAddress
);
3915 ok(info
.image
.ZeroBits
== 0, "expected 0, got %#x\n", info
.image
.ZeroBits
);
3917 ok(info
.image
.MaximumStackSize
== nt
->OptionalHeader
.SizeOfStackReserve
, "expected %#lx, got %#lx\n", (SIZE_T
)nt
->OptionalHeader
.SizeOfStackReserve
, info
.image
.MaximumStackSize
);
3919 ok(info
.image
.CommittedStackSize
== nt
->OptionalHeader
.SizeOfStackCommit
, "expected %#lx, got %#lx\n", (SIZE_T
)nt
->OptionalHeader
.SizeOfStackCommit
, info
.image
.CommittedStackSize
);
3920 ok(info
.image
.SubSystemType
== nt
->OptionalHeader
.Subsystem
, "expected %#x, got %#x\n", nt
->OptionalHeader
.Subsystem
, info
.image
.SubSystemType
);
3921 ok(info
.image
.SubsystemVersionLow
== nt
->OptionalHeader
.MinorSubsystemVersion
, "expected %#x, got %#x\n", nt
->OptionalHeader
.MinorSubsystemVersion
, info
.image
.SubsystemVersionLow
);
3922 ok(info
.image
.SubsystemVersionHigh
== nt
->OptionalHeader
.MajorSubsystemVersion
, "expected %#x, got %#x\n", nt
->OptionalHeader
.MajorSubsystemVersion
, info
.image
.SubsystemVersionHigh
);
3923 ok(info
.image
.ImageCharacteristics
== nt
->FileHeader
.Characteristics
, "expected %#x, got %#x\n", nt
->FileHeader
.Characteristics
, info
.image
.ImageCharacteristics
);
3924 ok(info
.image
.DllCharacteristics
== nt
->OptionalHeader
.DllCharacteristics
, "expected %#x, got %#x\n", nt
->OptionalHeader
.DllCharacteristics
, info
.image
.DllCharacteristics
);
3925 ok(info
.image
.Machine
== nt
->FileHeader
.Machine
, "expected %#x, got %#x\n", nt
->FileHeader
.Machine
, info
.image
.Machine
);
3926 ok(info
.image
.ImageContainsCode
== TRUE
, "expected 1, got %#x\n", info
.image
.ImageContainsCode
);
3928 memset(&info
, 0x55, sizeof(info
));
3930 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3931 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3932 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3933 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3935 ok(info
.basic
.Attributes
== (SEC_FILE
|SEC_IMAGE
), "expected SEC_FILE|SEC_IMAGE, got %#x\n", info
.basic
.Attributes
);
3936 ok(info
.basic
.Size
.QuadPart
== image_size
, "expected %#lx, got %#x/%08x\n", image_size
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3939 CloseHandle(mapping
);
3941 SetLastError(0xdeadbef);
3942 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
|SEC_COMMIT
|SEC_NOCACHE
, 0, 0, NULL
);
3943 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
3945 memset(&info
, 0x55, sizeof(info
));
3947 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3948 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3949 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3950 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3952 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
3954 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3956 CloseHandle(mapping
);
3958 SetLastError(0xdeadbef);
3959 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
|SEC_RESERVE
, 0, 0, NULL
);
3961 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
3962 if (!mapping
) goto skip1
;
3964 memset(&info
, 0x55, sizeof(info
));
3966 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3967 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3968 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3969 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3970 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
3971 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3973 CloseHandle(mapping
);
3977 SetLastError(0xdeadbef);
3978 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
|SEC_COMMIT
, 0, 4096, NULL
);
3979 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
3981 memset(&info
, 0x55, sizeof(info
));
3983 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3984 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3985 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3986 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3987 ok(info
.basic
.Attributes
== SEC_COMMIT
, "expected SEC_COMMIT, got %#x\n", info
.basic
.Attributes
);
3988 ok(info
.basic
.Size
.QuadPart
== 4096, "expected 4096, got %#x/%08x\n", info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3990 SetLastError(0xdeadbef);
3991 p
= MapViewOfFile(mapping
, FILE_MAP_READ
|FILE_MAP_WRITE
, 0, 0, 0);
3992 ok(p
!= NULL
, "MapViewOfFile error %u\n", GetLastError());
3994 memset(&info
, 0x55, sizeof(info
));
3996 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3997 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3998 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3999 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4000 ok(info
.basic
.Attributes
== SEC_COMMIT
, "expected SEC_COMMIT, got %#x\n", info
.basic
.Attributes
);
4001 ok(info
.basic
.Size
.QuadPart
== 4096, "expected 4096, got %#x/%08x\n", info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4004 CloseHandle(mapping
);
4006 SetLastError(0xdeadbef);
4007 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READONLY
|SEC_RESERVE
, 0, 4096, NULL
);
4008 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
4010 memset(&info
, 0x55, sizeof(info
));
4012 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4013 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4014 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4015 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4016 ok(info
.basic
.Attributes
== SEC_RESERVE
, "expected SEC_RESERVE, got %#x\n", info
.basic
.Attributes
);
4017 ok(info
.basic
.Size
.QuadPart
== 4096, "expected 4096, got %#x/%08x\n", info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4019 CloseHandle(mapping
);
4026 argc
= winetest_get_mainargs( &argv
);
4030 if (!strcmp(argv
[2], "sleep"))
4032 Sleep(5000); /* spawned process runs for at most 5 seconds */
4035 if (!strcmp(argv
[2], "sharedmem"))
4037 test_shared_memory(TRUE
);
4040 if (!strcmp(argv
[2], "sharedmemro"))
4042 if(!winetest_interactive
)
4044 skip("CORE-8541: Skipping test_shared_memory_ro(TRUE, strtol(argv[3], NULL, 16))\n");
4048 test_shared_memory_ro(TRUE
, strtol(argv
[3], NULL
, 16));
4056 mem
= VirtualAlloc(NULL
, 1<<20, MEM_COMMIT
|MEM_RESERVE
,
4057 PAGE_EXECUTE_READWRITE
);
4058 ok(mem
!= NULL
, "VirtualAlloc failed %u\n", GetLastError());
4059 if (mem
== NULL
) break;
4060 ret
= VirtualFree(mem
, 0, MEM_RELEASE
);
4061 ok(ret
, "VirtualFree failed %u\n", GetLastError());
4067 hkernel32
= GetModuleHandleA("kernel32.dll");
4068 hntdll
= GetModuleHandleA("ntdll.dll");
4070 pVirtualAllocEx
= (void *) GetProcAddress(hkernel32
, "VirtualAllocEx");
4071 pVirtualFreeEx
= (void *) GetProcAddress(hkernel32
, "VirtualFreeEx");
4072 pGetWriteWatch
= (void *) GetProcAddress(hkernel32
, "GetWriteWatch");
4073 pResetWriteWatch
= (void *) GetProcAddress(hkernel32
, "ResetWriteWatch");
4074 pGetProcessDEPPolicy
= (void *)GetProcAddress( hkernel32
, "GetProcessDEPPolicy" );
4075 pIsWow64Process
= (void *)GetProcAddress( hkernel32
, "IsWow64Process" );
4076 pNtAreMappedFilesTheSame
= (void *)GetProcAddress( hntdll
, "NtAreMappedFilesTheSame" );
4077 pNtMapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtMapViewOfSection" );
4078 pNtUnmapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtUnmapViewOfSection" );
4079 pNtCurrentTeb
= (void *)GetProcAddress( hntdll
, "NtCurrentTeb" );
4080 pRtlAddVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlAddVectoredExceptionHandler" );
4081 pRtlRemoveVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlRemoveVectoredExceptionHandler" );
4082 pNtQuerySection
= (void *)GetProcAddress( hntdll
, "NtQuerySection" );
4083 pNtProtectVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtProtectVirtualMemory" );
4084 pNtAllocateVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtAllocateVirtualMemory" );
4085 pNtFreeVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtFreeVirtualMemory" );
4087 test_shared_memory(FALSE
);
4088 test_shared_memory_ro(FALSE
, FILE_MAP_READ
|FILE_MAP_WRITE
);
4089 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
);
4090 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
|FILE_MAP_WRITE
);
4092 test_NtQuerySection();
4093 test_CreateFileMapping_protection();
4094 test_VirtualAlloc_protection();
4095 test_VirtualProtect();
4096 test_VirtualAllocEx();
4097 test_VirtualAlloc();
4098 test_MapViewOfFile();
4099 test_NtMapViewOfSection();
4100 test_NtAreMappedFilesTheSame();
4101 test_CreateFileMapping();
4102 test_IsBadReadPtr();
4103 test_IsBadWritePtr();
4104 test_IsBadCodePtr();
4106 test_stack_commit();
4108 if (!winetest_interactive
)
4110 skip("ROSTESTS-155: Skipping virtual guard page tests due to Mm assertion failure.\n");
4115 /* The following tests should be executed as a last step, and in exactly this
4116 * order, since ATL thunk emulation cannot be enabled anymore on Windows. */
4117 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE
);
4118 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
);
4119 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
| MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
);