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
23 #include <wine/exception.h>
26 #define MAPPING_SIZE 0x100000
28 static HINSTANCE hkernel32
, hntdll
;
29 static LPVOID (WINAPI
*pVirtualAllocEx
)(HANDLE
, LPVOID
, SIZE_T
, DWORD
, DWORD
);
30 static BOOL (WINAPI
*pVirtualFreeEx
)(HANDLE
, LPVOID
, SIZE_T
, DWORD
);
31 static UINT (WINAPI
*pGetWriteWatch
)(DWORD
,LPVOID
,SIZE_T
,LPVOID
*,ULONG_PTR
*,ULONG
*);
32 static UINT (WINAPI
*pResetWriteWatch
)(LPVOID
,SIZE_T
);
33 static NTSTATUS (WINAPI
*pNtAreMappedFilesTheSame
)(PVOID
,PVOID
);
34 static NTSTATUS (WINAPI
*pNtCreateSection
)(HANDLE
*, ACCESS_MASK
, const OBJECT_ATTRIBUTES
*,
35 const LARGE_INTEGER
*, ULONG
, ULONG
, HANDLE
);
36 static NTSTATUS (WINAPI
*pNtMapViewOfSection
)(HANDLE
, HANDLE
, PVOID
*, ULONG
, SIZE_T
, const LARGE_INTEGER
*, SIZE_T
*, ULONG
, ULONG
, ULONG
);
37 static DWORD (WINAPI
*pNtUnmapViewOfSection
)(HANDLE
, PVOID
);
38 static NTSTATUS (WINAPI
*pNtQuerySection
)(HANDLE
, SECTION_INFORMATION_CLASS
, void *, ULONG
, ULONG
*);
39 static PVOID (WINAPI
*pRtlAddVectoredExceptionHandler
)(ULONG
, PVECTORED_EXCEPTION_HANDLER
);
40 static ULONG (WINAPI
*pRtlRemoveVectoredExceptionHandler
)(PVOID
);
41 static BOOL (WINAPI
*pGetProcessDEPPolicy
)(HANDLE
, LPDWORD
, PBOOL
);
42 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
43 static NTSTATUS (WINAPI
*pNtProtectVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
, ULONG
*);
44 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG
, SIZE_T
*, ULONG
, ULONG
);
45 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
47 /* ############################### */
49 static UINT_PTR page_mask
= 0xfff;
50 #define ROUND_SIZE(addr,size) \
51 (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
53 static PIMAGE_NT_HEADERS
image_nt_header(HMODULE module
)
55 IMAGE_NT_HEADERS
*ret
= NULL
;
56 IMAGE_DOS_HEADER
*dos
= (IMAGE_DOS_HEADER
*)module
;
58 if (dos
->e_magic
== IMAGE_DOS_SIGNATURE
)
60 ret
= (IMAGE_NT_HEADERS
*)((char *)dos
+ dos
->e_lfanew
);
61 if (ret
->Signature
!= IMAGE_NT_SIGNATURE
) ret
= NULL
;
66 static HANDLE
create_target_process(const char *arg
)
69 char cmdline
[MAX_PATH
];
70 PROCESS_INFORMATION pi
;
72 STARTUPINFOA si
= { 0 };
75 winetest_get_mainargs( &argv
);
76 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], arg
);
77 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
78 ok(ret
, "error: %u\n", GetLastError());
79 ret
= CloseHandle(pi
.hThread
);
80 ok(ret
, "error %u\n", GetLastError());
84 static void test_VirtualAllocEx(void)
86 const unsigned int alloc_size
= 1<<15;
88 SIZE_T bytes_written
= 0, bytes_read
= 0, i
;
92 MEMORY_BASIC_INFORMATION info
;
95 /* not exported in all windows-versions */
96 if ((!pVirtualAllocEx
) || (!pVirtualFreeEx
)) {
97 win_skip("Virtual{Alloc,Free}Ex not available\n");
101 hProcess
= create_target_process("sleep");
102 ok(hProcess
!= NULL
, "Can't start process\n");
104 SetLastError(0xdeadbeef);
105 addr1
= pVirtualAllocEx(hProcess
, NULL
, alloc_size
, MEM_COMMIT
,
106 PAGE_EXECUTE_READWRITE
);
107 ok(addr1
!= NULL
, "VirtualAllocEx error %u\n", GetLastError());
109 src
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
110 dst
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
111 for (i
= 0; i
< alloc_size
; i
++)
114 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
115 ok(b
&& (bytes_written
== alloc_size
), "%lu bytes written\n",
117 b
= ReadProcessMemory(hProcess
, addr1
, dst
, alloc_size
, &bytes_read
);
118 ok(b
&& (bytes_read
== alloc_size
), "%lu bytes read\n", bytes_read
);
119 ok(!memcmp(src
, dst
, alloc_size
), "Data from remote process differs\n");
121 /* test invalid source buffers */
123 b
= VirtualProtect( src
+ 0x2000, 0x2000, PAGE_NOACCESS
, &old_prot
);
124 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
125 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
126 ok( !b
, "WriteProcessMemory succeeded\n" );
127 ok( GetLastError() == ERROR_NOACCESS
||
128 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
129 "wrong error %u\n", GetLastError() );
130 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
131 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
132 ok( !b
, "ReadProcessMemory succeeded\n" );
133 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
134 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
136 b
= VirtualProtect( src
, 0x2000, PAGE_NOACCESS
, &old_prot
);
137 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
138 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
139 ok( !b
, "WriteProcessMemory succeeded\n" );
140 ok( GetLastError() == ERROR_NOACCESS
||
141 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
142 "wrong error %u\n", GetLastError() );
143 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
144 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
145 ok( !b
, "ReadProcessMemory succeeded\n" );
146 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
147 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
149 b
= pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
);
150 ok(b
!= 0, "VirtualFreeEx, error %u\n", GetLastError());
152 VirtualFree( src
, 0, MEM_RELEASE
);
153 VirtualFree( dst
, 0, MEM_RELEASE
);
156 * The following tests parallel those in test_VirtualAlloc()
159 SetLastError(0xdeadbeef);
160 addr1
= pVirtualAllocEx(hProcess
, 0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
161 ok(addr1
== NULL
, "VirtualAllocEx should fail on zero-sized allocation\n");
162 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
163 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
165 addr1
= pVirtualAllocEx(hProcess
, 0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
166 ok(addr1
!= NULL
, "VirtualAllocEx failed\n");
168 /* test a not committed memory */
169 memset(&info
, 'q', sizeof(info
));
170 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
), "VirtualQueryEx failed\n");
171 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
172 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
173 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
174 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
175 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
176 ok(info
.Protect
== 0, "%x != PAGE_NOACCESS\n", info
.Protect
);
177 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
179 SetLastError(0xdeadbeef);
180 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
181 "VirtualProtectEx should fail on a not committed memory\n");
182 ok(GetLastError() == ERROR_INVALID_ADDRESS
,
183 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
185 addr2
= pVirtualAllocEx(hProcess
, addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
186 ok(addr1
== addr2
, "VirtualAllocEx failed\n");
188 /* test a committed memory */
189 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
),
190 "VirtualQueryEx failed\n");
191 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
192 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
193 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
194 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
195 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
196 /* this time NT reports PAGE_NOACCESS as well */
197 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
198 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
200 /* this should fail, since not the whole range is committed yet */
201 SetLastError(0xdeadbeef);
202 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
203 "VirtualProtectEx should fail on a not committed memory\n");
204 ok(GetLastError() == ERROR_INVALID_ADDRESS
,
205 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
208 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtectEx failed\n");
209 ok(old_prot
== PAGE_NOACCESS
, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
212 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtectEx failed\n");
213 ok(old_prot
== PAGE_READONLY
, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
215 ok(!pVirtualFreeEx(hProcess
, addr1
, 0x10000, 0),
216 "VirtualFreeEx should fail with type 0\n");
217 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
218 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
220 ok(pVirtualFreeEx(hProcess
, addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFreeEx failed\n");
222 /* if the type is MEM_RELEASE, size must be 0 */
223 ok(!pVirtualFreeEx(hProcess
, addr1
, 1, MEM_RELEASE
),
224 "VirtualFreeEx should fail\n");
225 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
226 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
228 ok(pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
), "VirtualFreeEx failed\n");
230 TerminateProcess(hProcess
, 0);
231 CloseHandle(hProcess
);
234 static void test_VirtualAlloc(void)
238 MEMORY_BASIC_INFORMATION info
;
242 SetLastError(0xdeadbeef);
243 addr1
= VirtualAlloc(0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
244 ok(addr1
== NULL
, "VirtualAlloc should fail on zero-sized allocation\n");
245 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
246 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
248 addr1
= VirtualAlloc(0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
249 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
251 /* test a not committed memory */
252 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
253 "VirtualQuery failed\n");
254 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
255 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
256 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
257 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
258 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
259 ok(info
.Protect
== 0, "%x != PAGE_NOACCESS\n", info
.Protect
);
260 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
262 SetLastError(0xdeadbeef);
263 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
264 "VirtualProtect should fail on a not committed memory\n");
265 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
266 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
268 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
269 ok(addr1
== addr2
, "VirtualAlloc failed\n");
271 /* test a committed memory */
272 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
273 "VirtualQuery failed\n");
274 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
275 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
276 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
277 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
278 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
279 /* this time NT reports PAGE_NOACCESS as well */
280 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
281 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
283 /* this should fail, since not the whole range is committed yet */
284 SetLastError(0xdeadbeef);
285 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
286 "VirtualProtect should fail on a not committed memory\n");
287 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
288 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
290 ok(VirtualProtect(addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtect failed\n");
291 ok(old_prot
== PAGE_NOACCESS
,
292 "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
294 ok(VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtect failed\n");
295 ok(old_prot
== PAGE_READONLY
,
296 "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
298 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
299 "VirtualQuery failed\n");
300 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
301 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
302 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
303 memset( addr1
, 0x55, 20 );
304 ok( *(DWORD
*)addr1
== 0x55555555, "wrong data %x\n", *(DWORD
*)addr1
);
306 addr2
= VirtualAlloc( addr1
, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
307 ok( addr2
== addr1
, "VirtualAlloc failed err %u\n", GetLastError() );
308 ok( *(DWORD
*)addr1
== 0x55555555 || *(DWORD
*)addr1
== 0, "wrong data %x\n", *(DWORD
*)addr1
);
309 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
310 "VirtualQuery failed\n");
311 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
312 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
313 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
315 addr2
= VirtualAlloc( (char *)addr1
+ 0x1000, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
316 ok( (char *)addr2
== (char *)addr1
+ 0x1000, "VirtualAlloc failed\n" );
318 ok(VirtualQuery(addr2
, &info
, sizeof(info
)) == sizeof(info
),
319 "VirtualQuery failed\n");
320 ok(info
.RegionSize
== 0xf000, "%lx != 0xf000\n", info
.RegionSize
);
321 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
322 ok(info
.Protect
== 0, "%x != 0\n", info
.Protect
);
324 addr2
= VirtualAlloc( (char *)addr1
+ 0xf000, 0x2000, MEM_RESET
, PAGE_NOACCESS
);
325 ok( !addr2
, "VirtualAlloc failed\n" );
326 ok( GetLastError() == ERROR_INVALID_ADDRESS
, "wrong error %u\n", GetLastError() );
328 /* invalid protection values */
329 SetLastError(0xdeadbeef);
330 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_RESERVE
, 0);
331 ok(!addr2
, "VirtualAlloc succeeded\n");
332 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
334 SetLastError(0xdeadbeef);
335 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_COMMIT
, 0);
336 ok(!addr2
, "VirtualAlloc succeeded\n");
337 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
339 SetLastError(0xdeadbeef);
340 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_READONLY
| PAGE_EXECUTE
);
341 ok(!addr2
, "VirtualAlloc succeeded\n");
342 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
344 SetLastError(0xdeadbeef);
345 ok(!VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
| PAGE_EXECUTE_WRITECOPY
, &old_prot
),
346 "VirtualProtect succeeded\n");
347 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
349 SetLastError(0xdeadbeef);
350 ok(!VirtualProtect(addr1
, 0x1000, 0, &old_prot
), "VirtualProtect succeeded\n");
351 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
353 SetLastError(0xdeadbeef);
354 ok(!VirtualFree(addr1
, 0x10000, 0), "VirtualFree should fail with type 0\n");
355 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
356 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
358 SetLastError(0xdeadbeef);
359 ok(!VirtualFree(addr1
, 0, MEM_FREE
), "VirtualFree should fail with type MEM_FREE\n");
360 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
361 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
363 ok(VirtualFree(addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFree failed\n");
365 /* if the type is MEM_RELEASE, size must be 0 */
366 ok(!VirtualFree(addr1
, 1, MEM_RELEASE
), "VirtualFree should fail\n");
367 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
368 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
370 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
372 /* memory returned by VirtualAlloc should be aligned to 64k */
373 addr1
= VirtualAlloc(0, 0x2000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
374 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
375 ok(!((ULONG_PTR
)addr1
& 0xffff), "returned memory %p is not aligned to 64k\n", addr1
);
376 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
377 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
378 ok(addr2
== addr1
, "VirtualAlloc returned %p, expected %p\n", addr2
, addr1
);
380 /* allocation conflicts because of 64k align */
382 addr2
= (char *)addr1
+ 0x1000;
383 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
,
384 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
385 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
387 /* it should conflict, even when zero_bits is explicitly set */
389 addr2
= (char *)addr1
+ 0x1000;
390 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 12, &size
,
391 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
393 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
394 if (status
== STATUS_SUCCESS
) ok(VirtualFree(addr2
, 0, MEM_RELEASE
), "VirtualFree failed\n");
396 /* 21 zero bits is valid */
399 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 21, &size
,
400 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
401 ok(status
== STATUS_SUCCESS
|| status
== STATUS_NO_MEMORY
,
402 "NtAllocateVirtualMemory returned %08x\n", status
);
403 if (status
== STATUS_SUCCESS
) ok(VirtualFree(addr2
, 0, MEM_RELEASE
), "VirtualFree failed\n");
405 /* 22 zero bits is invalid */
408 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 22, &size
,
409 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
410 ok(status
== STATUS_INVALID_PARAMETER_3
, "NtAllocateVirtualMemory returned %08x\n", status
);
411 if (status
== STATUS_SUCCESS
) ok(VirtualFree(addr2
, 0, MEM_RELEASE
), "VirtualFree failed\n");
413 /* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
414 SetLastError(0xdeadbeef);
415 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_RESERVE
| MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
416 ok(!addr2
, "VirtualAlloc unexpectedly succeeded\n");
417 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
419 /* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
421 addr2
= (char *)addr1
+ 0x1000;
422 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
, MEM_RESERVE
|
423 MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
425 ok(status
== STATUS_INVALID_PARAMETER_5
, "NtAllocateVirtualMemory returned %08x\n", status
);
427 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
430 static void test_MapViewOfFile(void)
432 static const char testfile
[] = "testfile.xxx";
434 HANDLE file
, mapping
, map2
;
435 void *ptr
, *ptr2
, *addr
;
436 SECTION_BASIC_INFORMATION section_info
;
437 SECTION_IMAGE_INFORMATION image_info
;
438 MEMORY_BASIC_INFORMATION info
;
443 LARGE_INTEGER map_size
;
445 SetLastError(0xdeadbeef);
446 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
447 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
448 SetFilePointer( file
, 12288, NULL
, FILE_BEGIN
);
449 SetEndOfFile( file
);
451 /* read/write mapping */
453 SetLastError(0xdeadbeef);
454 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
455 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
457 SetLastError(0xdeadbeef);
458 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
459 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
460 UnmapViewOfFile( ptr
);
462 SetLastError(0xdeadbeef);
463 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
464 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
465 UnmapViewOfFile( ptr
);
467 SetLastError(0xdeadbeef);
468 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
469 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
470 UnmapViewOfFile( ptr
);
472 SetLastError(0xdeadbeef);
473 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
474 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
475 UnmapViewOfFile( ptr
);
477 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
478 FILE_MAP_READ
|FILE_MAP_WRITE
, FALSE
, 0 );
479 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
480 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
481 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
482 UnmapViewOfFile( ptr
);
485 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
486 FILE_MAP_READ
, FALSE
, 0 );
487 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
488 SetLastError(0xdeadbeef);
489 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
490 ok( !ptr
, "MapViewOfFile succeeded\n" );
491 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
493 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
, 0, FALSE
, 0 );
494 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
495 SetLastError(0xdeadbeef);
496 ptr
= MapViewOfFile( map2
, 0, 0, 0, 4096 );
497 ok( !ptr
, "MapViewOfFile succeeded\n" );
498 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
500 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
501 FILE_MAP_READ
, FALSE
, 0 );
502 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
503 ptr
= MapViewOfFile( map2
, 0, 0, 0, 4096 );
504 ok( ptr
!= NULL
, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
506 UnmapViewOfFile( ptr
);
508 CloseHandle( mapping
);
510 /* read-only mapping */
512 SetLastError(0xdeadbeef);
513 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
514 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
516 SetLastError(0xdeadbeef);
517 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
518 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
519 UnmapViewOfFile( ptr
);
521 SetLastError(0xdeadbeef);
522 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
523 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
524 UnmapViewOfFile( ptr
);
526 SetLastError(0xdeadbeef);
527 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
528 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
529 UnmapViewOfFile( ptr
);
531 SetLastError(0xdeadbeef);
532 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
533 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
534 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
535 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
536 CloseHandle( mapping
);
538 /* copy-on-write mapping */
540 SetLastError(0xdeadbeef);
541 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
542 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
544 SetLastError(0xdeadbeef);
545 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
546 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
547 UnmapViewOfFile( ptr
);
549 SetLastError(0xdeadbeef);
550 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
551 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
552 UnmapViewOfFile( ptr
);
554 SetLastError(0xdeadbeef);
555 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
556 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
557 UnmapViewOfFile( ptr
);
559 SetLastError(0xdeadbeef);
560 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
561 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
562 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
563 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
564 CloseHandle( mapping
);
566 /* no access mapping */
568 SetLastError(0xdeadbeef);
569 mapping
= CreateFileMappingA( file
, NULL
, PAGE_NOACCESS
, 0, 4096, NULL
);
570 ok( !mapping
, "CreateFileMappingA succeeded\n" );
571 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
574 /* now try read-only file */
576 SetLastError(0xdeadbeef);
577 file
= CreateFileA( testfile
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0 );
578 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
580 SetLastError(0xdeadbeef);
581 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
582 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
583 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
584 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
586 SetLastError(0xdeadbeef);
587 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
588 ok( mapping
!= 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
589 CloseHandle( mapping
);
591 SetLastError(0xdeadbeef);
592 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
593 ok( mapping
!= 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
594 CloseHandle( mapping
);
597 /* now try no access file */
599 SetLastError(0xdeadbeef);
600 file
= CreateFileA( testfile
, 0, 0, NULL
, OPEN_EXISTING
, 0, 0 );
601 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
603 SetLastError(0xdeadbeef);
604 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
605 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
606 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
607 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
609 SetLastError(0xdeadbeef);
610 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
611 ok( !mapping
, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
612 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
613 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
615 SetLastError(0xdeadbeef);
616 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
617 ok( !mapping
, "CreateFileMapping PAGE_READONLY succeeded\n" );
618 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
619 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
622 DeleteFileA( testfile
);
624 SetLastError(0xdeadbeef);
626 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4090, name
);
627 /* nt4 doesn't have Local\\ */
628 if (!file
&& GetLastError() == ERROR_PATH_NOT_FOUND
)
631 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4090, name
);
633 ok( file
!= 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
635 SetLastError(0xdeadbeef);
636 mapping
= OpenFileMappingA( FILE_MAP_READ
, FALSE
, name
);
637 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
638 SetLastError(0xdeadbeef);
639 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
640 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
641 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
642 SetLastError(0xdeadbeef);
643 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
644 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
645 SetLastError(0xdeadbeef);
646 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
647 ok( size
== sizeof(info
),
648 "VirtualQuery error %u\n", GetLastError() );
649 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
650 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
651 ok( info
.AllocationProtect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.AllocationProtect
);
652 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
653 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
654 ok( info
.Protect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.Protect
);
655 UnmapViewOfFile( ptr
);
656 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
657 sizeof(section_info
), &info_size
);
658 ok( status
== STATUS_ACCESS_DENIED
, "NtQuerySection failed err %x\n", status
);
659 CloseHandle( mapping
);
660 mapping
= OpenFileMappingA( FILE_MAP_READ
| SECTION_QUERY
, FALSE
, name
);
661 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
662 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
663 sizeof(section_info
), &info_size
);
664 ok( !status
, "NtQuerySection failed err %x\n", status
);
665 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
666 ok( section_info
.Attributes
== SEC_COMMIT
, "NtQuerySection wrong attr %08x\n",
667 section_info
.Attributes
);
668 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
669 ok( section_info
.Size
.QuadPart
== info
.RegionSize
, "NtQuerySection wrong size %x%08x / %08lx\n",
670 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
, info
.RegionSize
);
671 CloseHandle( mapping
);
673 SetLastError(0xdeadbeef);
674 mapping
= OpenFileMappingA( FILE_MAP_WRITE
, FALSE
, name
);
675 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
676 SetLastError(0xdeadbeef);
677 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
678 ok( !ptr
, "MapViewOfFile succeeded\n" );
679 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
680 SetLastError(0xdeadbeef);
681 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
682 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
683 SetLastError(0xdeadbeef);
684 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
685 ok( size
== sizeof(info
),
686 "VirtualQuery error %u\n", GetLastError() );
687 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
688 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
689 ok( info
.AllocationProtect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.AllocationProtect
);
690 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
691 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
692 ok( info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
693 UnmapViewOfFile( ptr
);
694 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
695 sizeof(section_info
), &info_size
);
696 ok( status
== STATUS_ACCESS_DENIED
, "NtQuerySection failed err %x\n", status
);
697 CloseHandle( mapping
);
699 mapping
= OpenFileMappingA( FILE_MAP_WRITE
| SECTION_QUERY
, FALSE
, name
);
700 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
701 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
702 sizeof(section_info
), &info_size
);
703 ok( !status
, "NtQuerySection failed err %x\n", status
);
704 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
705 ok( section_info
.Attributes
== SEC_COMMIT
, "NtQuerySection wrong attr %08x\n",
706 section_info
.Attributes
);
707 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
708 ok( section_info
.Size
.QuadPart
== info
.RegionSize
, "NtQuerySection wrong size %x%08x / %08lx\n",
709 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
, info
.RegionSize
);
710 CloseHandle( mapping
);
714 /* read/write mapping with SEC_RESERVE */
715 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
| SEC_RESERVE
, 0, MAPPING_SIZE
, NULL
);
716 ok(mapping
!= INVALID_HANDLE_VALUE
, "CreateFileMappingA failed with error %d\n", GetLastError());
717 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
718 sizeof(section_info
), NULL
);
719 ok( !status
, "NtQuerySection failed err %x\n", status
);
720 ok( section_info
.Attributes
== SEC_RESERVE
, "NtQuerySection wrong attr %08x\n",
721 section_info
.Attributes
);
722 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
723 ok( section_info
.Size
.QuadPart
== MAPPING_SIZE
, "NtQuerySection wrong size %x%08x / %08x\n",
724 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
, MAPPING_SIZE
);
726 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
727 ok(ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
729 ptr2
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
730 ok( ptr2
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
731 ok( ptr
!= ptr2
, "MapViewOfFile returned same pointer\n" );
733 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
734 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
735 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
736 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
737 ok(info
.RegionSize
== MAPPING_SIZE
, "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
738 ok(info
.State
== MEM_RESERVE
, "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
739 ok(info
.AllocationProtect
== PAGE_READWRITE
,
740 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
741 ok(info
.Protect
== 0, "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
742 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
744 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
745 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
746 ok(info
.BaseAddress
== ptr2
,
747 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
748 ok(info
.AllocationBase
== ptr2
,
749 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
750 ok(info
.AllocationProtect
== PAGE_READWRITE
,
751 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
752 ok(info
.RegionSize
== MAPPING_SIZE
,
753 "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
754 ok(info
.State
== MEM_RESERVE
, "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
755 ok(info
.Protect
== 0, "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
756 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
758 ptr
= VirtualAlloc(ptr
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
759 ok(ptr
!= NULL
, "VirtualAlloc failed with error %d\n", GetLastError());
761 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
762 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
763 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
764 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
765 ok(info
.RegionSize
== 0x10000, "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
766 ok(info
.State
== MEM_COMMIT
, "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
767 ok(info
.Protect
== PAGE_READONLY
, "Protect should have been PAGE_READONLY instead of 0x%x\n", info
.Protect
);
768 ok(info
.AllocationProtect
== PAGE_READWRITE
,
769 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
770 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
772 /* shows that the VirtualAlloc above affects the mapping, not just the
773 * virtual memory in this process - it also affects all other processes
774 * with a view of the mapping, but that isn't tested here */
775 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
776 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
777 ok(info
.BaseAddress
== ptr2
,
778 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
779 ok(info
.AllocationBase
== ptr2
,
780 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
781 ok(info
.AllocationProtect
== PAGE_READWRITE
,
782 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
783 ok(info
.RegionSize
== 0x10000,
784 "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
785 ok(info
.State
== MEM_COMMIT
,
786 "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
787 ok(info
.Protect
== PAGE_READWRITE
,
788 "Protect should have been PAGE_READWRITE instead of 0x%x\n", info
.Protect
);
789 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
791 addr
= VirtualAlloc( ptr
, MAPPING_SIZE
, MEM_RESET
, PAGE_READONLY
);
792 ok( addr
== ptr
, "VirtualAlloc failed with error %u\n", GetLastError() );
794 ret
= VirtualFree( ptr
, 0x10000, MEM_DECOMMIT
);
795 ok( !ret
, "VirtualFree succeeded\n" );
796 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "VirtualFree failed with %u\n", GetLastError() );
798 ret
= UnmapViewOfFile(ptr2
);
799 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
800 ret
= UnmapViewOfFile(ptr
);
801 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
802 CloseHandle(mapping
);
804 addr
= VirtualAlloc(NULL
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
805 ok( addr
!= NULL
, "VirtualAlloc failed with error %u\n", GetLastError() );
807 SetLastError(0xdeadbeef);
808 ok( !UnmapViewOfFile(addr
), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
809 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
810 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
811 SetLastError(0xdeadbeef);
812 ok( !UnmapViewOfFile((char *)addr
+ 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
813 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
814 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
815 SetLastError(0xdeadbeef);
816 ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
817 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
818 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
820 ok( VirtualFree(addr
, 0, MEM_RELEASE
), "VirtualFree failed\n" );
822 /* close named mapping handle without unmapping */
824 SetLastError(0xdeadbeef);
825 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
826 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
827 SetLastError(0xdeadbeef);
828 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
829 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
830 SetLastError(0xdeadbeef);
831 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
832 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
833 SetLastError(0xdeadbeef);
834 ret
= CloseHandle(map2
);
835 ok(ret
, "CloseHandle error %d\n", GetLastError());
836 SetLastError(0xdeadbeef);
837 ret
= CloseHandle(mapping
);
838 ok(ret
, "CloseHandle error %d\n", GetLastError());
840 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
841 ok( !ret
, "memory is not accessible\n" );
843 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
844 ok(ret
, "VirtualQuery error %d\n", GetLastError());
845 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
846 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
847 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
848 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
849 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
850 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
851 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
853 SetLastError(0xdeadbeef);
854 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
856 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
858 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
859 if (map2
) CloseHandle(map2
); /* FIXME: remove once Wine is fixed */
860 SetLastError(0xdeadbeef);
861 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
862 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
864 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set error %d\n", GetLastError() );
865 SetLastError(0xdeadbeef);
866 ret
= CloseHandle(mapping
);
867 ok(ret
, "CloseHandle error %d\n", GetLastError());
869 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
870 ok( !ret
, "memory is not accessible\n" );
872 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
873 ok(ret
, "VirtualQuery error %d\n", GetLastError());
874 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
875 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
876 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
877 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
878 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
879 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
880 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
882 SetLastError(0xdeadbeef);
883 ret
= UnmapViewOfFile(ptr
);
884 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
886 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
887 ok( ret
, "memory is accessible\n" );
889 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
890 ok(ret
, "VirtualQuery error %d\n", GetLastError());
891 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
892 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
893 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
894 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
895 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
896 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
898 SetLastError(0xdeadbeef);
899 file
= CreateFileA(testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
900 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
901 SetFilePointer(file
, 4096, NULL
, FILE_BEGIN
);
904 SetLastError(0xdeadbeef);
905 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
906 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
907 SetLastError(0xdeadbeef);
908 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
909 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
910 SetLastError(0xdeadbeef);
911 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
912 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
913 SetLastError(0xdeadbeef);
914 ret
= CloseHandle(map2
);
915 ok(ret
, "CloseHandle error %d\n", GetLastError());
916 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
917 sizeof(section_info
), &info_size
);
918 ok( !status
, "NtQuerySection failed err %x\n", status
);
919 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
920 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
921 section_info
.Attributes
);
922 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
923 ok( section_info
.Size
.QuadPart
== MAPPING_SIZE
, "NtQuerySection wrong size %x%08x\n",
924 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
925 SetLastError(0xdeadbeef);
926 ret
= CloseHandle(mapping
);
927 ok(ret
, "CloseHandle error %d\n", GetLastError());
929 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
930 ok( !ret
, "memory is not accessible\n" );
932 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
933 ok(ret
, "VirtualQuery error %d\n", GetLastError());
934 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
935 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
936 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
937 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
938 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
939 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
940 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
942 SetLastError(0xdeadbeef);
943 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
945 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
947 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
949 SetLastError(0xdeadbeef);
950 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
951 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
953 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set 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 ret
= UnmapViewOfFile(ptr
);
973 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
975 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
976 ok( ret
, "memory is accessible\n" );
978 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
979 ok(ret
, "VirtualQuery error %d\n", GetLastError());
980 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
981 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
982 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
983 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
984 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
985 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
987 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 12288, NULL
);
988 ok( mapping
!= NULL
, "CreateFileMappingA failed with error %u\n", GetLastError() );
990 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 12288 );
991 ok( ptr
!= NULL
, "MapViewOfFile failed with error %u\n", GetLastError() );
993 ret
= UnmapViewOfFile( (char *)ptr
+ 100 );
994 ok( ret
, "UnmapViewOfFile failed with error %u\n", GetLastError() );
996 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 12288 );
997 ok( ptr
!= NULL
, "MapViewOfFile failed with error %u\n", GetLastError() );
999 ret
= UnmapViewOfFile( (char *)ptr
+ 4096 );
1000 ok( ret
, "UnmapViewOfFile failed with error %u\n", GetLastError() );
1002 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 12288 );
1003 ok( ptr
!= NULL
, "MapViewOfFile failed with error %u\n", GetLastError() );
1005 ret
= UnmapViewOfFile( (char *)ptr
+ 4096 + 100 );
1006 ok( ret
, "UnmapViewOfFile failed with error %u\n", GetLastError() );
1008 CloseHandle(mapping
);
1010 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 36, NULL
);
1011 ok( mapping
!= NULL
, "CreateFileMappingA failed with error %u\n", GetLastError() );
1012 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
1013 sizeof(section_info
), &info_size
);
1014 ok( !status
, "NtQuerySection failed err %x\n", status
);
1015 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
1016 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
1017 section_info
.Attributes
);
1018 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
1019 ok( section_info
.Size
.QuadPart
== 36, "NtQuerySection wrong size %x%08x\n",
1020 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
1021 CloseHandle(mapping
);
1023 SetFilePointer(file
, 0x3456, NULL
, FILE_BEGIN
);
1025 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
1026 ok( mapping
!= NULL
, "CreateFileMappingA failed with error %u\n", GetLastError() );
1027 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
1028 sizeof(section_info
), &info_size
);
1029 ok( !status
, "NtQuerySection failed err %x\n", status
);
1030 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
1031 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
1032 section_info
.Attributes
);
1033 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
1034 ok( section_info
.Size
.QuadPart
== 0x3456, "NtQuerySection wrong size %x%08x\n",
1035 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
1036 CloseHandle(mapping
);
1038 map_size
.QuadPart
= 0x3457;
1039 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1040 &map_size
, PAGE_READONLY
, SEC_COMMIT
, file
);
1041 ok( status
== STATUS_SECTION_TOO_BIG
, "NtCreateSection failed %x\n", status
);
1042 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1043 &map_size
, PAGE_READONLY
, SEC_IMAGE
, file
);
1044 ok( status
== STATUS_INVALID_IMAGE_NOT_MZ
, "NtCreateSection failed %x\n", status
);
1045 if (!status
) CloseHandle( mapping
);
1046 map_size
.QuadPart
= 0x3452;
1047 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1048 &map_size
, PAGE_READONLY
, SEC_COMMIT
, file
);
1049 ok( !status
, "NtCreateSection failed %x\n", status
);
1050 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
, sizeof(section_info
), NULL
);
1051 ok( !status
, "NtQuerySection failed err %x\n", status
);
1052 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
1053 section_info
.Attributes
);
1054 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
1055 ok( section_info
.Size
.QuadPart
== 0x3452, "NtQuerySection wrong size %x%08x\n",
1056 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
1057 size
= map_size
.QuadPart
;
1058 status
= pNtMapViewOfSection( mapping
, GetCurrentProcess(), &ptr
, 0, 0, NULL
,
1059 &size
, ViewShare
, 0, PAGE_READONLY
);
1060 ok( !status
, "NtMapViewOfSection failed err %x\n", status
);
1061 pNtUnmapViewOfSection( GetCurrentProcess(), ptr
);
1062 size
= map_size
.QuadPart
+ 1;
1063 status
= pNtMapViewOfSection( mapping
, GetCurrentProcess(), &ptr
, 0, 0, NULL
,
1064 &size
, ViewShare
, 0, PAGE_READONLY
);
1065 ok( status
== STATUS_INVALID_VIEW_SIZE
, "NtMapViewOfSection failed err %x\n", status
);
1066 CloseHandle(mapping
);
1068 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1069 &map_size
, PAGE_READONLY
, SEC_COMMIT
, 0 );
1070 ok( !status
, "NtCreateSection failed %x\n", status
);
1071 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
, sizeof(section_info
), NULL
);
1072 ok( !status
, "NtQuerySection failed err %x\n", status
);
1073 ok( section_info
.Attributes
== SEC_COMMIT
, "NtQuerySection wrong attr %08x\n",
1074 section_info
.Attributes
);
1075 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
1076 ok( section_info
.Size
.QuadPart
== 0x4000, "NtQuerySection wrong size %x%08x\n",
1077 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
1078 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
, sizeof(section_info
)-1, NULL
);
1079 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "NtQuerySection failed err %x\n", status
);
1080 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
, sizeof(section_info
)+1, NULL
);
1081 ok( !status
, "NtQuerySection failed err %x\n", status
);
1082 status
= pNtQuerySection( mapping
, SectionImageInformation
, &image_info
, sizeof(image_info
)-1, NULL
);
1083 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "NtQuerySection failed err %x\n", status
);
1084 status
= pNtQuerySection( mapping
, SectionImageInformation
, &image_info
, sizeof(image_info
), NULL
);
1085 ok( status
== STATUS_SECTION_NOT_IMAGE
, "NtQuerySection failed err %x\n", status
);
1086 status
= pNtQuerySection( mapping
, SectionImageInformation
, &image_info
, sizeof(image_info
)+1, NULL
);
1087 ok( status
== STATUS_SECTION_NOT_IMAGE
, "NtQuerySection failed err %x\n", status
);
1088 CloseHandle(mapping
);
1090 SetFilePointer(file
, 0, NULL
, FILE_BEGIN
);
1092 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1093 NULL
, PAGE_READONLY
, SEC_COMMIT
, file
);
1094 ok( status
== STATUS_MAPPED_FILE_SIZE_ZERO
, "NtCreateSection failed %x\n", status
);
1095 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1096 NULL
, PAGE_READONLY
, SEC_IMAGE
, file
);
1097 ok( status
== STATUS_INVALID_FILE_FOR_SECTION
, "NtCreateSection failed %x\n", status
);
1100 DeleteFileA(testfile
);
1103 static void test_NtMapViewOfSection(void)
1107 static const char testfile
[] = "testfile.xxx";
1108 static const char data
[] = "test data for NtMapViewOfSection";
1109 char buffer
[sizeof(data
)];
1110 HANDLE file
, mapping
;
1113 DWORD status
, written
;
1114 SIZE_T size
, result
;
1115 LARGE_INTEGER offset
;
1117 if (!pNtMapViewOfSection
|| !pNtUnmapViewOfSection
)
1119 win_skip( "NtMapViewOfSection not available\n" );
1123 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1124 ok( file
!= INVALID_HANDLE_VALUE
, "Failed to create test file\n" );
1125 WriteFile( file
, data
, sizeof(data
), &written
, NULL
);
1126 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1127 SetEndOfFile( file
);
1129 /* read/write mapping */
1131 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1132 ok( mapping
!= 0, "CreateFileMapping failed\n" );
1134 hProcess
= create_target_process("sleep");
1135 ok(hProcess
!= NULL
, "Can't start process\n");
1139 offset
.QuadPart
= 0;
1140 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1141 ok( !status
, "NtMapViewOfSection failed status %x\n", status
);
1142 ok( !((ULONG_PTR
)ptr
& 0xffff), "returned memory %p is not aligned to 64k\n", ptr
);
1144 ret
= ReadProcessMemory( hProcess
, ptr
, buffer
, sizeof(buffer
), &result
);
1145 ok( ret
, "ReadProcessMemory failed\n" );
1146 ok( result
== sizeof(buffer
), "ReadProcessMemory didn't read all data (%lx)\n", result
);
1147 ok( !memcmp( buffer
, data
, sizeof(buffer
) ), "Wrong data read\n" );
1149 /* for some unknown reason NtMapViewOfSection fails with STATUS_NO_MEMORY when zero_bits != 0 ? */
1152 offset
.QuadPart
= 0;
1153 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1155 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1156 if (status
== STATUS_SUCCESS
)
1158 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1159 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1164 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1166 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1167 if (status
== STATUS_SUCCESS
)
1169 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1170 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1173 /* 22 zero bits isn't acceptable */
1176 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 22, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1177 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1178 if (status
== STATUS_SUCCESS
)
1180 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1181 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1184 /* mapping at the same page conflicts */
1187 offset
.QuadPart
= 0;
1188 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1189 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1191 /* offset has to be aligned */
1194 offset
.QuadPart
= 1;
1195 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1196 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1198 /* ptr has to be aligned */
1199 ptr2
= (char *)ptr
+ 42;
1201 offset
.QuadPart
= 0;
1202 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1203 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1205 /* still not 64k aligned */
1206 ptr2
= (char *)ptr
+ 0x1000;
1208 offset
.QuadPart
= 0;
1209 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1210 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1212 /* zero_bits != 0 is not allowed when an address is set */
1213 ptr2
= (char *)ptr
+ 0x1000;
1215 offset
.QuadPart
= 0;
1216 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1217 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1219 ptr2
= (char *)ptr
+ 0x1000;
1221 offset
.QuadPart
= 0;
1222 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1223 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1225 ptr2
= (char *)ptr
+ 0x1001;
1227 offset
.QuadPart
= 0;
1228 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1229 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1231 ptr2
= (char *)ptr
+ 0x1000;
1233 offset
.QuadPart
= 1;
1234 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1235 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1237 if (sizeof(void *) == sizeof(int) && (!pIsWow64Process
||
1238 !pIsWow64Process( GetCurrentProcess(), &is_wow64
) || !is_wow64
))
1240 /* new memory region conflicts with previous mapping */
1243 offset
.QuadPart
= 0;
1244 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1245 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1246 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1248 ptr2
= (char *)ptr
+ 42;
1250 offset
.QuadPart
= 0;
1251 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1252 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1253 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1255 /* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
1256 ptr2
= (char *)ptr
+ 0x1000;
1258 offset
.QuadPart
= 0;
1259 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1260 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1261 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1262 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1263 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1264 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1265 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1267 /* the address is rounded down if not on a page boundary */
1268 ptr2
= (char *)ptr
+ 0x1001;
1270 offset
.QuadPart
= 0;
1271 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1272 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1273 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1274 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1275 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1276 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1277 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1279 ptr2
= (char *)ptr
+ 0x2000;
1281 offset
.QuadPart
= 0;
1282 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1283 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1284 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1285 ok( (char *)ptr2
== (char *)ptr
+ 0x2000,
1286 "expected address %p, got %p\n", (char *)ptr
+ 0x2000, ptr2
);
1287 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1288 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1292 ptr2
= (char *)ptr
+ 0x1000;
1294 offset
.QuadPart
= 0;
1295 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1296 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1298 ok( status
== STATUS_INVALID_PARAMETER_9
, "NtMapViewOfSection returned %x\n", status
);
1301 status
= pNtUnmapViewOfSection( hProcess
, ptr
);
1302 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1304 CloseHandle( mapping
);
1305 CloseHandle( file
);
1306 DeleteFileA( testfile
);
1308 TerminateProcess(hProcess
, 0);
1309 CloseHandle(hProcess
);
1312 static void test_NtAreMappedFilesTheSame(void)
1314 static const char testfile
[] = "testfile.xxx";
1315 HANDLE file
, file2
, mapping
, map2
;
1318 char path
[MAX_PATH
];
1320 if (!pNtAreMappedFilesTheSame
)
1322 win_skip( "NtAreMappedFilesTheSame not available\n" );
1326 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1327 NULL
, CREATE_ALWAYS
, 0, 0 );
1328 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1329 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1330 SetEndOfFile( file
);
1332 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1333 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1335 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1336 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1338 file2
= CreateFileA( testfile
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1339 NULL
, OPEN_EXISTING
, 0, 0 );
1340 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1342 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1343 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1344 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1345 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1346 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1347 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1348 UnmapViewOfFile( ptr2
);
1350 ptr2
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1351 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1352 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1353 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1354 UnmapViewOfFile( ptr2
);
1355 CloseHandle( map2
);
1357 map2
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1358 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1359 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1360 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1361 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1362 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1363 UnmapViewOfFile( ptr2
);
1364 CloseHandle( map2
);
1365 CloseHandle( file2
);
1367 status
= pNtAreMappedFilesTheSame( ptr
, ptr
);
1368 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1369 "NtAreMappedFilesTheSame returned %x\n", status
);
1371 status
= pNtAreMappedFilesTheSame( ptr
, (char *)ptr
+ 30 );
1372 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1373 "NtAreMappedFilesTheSame returned %x\n", status
);
1375 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1376 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1378 status
= pNtAreMappedFilesTheSame( ptr
, (void *)0xdeadbeef );
1379 ok( status
== STATUS_CONFLICTING_ADDRESSES
|| status
== STATUS_INVALID_ADDRESS
,
1380 "NtAreMappedFilesTheSame returned %x\n", status
);
1382 status
= pNtAreMappedFilesTheSame( ptr
, NULL
);
1383 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1385 status
= pNtAreMappedFilesTheSame( ptr
, (void *)GetProcessHeap() );
1386 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1388 status
= pNtAreMappedFilesTheSame( NULL
, NULL
);
1389 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1391 ptr2
= VirtualAlloc( NULL
, 0x10000, MEM_COMMIT
, PAGE_READWRITE
);
1392 ok( ptr2
!= NULL
, "VirtualAlloc error %u\n", GetLastError() );
1393 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1394 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1395 VirtualFree( ptr2
, 0, MEM_RELEASE
);
1397 UnmapViewOfFile( ptr
);
1398 CloseHandle( mapping
);
1399 CloseHandle( file
);
1401 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
1402 GetModuleHandleA("kernel32.dll") );
1403 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1404 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1405 GetModuleHandleA("kernel32.dll") );
1406 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1407 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1408 (char *)GetModuleHandleA("kernel32.dll") + 4096 );
1409 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1411 GetSystemDirectoryA( path
, MAX_PATH
);
1412 strcat( path
, "\\kernel32.dll" );
1413 file
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1414 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1416 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1417 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1418 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1419 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1420 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1421 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1422 UnmapViewOfFile( ptr
);
1423 CloseHandle( mapping
);
1425 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1426 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1427 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
1428 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1429 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1431 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1433 file2
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1434 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1435 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1436 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1437 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 0 );
1438 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1439 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1440 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1441 UnmapViewOfFile( ptr2
);
1442 CloseHandle( map2
);
1443 CloseHandle( file2
);
1445 UnmapViewOfFile( ptr
);
1446 CloseHandle( mapping
);
1448 CloseHandle( file
);
1449 DeleteFileA( testfile
);
1452 static void test_CreateFileMapping(void)
1454 HANDLE handle
, handle2
;
1456 /* test case sensitivity */
1458 SetLastError(0xdeadbeef);
1459 handle
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1460 "Wine Test Mapping");
1461 ok( handle
!= NULL
, "CreateFileMapping failed with error %u\n", GetLastError());
1462 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1464 SetLastError(0xdeadbeef);
1465 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1466 "Wine Test Mapping");
1467 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1468 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
1469 CloseHandle( handle2
);
1471 SetLastError(0xdeadbeef);
1472 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1473 "WINE TEST MAPPING");
1474 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1475 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1476 CloseHandle( handle2
);
1478 SetLastError(0xdeadbeef);
1479 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "Wine Test Mapping");
1480 ok( handle2
!= NULL
, "OpenFileMapping failed with error %d\n", GetLastError());
1481 CloseHandle( handle2
);
1483 SetLastError(0xdeadbeef);
1484 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "WINE TEST MAPPING");
1485 ok( !handle2
, "OpenFileMapping succeeded\n");
1486 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
1488 CloseHandle( handle
);
1491 static void test_IsBadReadPtr(void)
1494 void *ptr
= (void *)0xdeadbeef;
1497 ret
= IsBadReadPtr(NULL
, 0);
1498 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1500 ret
= IsBadReadPtr(NULL
, 1);
1501 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1503 ret
= IsBadReadPtr(ptr
, 0);
1504 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1506 ret
= IsBadReadPtr(ptr
, 1);
1507 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1509 ret
= IsBadReadPtr(&stackvar
, 0);
1510 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1512 ret
= IsBadReadPtr(&stackvar
, sizeof(char));
1513 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1516 static void test_IsBadWritePtr(void)
1519 void *ptr
= (void *)0xdeadbeef;
1522 ret
= IsBadWritePtr(NULL
, 0);
1523 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1525 ret
= IsBadWritePtr(NULL
, 1);
1526 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1528 ret
= IsBadWritePtr(ptr
, 0);
1529 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1531 ret
= IsBadWritePtr(ptr
, 1);
1532 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1534 ret
= IsBadWritePtr(&stackval
, 0);
1535 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1537 ret
= IsBadWritePtr(&stackval
, sizeof(char));
1538 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1541 static void test_IsBadCodePtr(void)
1544 void *ptr
= (void *)0xdeadbeef;
1547 ret
= IsBadCodePtr(NULL
);
1548 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1550 ret
= IsBadCodePtr(ptr
);
1551 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1553 ret
= IsBadCodePtr((void *)&stackval
);
1554 ok(ret
== FALSE
, "Expected IsBadCodePtr to return FALSE, got %d\n", ret
);
1557 static void test_write_watch(void)
1559 static const char pipename
[] = "\\\\.\\pipe\\test_write_watch_pipe";
1560 static const char testdata
[] = "Hello World";
1561 DWORD ret
, size
, old_prot
, num_bytes
;
1562 MEMORY_BASIC_INFORMATION info
;
1563 HANDLE readpipe
, writepipe
;
1564 OVERLAPPED overlapped
;
1571 if (!pGetWriteWatch
|| !pResetWriteWatch
)
1573 win_skip( "GetWriteWatch not supported\n" );
1578 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1580 (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
1582 win_skip( "MEM_WRITE_WATCH not supported\n" );
1585 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1586 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1587 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1588 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1589 ok( info
.AllocationProtect
== PAGE_READWRITE
, "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1590 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1591 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1592 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1593 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1596 SetLastError( 0xdeadbeef );
1597 ret
= pGetWriteWatch( 0, NULL
, size
, results
, &count
, &pagesize
);
1598 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1599 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
1600 broken( GetLastError() == 0xdeadbeef ), /* win98 */
1601 "wrong error %u\n", GetLastError() );
1603 SetLastError( 0xdeadbeef );
1604 ret
= pGetWriteWatch( 0, GetModuleHandleW(NULL
), size
, results
, &count
, &pagesize
);
1607 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1608 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1612 ok( count
== 0, "wrong count %lu\n", count
);
1615 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1616 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1617 ok( count
== 0, "wrong count %lu\n", count
);
1619 base
[pagesize
+ 1] = 0x44;
1622 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1623 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1624 ok( count
== 1, "wrong count %lu\n", count
);
1625 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1628 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1629 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1630 ok( count
== 1, "wrong count %lu\n", count
);
1631 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1634 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1635 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1636 ok( count
== 0, "wrong count %lu\n", count
);
1638 base
[2*pagesize
+ 3] = 0x11;
1639 base
[4*pagesize
+ 8] = 0x11;
1642 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1643 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1644 ok( count
== 2, "wrong count %lu\n", count
);
1645 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1646 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1649 ret
= pGetWriteWatch( 0, base
+ 3*pagesize
, 2*pagesize
, results
, &count
, &pagesize
);
1650 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1651 ok( count
== 1, "wrong count %lu\n", count
);
1652 ok( results
[0] == base
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1654 ret
= pResetWriteWatch( base
, 3*pagesize
);
1655 ok( !ret
, "pResetWriteWatch failed %u\n", GetLastError() );
1658 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1659 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1660 ok( count
== 1, "wrong count %lu\n", count
);
1661 ok( results
[0] == base
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1663 *(DWORD
*)(base
+ 2*pagesize
- 2) = 0xdeadbeef;
1666 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1667 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1668 ok( count
== 3, "wrong count %lu\n", count
);
1669 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1670 ok( results
[1] == base
+ 2*pagesize
, "wrong result %p\n", results
[1] );
1671 ok( results
[2] == base
+ 4*pagesize
, "wrong result %p\n", results
[2] );
1674 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1675 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1676 ok( count
== 1, "wrong count %lu\n", count
);
1677 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1680 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1681 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1682 ok( count
== 2, "wrong count %lu\n", count
);
1683 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1684 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1686 /* changing protections doesn't affect watches */
1688 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READONLY
, &old_prot
);
1689 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1690 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1692 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1693 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1694 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1695 ok( info
.RegionSize
== 3*pagesize
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1696 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1697 ok( info
.Protect
== PAGE_READONLY
, "wrong Protect 0x%x\n", info
.Protect
);
1699 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READWRITE
, &old_prot
);
1700 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1701 ok( old_prot
== PAGE_READONLY
, "wrong old prot %x\n", old_prot
);
1704 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1705 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1706 ok( count
== 2, "wrong count %lu\n", count
);
1707 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1708 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1710 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1711 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1712 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1713 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1714 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1715 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1717 /* ReadFile should trigger write watches */
1719 memset( &overlapped
, 0, sizeof(overlapped
) );
1720 overlapped
.hEvent
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1722 readpipe
= CreateNamedPipeA( pipename
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_INBOUND
,
1723 PIPE_TYPE_BYTE
| PIPE_WAIT
, 1, 1024, 1024,
1724 NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1725 ok( readpipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipeA failed %u\n", GetLastError() );
1727 success
= ConnectNamedPipe( readpipe
, &overlapped
);
1728 ok( !success
, "ConnectNamedPipe unexpectedly succeeded\n" );
1729 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1731 writepipe
= CreateFileA( pipename
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
1732 ok( writepipe
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %u\n", GetLastError() );
1734 ret
= WaitForSingleObject( overlapped
.hEvent
, 1000 );
1735 ok( ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", ret
);
1737 memset( base
, 0, size
);
1740 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1741 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1742 ok( count
== 16, "wrong count %lu\n", count
);
1744 success
= ReadFile( readpipe
, base
, size
, NULL
, &overlapped
);
1745 ok( !success
, "ReadFile unexpectedly succeeded\n" );
1746 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1749 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1750 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1751 ok( count
== 16, "wrong count %lu\n", count
);
1754 success
= WriteFile( writepipe
, testdata
, sizeof(testdata
), &num_bytes
, NULL
);
1755 ok( success
, "WriteFile failed %u\n", GetLastError() );
1756 ok( num_bytes
== sizeof(testdata
), "wrong number of bytes written\n" );
1759 success
= GetOverlappedResult( readpipe
, &overlapped
, &num_bytes
, TRUE
);
1760 ok( success
, "GetOverlappedResult failed %u\n", GetLastError() );
1761 ok( num_bytes
== sizeof(testdata
), "wrong number of bytes read\n" );
1762 ok( !memcmp( base
, testdata
, sizeof(testdata
)), "didn't receive expected data\n" );
1765 memset( results
, 0, sizeof(results
) );
1766 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1767 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1768 todo_wine
ok( count
== 1, "wrong count %lu\n", count
);
1769 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
1771 CloseHandle( readpipe
);
1772 CloseHandle( writepipe
);
1773 CloseHandle( overlapped
.hEvent
);
1775 /* some invalid parameter tests */
1777 SetLastError( 0xdeadbeef );
1779 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1782 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1783 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1785 SetLastError( 0xdeadbeef );
1786 ret
= pGetWriteWatch( 0, base
, size
, results
, NULL
, &pagesize
);
1787 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1788 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1790 SetLastError( 0xdeadbeef );
1792 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, NULL
);
1793 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1794 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1796 SetLastError( 0xdeadbeef );
1798 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1799 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1800 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1802 SetLastError( 0xdeadbeef );
1804 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1805 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1806 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1808 SetLastError( 0xdeadbeef );
1810 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1811 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1812 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1814 SetLastError( 0xdeadbeef );
1816 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1817 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1818 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1820 SetLastError( 0xdeadbeef );
1822 ret
= pGetWriteWatch( 0, base
, size
* 2, results
, &count
, &pagesize
);
1823 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1824 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1826 SetLastError( 0xdeadbeef );
1828 ret
= pGetWriteWatch( 0, base
+ size
- pagesize
, pagesize
+ 1, results
, &count
, &pagesize
);
1829 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1830 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1832 SetLastError( 0xdeadbeef );
1833 ret
= pResetWriteWatch( base
, 0 );
1834 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1835 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1837 SetLastError( 0xdeadbeef );
1838 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1839 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1840 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1842 else /* win98 is completely different */
1844 SetLastError( 0xdeadbeef );
1846 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1847 ok( ret
== ERROR_INVALID_PARAMETER
, "GetWriteWatch succeeded %u\n", ret
);
1848 ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
1851 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1852 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1855 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1856 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1859 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1860 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1862 ret
= pResetWriteWatch( base
, 0 );
1863 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1865 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1866 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1869 VirtualFree( base
, 0, MEM_RELEASE
);
1871 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1872 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1873 VirtualFree( base
, 0, MEM_RELEASE
);
1875 base
= VirtualAlloc( 0, size
, MEM_WRITE_WATCH
, PAGE_READWRITE
);
1876 ok( !base
, "VirtualAlloc succeeded\n" );
1877 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1879 /* initial protect doesn't matter */
1881 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_NOACCESS
);
1882 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1883 base
= VirtualAlloc( base
, size
, MEM_COMMIT
, PAGE_NOACCESS
);
1884 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1887 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1888 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1889 ok( count
== 0, "wrong count %lu\n", count
);
1891 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_READWRITE
, &old_prot
);
1892 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1893 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
1895 base
[5*pagesize
+ 200] = 3;
1897 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_NOACCESS
, &old_prot
);
1898 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1899 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1902 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1903 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1904 ok( count
== 1, "wrong count %lu\n", count
);
1905 ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1907 ret
= VirtualFree( base
, size
, MEM_DECOMMIT
);
1908 ok( ret
, "VirtualFree failed %u\n", GetLastError() );
1911 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1912 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1913 ok( count
== 1 || broken(count
== 0), /* win98 */
1914 "wrong count %lu\n", count
);
1915 if (count
) ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1917 VirtualFree( base
, 0, MEM_RELEASE
);
1920 #if defined(__i386__) || defined(__x86_64__)
1922 static DWORD WINAPI
stack_commit_func( void *arg
)
1924 volatile char *p
= (char *)&p
;
1926 /* trigger all guard pages, to ensure that the pages are committed */
1927 while (p
>= (char *)NtCurrentTeb()->DeallocationStack
+ 4 * 0x1000)
1933 ok( arg
== (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg
);
1937 static void test_stack_commit(void)
1940 static const char code_call_on_stack
[] = {
1941 0x55, /* pushl %ebp */
1942 0x56, /* pushl %esi */
1943 0x89, 0xe6, /* movl %esp,%esi */
1944 0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */
1945 0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */
1946 0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */
1947 0x83, 0xe0, 0xf0, /* andl $~15,%eax */
1948 0x83, 0xe8, 0x0c, /* subl $12,%eax */
1949 0x89, 0xc4, /* movl %eax,%esp */
1950 0x52, /* pushl %edx */
1951 0x31, 0xed, /* xorl %ebp,%ebp */
1952 0xff, 0xd1, /* call *%ecx */
1953 0x89, 0xf4, /* movl %esi,%esp */
1954 0x5e, /* popl %esi */
1955 0x5d, /* popl %ebp */
1956 0xc2, 0x0c, 0x00 }; /* ret $12 */
1958 static const char code_call_on_stack
[] = {
1959 0x55, /* pushq %rbp */
1960 0x48, 0x89, 0xe5, /* movq %rsp,%rbp */
1961 /* %rcx - func, %rdx - arg, %r8 - stack */
1962 0x48, 0x87, 0xca, /* xchgq %rcx,%rdx */
1963 0x49, 0x83, 0xe0, 0xf0, /* andq $~15,%r8 */
1964 0x49, 0x83, 0xe8, 0x20, /* subq $0x20,%r8 */
1965 0x4c, 0x89, 0xc4, /* movq %r8,%rsp */
1966 0xff, 0xd2, /* callq *%rdx */
1967 0x48, 0x89, 0xec, /* movq %rbp,%rsp */
1968 0x5d, /* popq %rbp */
1971 DWORD (WINAPI
*call_on_stack
)( DWORD (WINAPI
*func
)(void *), void *arg
, void *stack
);
1972 void *old_stack
, *old_stack_base
, *old_stack_limit
;
1973 void *new_stack
, *new_stack_base
;
1976 call_on_stack
= VirtualAlloc( 0, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
1977 ok( call_on_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1978 memcpy( call_on_stack
, code_call_on_stack
, sizeof(code_call_on_stack
) );
1980 /* allocate a new stack, only the first guard page is committed */
1981 new_stack
= VirtualAlloc( 0, 0x400000, MEM_RESERVE
, PAGE_READWRITE
);
1982 ok( new_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1983 new_stack_base
= (char *)new_stack
+ 0x400000;
1984 VirtualAlloc( (char *)new_stack_base
- 0x1000, 0x1000, MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
1986 old_stack
= NtCurrentTeb()->DeallocationStack
;
1987 old_stack_base
= NtCurrentTeb()->Tib
.StackBase
;
1988 old_stack_limit
= NtCurrentTeb()->Tib
.StackLimit
;
1990 NtCurrentTeb()->DeallocationStack
= new_stack
;
1991 NtCurrentTeb()->Tib
.StackBase
= new_stack_base
;
1992 NtCurrentTeb()->Tib
.StackLimit
= new_stack_base
;
1994 result
= call_on_stack( stack_commit_func
, (void *)0xdeadbeef, new_stack_base
);
1996 NtCurrentTeb()->DeallocationStack
= old_stack
;
1997 NtCurrentTeb()->Tib
.StackBase
= old_stack_base
;
1998 NtCurrentTeb()->Tib
.StackLimit
= old_stack_limit
;
2000 ok( result
== 42, "expected 42, got %u\n", result
);
2002 VirtualFree( new_stack
, 0, MEM_RELEASE
);
2003 VirtualFree( call_on_stack
, 0, MEM_RELEASE
);
2006 #endif /* defined(__i386__) || defined(__x86_64__) */
2009 static LONG num_guard_page_calls
;
2011 static DWORD
guard_page_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
2012 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
2014 trace( "exception: %08x flags:%x addr:%p\n",
2015 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
);
2017 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2018 ok( rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
, "ExceptionCode is %08x instead of %08x\n",
2019 rec
->ExceptionCode
, STATUS_GUARD_PAGE_VIOLATION
);
2021 InterlockedIncrement( &num_guard_page_calls
);
2022 *(int *)rec
->ExceptionInformation
[1] += 0x100;
2024 return ExceptionContinueExecution
;
2027 static void test_guard_page(void)
2029 EXCEPTION_REGISTRATION_RECORD frame
;
2030 MEMORY_BASIC_INFORMATION info
;
2031 DWORD ret
, size
, old_prot
;
2032 int *value
, old_value
;
2040 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
2041 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2042 value
= (int *)base
;
2044 /* verify info structure */
2045 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2046 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
2047 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
2048 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
2049 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
2050 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
2051 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
2052 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
2054 /* put some initial value into the memory */
2055 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2056 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2057 ok( old_prot
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong old prot %x\n", old_prot
);
2062 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2063 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2064 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2066 /* test behaviour of VirtualLock - first attempt should fail */
2067 SetLastError( 0xdeadbeef );
2068 success
= VirtualLock( base
, size
);
2069 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
2071 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
2073 success
= VirtualLock( base
, size
);
2075 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2078 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2079 success
= VirtualUnlock( base
, size
);
2080 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2083 /* check info structure again, PAGE_GUARD should be removed now */
2084 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2085 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
2086 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
2087 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
2088 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
2089 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
2091 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
2092 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
2094 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2095 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2097 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2099 /* test directly accessing the memory - we need to setup an exception handler first */
2100 frame
.Handler
= guard_page_handler
;
2101 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2102 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2104 InterlockedExchange( &num_guard_page_calls
, 0 );
2105 InterlockedExchange( &old_value
, *value
); /* exception handler increments value by 0x100 */
2107 ok( old_value
== 0x101, "memory block contains wrong value, expected 0x101, got 0x%x\n", old_value
);
2108 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2110 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2112 /* check info structure again, PAGE_GUARD should be removed now */
2113 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2114 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
2115 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
2117 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2118 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2119 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2121 /* test accessing second integer in memory */
2122 frame
.Handler
= guard_page_handler
;
2123 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2124 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2126 InterlockedExchange( &num_guard_page_calls
, 0 );
2127 old_value
= *(value
+ 1);
2128 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
2129 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
2130 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2132 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2134 success
= VirtualLock( base
, size
);
2135 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2138 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
2139 success
= VirtualUnlock( base
, size
);
2140 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2143 VirtualFree( base
, 0, MEM_RELEASE
);
2145 /* combined guard page / write watch tests */
2146 if (!pGetWriteWatch
|| !pResetWriteWatch
)
2148 win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" );
2152 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
| PAGE_GUARD
);
2153 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
2155 win_skip( "MEM_WRITE_WATCH not supported\n" );
2158 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2159 value
= (int *)base
;
2161 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2162 ok( ret
, "VirtualQuery failed %u\n", GetLastError() );
2163 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
2164 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
2165 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
2166 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
2167 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
2168 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
2171 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
2172 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2173 ok( count
== 0, "wrong count %lu\n", count
);
2175 /* writing to a page should trigger should trigger guard page, even if write watch is set */
2176 frame
.Handler
= guard_page_handler
;
2177 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2178 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2180 InterlockedExchange( &num_guard_page_calls
, 0 );
2183 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2185 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2188 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2189 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2190 ok( count
== 1, "wrong count %lu\n", count
);
2191 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2193 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2194 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2196 /* write watch is triggered from inside of the guard page handler */
2197 frame
.Handler
= guard_page_handler
;
2198 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2199 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2201 InterlockedExchange( &num_guard_page_calls
, 0 );
2202 old_value
= *(value
+ 1); /* doesn't trigger write watch */
2203 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
2204 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2205 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2207 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2210 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2211 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2212 ok( count
== 1, "wrong count %lu\n", count
);
2213 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2215 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2216 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2218 /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */
2219 SetLastError( 0xdeadbeef );
2220 success
= VirtualLock( base
, size
);
2221 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
2223 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
2226 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
2227 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2228 ok( count
== 0, "wrong count %lu\n", count
);
2230 success
= VirtualLock( base
, size
);
2232 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2235 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2236 success
= VirtualUnlock( base
, size
);
2237 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2241 results
[0] = (void *)0xdeadbeef;
2242 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2243 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2245 ok( count
== 1 || broken(count
== 0) /* Windows 8 */, "wrong count %lu\n", count
);
2247 ok( results
[0] == base
|| broken(results
[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results
[0] );
2249 VirtualFree( base
, 0, MEM_RELEASE
);
2252 static LONG num_execute_fault_calls
;
2254 static DWORD
execute_fault_seh_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
2255 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
2257 ULONG flags
= MEM_EXECUTE_OPTION_ENABLE
;
2260 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2261 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2262 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2264 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2265 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
|| rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
,
2266 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec
->ExceptionCode
);
2268 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &flags
, sizeof(flags
), NULL
);
2270 if (rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
)
2273 err
= IsProcessorFeaturePresent( PF_NX_ENABLED
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2274 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2275 (DWORD
)rec
->ExceptionInformation
[0], err
);
2277 InterlockedIncrement( &num_guard_page_calls
);
2279 else if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2284 err
= (flags
& MEM_EXECUTE_OPTION_DISABLE
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2285 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2286 (DWORD
)rec
->ExceptionInformation
[0], err
);
2288 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2289 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2290 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2292 InterlockedIncrement( &num_execute_fault_calls
);
2295 return ExceptionContinueExecution
;
2298 static LONG CALLBACK
execute_fault_vec_handler( EXCEPTION_POINTERS
*ExceptionInfo
)
2300 PEXCEPTION_RECORD rec
= ExceptionInfo
->ExceptionRecord
;
2304 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2305 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2306 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2308 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2309 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
,
2310 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec
->ExceptionCode
);
2312 if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2313 InterlockedIncrement( &num_execute_fault_calls
);
2315 if (rec
->ExceptionInformation
[0] == EXCEPTION_READ_FAULT
)
2316 return EXCEPTION_CONTINUE_SEARCH
;
2318 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2319 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2320 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
2322 return EXCEPTION_CONTINUE_EXECUTION
;
2325 static inline DWORD
send_message_excpt( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2327 EXCEPTION_REGISTRATION_RECORD frame
;
2330 frame
.Handler
= execute_fault_seh_handler
;
2331 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2332 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2334 InterlockedExchange( &num_guard_page_calls
, 0 );
2335 InterlockedExchange( &num_execute_fault_calls
, 0 );
2336 ret
= SendMessageA( hWnd
, uMsg
, wParam
, lParam
);
2338 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2343 static inline DWORD
call_proc_excpt( DWORD (CALLBACK
*code
)(void *), void *arg
)
2345 EXCEPTION_REGISTRATION_RECORD frame
;
2348 frame
.Handler
= execute_fault_seh_handler
;
2349 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2350 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2352 InterlockedExchange( &num_guard_page_calls
, 0 );
2353 InterlockedExchange( &num_execute_fault_calls
, 0 );
2356 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2361 static LRESULT CALLBACK
jmp_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2363 if (uMsg
== WM_USER
)
2366 return DefWindowProcA( hWnd
, uMsg
, wParam
, lParam
);
2369 static LRESULT CALLBACK
atl_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2371 DWORD arg
= (DWORD
)hWnd
;
2372 if (uMsg
== WM_USER
)
2373 ok( arg
== 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg
);
2375 ok( arg
!= 0x11223344, "arg is unexpectedly 0x11223344\n" );
2379 static DWORD CALLBACK
atl5_test_func( void )
2384 static void test_atl_thunk_emulation( ULONG dep_flags
)
2386 static const char code_jmp
[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
2387 static const char code_atl1
[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2388 static const char code_atl2
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2389 static const char code_atl3
[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1};
2390 static const char code_atl4
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
2391 static const char code_atl5
[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04};
2392 static const char cls_name
[] = "atl_thunk_class";
2393 DWORD ret
, size
, old_prot
;
2394 ULONG old_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2395 BOOL success
, restore_flags
= FALSE
;
2403 trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2405 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
), NULL
);
2406 if (old_flags
!= dep_flags
)
2408 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &dep_flags
, sizeof(dep_flags
) );
2409 if (ret
== STATUS_INVALID_INFO_CLASS
) /* Windows 2000 */
2411 win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2414 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2415 restore_flags
= TRUE
;
2419 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
2420 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2422 /* Check result of GetProcessDEPPolicy */
2423 if (!pGetProcessDEPPolicy
)
2424 win_skip( "GetProcessDEPPolicy not supported\n" );
2427 BOOL (WINAPI
*get_dep_policy
)(HANDLE
, LPDWORD
, PBOOL
) = (void *)base
;
2428 BOOL policy_permanent
= 0xdeadbeef;
2429 DWORD policy_flags
= 0xdeadbeef;
2431 /* GetProcessDEPPolicy crashes on Windows when a NULL pointer is passed.
2432 * Moreover this function has a bug on Windows 8, which has the effect that
2433 * policy_permanent is set to the content of the CL register instead of 0,
2434 * when the policy is not permanent. To detect that we use an assembler
2435 * wrapper to call the function. */
2437 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2438 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)pGetProcessDEPPolicy
- (DWORD_PTR
)(base
+ 10);
2440 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2441 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2443 success
= get_dep_policy( GetCurrentProcess(), &policy_flags
, &policy_permanent
);
2444 ok( success
, "GetProcessDEPPolicy failed %u\n", GetLastError() );
2447 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2448 ret
|= PROCESS_DEP_ENABLE
;
2449 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
)
2450 ret
|= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
;
2452 ok( policy_flags
== ret
, "expected policy flags %d, got %d\n", ret
, policy_flags
);
2453 ok( !policy_permanent
|| broken(policy_permanent
== 0x44),
2454 "expected policy permanent FALSE, got %d\n", policy_permanent
);
2457 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2458 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2460 /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
2461 * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
2462 * where it is active, so that application which depend on that still work properly.
2463 * We have no exception handler enabled yet, so give proper EXECUTE permissions to
2464 * prevent crashes while creating the window. */
2466 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2467 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2469 memset( &wc
, 0, sizeof(wc
) );
2470 wc
.cbSize
= sizeof(wc
);
2471 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2472 wc
.hInstance
= GetModuleHandleA( 0 );
2473 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2474 wc
.hbrBackground
= NULL
;
2475 wc
.lpszClassName
= cls_name
;
2476 wc
.lpfnWndProc
= (WNDPROC
)base
;
2477 success
= RegisterClassExA(&wc
) != 0;
2478 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2480 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2481 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2483 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2484 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2486 /* At first try with an instruction which is not recognized as proper ATL thunk
2487 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2488 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2490 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2491 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2493 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2494 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2495 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2496 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !IsProcessorFeaturePresent( PF_NX_ENABLED
))
2498 trace( "DEP hardware support is not available\n" );
2499 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2500 dep_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2502 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2504 trace( "DEP hardware support is available\n" );
2505 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2508 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2510 /* Now a bit more complicated, the page containing the code is protected with
2511 * PAGE_GUARD memory protection. */
2513 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2514 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2516 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2517 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2518 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2519 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2520 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2522 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2524 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2525 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2526 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2527 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2529 /* Now test with a proper ATL thunk instruction. */
2531 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2532 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2534 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2535 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2537 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2538 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2540 /* Try executing with PAGE_READWRITE protection. */
2542 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2543 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2545 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2546 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2547 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2548 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2549 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2551 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2553 /* Now a bit more complicated, the page containing the code is protected with
2554 * PAGE_GUARD memory protection. */
2556 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2557 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2559 /* the same, but with PAGE_GUARD set */
2560 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2561 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2562 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2563 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2564 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2566 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2568 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2569 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2570 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2571 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2573 /* The following test shows that on Windows, even a vectored exception handler
2574 * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */
2576 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !(dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2578 if (pRtlAddVectoredExceptionHandler
&& pRtlRemoveVectoredExceptionHandler
)
2580 PVOID vectored_handler
;
2582 success
= VirtualProtect( base
, size
, PAGE_NOACCESS
, &old_prot
);
2583 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2585 vectored_handler
= pRtlAddVectoredExceptionHandler( TRUE
, &execute_fault_vec_handler
);
2586 ok( vectored_handler
!= 0, "RtlAddVectoredExceptionHandler failed\n" );
2588 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2590 pRtlRemoveVectoredExceptionHandler( vectored_handler
);
2592 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2593 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2596 win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" );
2599 /* Test alternative ATL thunk instructions. */
2601 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2602 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 10);
2604 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2605 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2607 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2608 /* FIXME: we don't check the content of the register ECX yet */
2609 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2610 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2611 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2612 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2614 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2616 memcpy( base
, code_atl3
, sizeof(code_atl3
) );
2617 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2619 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2620 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2622 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2623 /* FIXME: we don't check the content of the registers ECX/EDX yet */
2624 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2625 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2626 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2627 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2629 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2631 memcpy( base
, code_atl4
, sizeof(code_atl4
) );
2632 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2634 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2635 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2637 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2638 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2639 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2640 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2641 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2642 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2643 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2644 ok( num_execute_fault_calls
== 0 || broken(num_execute_fault_calls
== 1) /* Windows XP */,
2645 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2647 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2649 memcpy( base
, code_atl5
, sizeof(code_atl5
) );
2651 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2652 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2654 ret
= (DWORD_PTR
)atl5_test_func
;
2655 ret
= call_proc_excpt( (void *)base
, &ret
- 1 );
2656 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2657 ok( ret
== 44, "call returned wrong result, expected 44, got %d\n", ret
);
2658 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2659 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2660 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2661 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2662 ok( num_execute_fault_calls
== 0 || broken(num_execute_fault_calls
== 1) /* Windows XP */,
2663 "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2665 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2667 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2669 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2670 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2672 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2673 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2675 DestroyWindow( hWnd
);
2677 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2678 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2680 VirtualFree( base
, 0, MEM_RELEASE
);
2682 /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */
2684 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
2685 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
2687 win_skip( "MEM_WRITE_WATCH not supported\n" );
2690 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2693 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2694 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2695 ok( count
== 0, "wrong count %lu\n", count
);
2697 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2698 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2701 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2702 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2703 ok( count
== 1, "wrong count %lu\n", count
);
2704 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2706 /* Create a new window class and associated Window (see above) */
2708 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2709 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2711 memset( &wc
, 0, sizeof(wc
) );
2712 wc
.cbSize
= sizeof(wc
);
2713 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2714 wc
.hInstance
= GetModuleHandleA( 0 );
2715 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2716 wc
.hbrBackground
= NULL
;
2717 wc
.lpszClassName
= cls_name
;
2718 wc
.lpfnWndProc
= (WNDPROC
)base
;
2719 success
= RegisterClassExA(&wc
) != 0;
2720 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2722 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2723 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2725 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2726 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2729 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2730 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2731 ok( count
== 0, "wrong count %lu\n", count
);
2733 /* At first try with an instruction which is not recognized as proper ATL thunk
2734 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2735 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2737 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2738 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2740 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2741 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2742 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2743 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2744 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2746 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2749 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2750 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2751 ok( count
== 0, "wrong count %lu\n", count
);
2753 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2754 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2755 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2756 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2758 /* Now a bit more complicated, the page containing the code is protected with
2759 * PAGE_GUARD memory protection. */
2761 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2762 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2764 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2765 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2766 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2767 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2768 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2770 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2772 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2773 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2774 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2775 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2778 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2779 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2780 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2782 /* Now test with a proper ATL thunk instruction. */
2784 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2785 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2788 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2789 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2790 ok( count
== 1, "wrong count %lu\n", count
);
2791 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2793 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2794 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2796 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2797 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2799 /* Try executing with PAGE_READWRITE protection. */
2801 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2802 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2804 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2805 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2806 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2807 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2808 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2810 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2813 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2814 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2815 ok( count
== 0, "wrong count %lu\n", count
);
2817 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2818 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2819 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2820 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2822 /* Now a bit more complicated, the page containing the code is protected with
2823 * PAGE_GUARD memory protection. */
2825 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2826 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2828 /* the same, but with PAGE_GUARD set */
2829 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2830 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2831 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2832 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2833 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2835 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2837 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2838 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2839 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2840 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2843 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2844 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2845 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2847 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2849 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2850 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2853 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2854 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2855 ok( count
== 1, "wrong count %lu\n", count
);
2856 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2858 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2859 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2861 DestroyWindow( hWnd
);
2863 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2864 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2866 VirtualFree( base
, 0, MEM_RELEASE
);
2871 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
) );
2872 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2876 #endif /* __i386__ */
2878 static void test_VirtualProtect(void)
2880 static const struct test_data
2882 DWORD prot_set
, prot_get
;
2885 { 0, 0 }, /* 0x00 */
2886 { PAGE_NOACCESS
, PAGE_NOACCESS
}, /* 0x01 */
2887 { PAGE_READONLY
, PAGE_READONLY
}, /* 0x02 */
2888 { PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x03 */
2889 { PAGE_READWRITE
, PAGE_READWRITE
}, /* 0x04 */
2890 { PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x05 */
2891 { PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x06 */
2892 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x07 */
2893 { PAGE_WRITECOPY
, 0 }, /* 0x08 */
2894 { PAGE_WRITECOPY
| PAGE_NOACCESS
, 0 }, /* 0x09 */
2895 { PAGE_WRITECOPY
| PAGE_READONLY
, 0 }, /* 0x0a */
2896 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, 0 }, /* 0x0b */
2897 { PAGE_WRITECOPY
| PAGE_READWRITE
, 0 }, /* 0x0c */
2898 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x0d */
2899 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x0e */
2900 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x0f */
2902 { PAGE_EXECUTE
, PAGE_EXECUTE
}, /* 0x10 */
2903 { PAGE_EXECUTE_READ
, PAGE_EXECUTE_READ
}, /* 0x20 */
2904 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x30 */
2905 { PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
2906 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0x50 */
2907 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0x60 */
2908 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x70 */
2909 { PAGE_EXECUTE_WRITECOPY
, 0 }, /* 0x80 */
2910 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, 0 }, /* 0x90 */
2911 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, 0 }, /* 0xa0 */
2912 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0xb0 */
2913 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, 0 }, /* 0xc0 */
2914 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0xd0 */
2915 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0xe0 */
2916 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 } /* 0xf0 */
2919 DWORD ret
, old_prot
, rw_prot
, exec_prot
, i
, j
;
2920 MEMORY_BASIC_INFORMATION info
;
2927 trace("system page size %#x\n", si
.dwPageSize
);
2929 SetLastError(0xdeadbeef);
2930 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_RESERVE
| MEM_COMMIT
, PAGE_NOACCESS
);
2931 ok(base
!= NULL
, "VirtualAlloc failed %d\n", GetLastError());
2933 SetLastError(0xdeadbeef);
2934 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_READONLY
, NULL
);
2935 ok(!ret
, "VirtualProtect should fail\n");
2936 ok(GetLastError() == ERROR_NOACCESS
, "expected ERROR_NOACCESS, got %d\n", GetLastError());
2937 old_prot
= 0xdeadbeef;
2938 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2939 ok(ret
, "VirtualProtect failed %d\n", GetLastError());
2940 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2943 size
= si
.dwPageSize
;
2944 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_READONLY
, NULL
);
2945 ok(status
== STATUS_ACCESS_VIOLATION
, "NtProtectVirtualMemory should fail, got %08x\n", status
);
2947 size
= si
.dwPageSize
;
2948 old_prot
= 0xdeadbeef;
2949 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_NOACCESS
, &old_prot
);
2950 ok(status
== STATUS_SUCCESS
, "NtProtectVirtualMemory should succeed, got %08x\n", status
);
2951 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2953 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
2955 SetLastError(0xdeadbeef);
2956 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2957 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2958 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2959 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2960 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
2961 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2962 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2963 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2964 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2966 old_prot
= 0xdeadbeef;
2967 SetLastError(0xdeadbeef);
2968 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot_set
, &old_prot
);
2971 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2972 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
2974 SetLastError(0xdeadbeef);
2975 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2976 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2977 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2978 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2979 ok(info
.Protect
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_get
);
2980 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2981 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2982 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2983 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2987 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
2988 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
2991 old_prot
= 0xdeadbeef;
2992 SetLastError(0xdeadbeef);
2993 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2994 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2996 ok(old_prot
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_get
);
2998 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
3003 for (i
= 0; i
<= 4; i
++)
3007 for (j
= 0; j
<= 4; j
++)
3009 DWORD prot
= exec_prot
| rw_prot
;
3011 SetLastError(0xdeadbeef);
3012 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, prot
);
3013 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
3015 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
3016 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3020 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
3022 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
3023 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3027 ok(ptr
!= NULL
, "VirtualAlloc(%02x) error %d\n", prot
, GetLastError());
3028 ok(ptr
== base
, "expected %p, got %p\n", base
, ptr
);
3032 SetLastError(0xdeadbeef);
3033 ret
= VirtualProtect(base
, si
.dwPageSize
, prot
, &old_prot
);
3034 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
3036 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
3037 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3041 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
3043 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
3044 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3047 ok(ret
, "VirtualProtect(%02x) error %d\n", prot
, GetLastError());
3053 exec_prot
= 1 << (i
+ 4);
3056 VirtualFree(base
, 0, MEM_RELEASE
);
3059 static BOOL
is_mem_writable(DWORD prot
)
3061 switch (prot
& 0xff)
3063 case PAGE_READWRITE
:
3064 case PAGE_WRITECOPY
:
3065 case PAGE_EXECUTE_READWRITE
:
3066 case PAGE_EXECUTE_WRITECOPY
:
3074 static void test_VirtualAlloc_protection(void)
3076 static const struct test_data
3082 { 0, FALSE
}, /* 0x00 */
3083 { PAGE_NOACCESS
, TRUE
}, /* 0x01 */
3084 { PAGE_READONLY
, TRUE
}, /* 0x02 */
3085 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x03 */
3086 { PAGE_READWRITE
, TRUE
}, /* 0x04 */
3087 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x05 */
3088 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x06 */
3089 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x07 */
3090 { PAGE_WRITECOPY
, FALSE
}, /* 0x08 */
3091 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
}, /* 0x09 */
3092 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
}, /* 0x0a */
3093 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
}, /* 0x0b */
3094 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
}, /* 0x0c */
3095 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x0d */
3096 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x0e */
3097 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x0f */
3099 { PAGE_EXECUTE
, TRUE
}, /* 0x10 */
3100 { PAGE_EXECUTE_READ
, TRUE
}, /* 0x20 */
3101 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x30 */
3102 { PAGE_EXECUTE_READWRITE
, TRUE
}, /* 0x40 */
3103 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0x50 */
3104 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0x60 */
3105 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x70 */
3106 { PAGE_EXECUTE_WRITECOPY
, FALSE
}, /* 0x80 */
3107 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
}, /* 0x90 */
3108 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xa0 */
3109 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0xb0 */
3110 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
}, /* 0xc0 */
3111 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0xd0 */
3112 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xe0 */
3113 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
} /* 0xf0 */
3117 MEMORY_BASIC_INFORMATION info
;
3121 trace("system page size %#x\n", si
.dwPageSize
);
3123 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3125 SetLastError(0xdeadbeef);
3126 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3130 ok(base
!= NULL
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3132 SetLastError(0xdeadbeef);
3133 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3134 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3135 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3136 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3137 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3138 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3139 ok(info
.AllocationProtect
== td
[i
].prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, td
[i
].prot
);
3140 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3141 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
3143 if (is_mem_writable(info
.Protect
))
3147 SetLastError(0xdeadbeef);
3148 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3149 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3150 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3153 SetLastError(0xdeadbeef);
3154 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3155 ok(ptr
== base
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3157 VirtualFree(base
, 0, MEM_RELEASE
);
3161 ok(!base
, "%d: VirtualAlloc should fail\n", i
);
3162 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3167 static void test_CreateFileMapping_protection(void)
3169 static const struct test_data
3173 DWORD prot_after_write
;
3176 { 0, FALSE
, 0 }, /* 0x00 */
3177 { PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x01 */
3178 { PAGE_READONLY
, TRUE
, PAGE_READONLY
}, /* 0x02 */
3179 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x03 */
3180 { PAGE_READWRITE
, TRUE
, PAGE_READWRITE
}, /* 0x04 */
3181 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x05 */
3182 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x06 */
3183 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x07 */
3184 { PAGE_WRITECOPY
, TRUE
, PAGE_READWRITE
}, /* 0x08 */
3185 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x09 */
3186 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0a */
3187 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0b */
3188 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0x0c */
3189 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0d */
3190 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0e */
3191 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0f */
3193 { PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE
}, /* 0x10 */
3194 { PAGE_EXECUTE_READ
, TRUE
, PAGE_EXECUTE_READ
}, /* 0x20 */
3195 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE_READ
}, /* 0x30 */
3196 { PAGE_EXECUTE_READWRITE
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
3197 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x50 */
3198 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0x60 */
3199 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x70 */
3200 { PAGE_EXECUTE_WRITECOPY
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x80 */
3201 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x90 */
3202 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xa0 */
3203 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xb0 */
3204 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0xc0 */
3205 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xd0 */
3206 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xe0 */
3207 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
} /* 0xf0 */
3210 DWORD ret
, i
, alloc_prot
, prot
, old_prot
;
3211 MEMORY_BASIC_INFORMATION info
;
3213 char temp_path
[MAX_PATH
];
3214 char file_name
[MAX_PATH
];
3216 BOOL page_exec_supported
= TRUE
;
3219 trace("system page size %#x\n", si
.dwPageSize
);
3221 GetTempPathA(MAX_PATH
, temp_path
);
3222 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3224 SetLastError(0xdeadbeef);
3225 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3226 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3227 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3228 SetEndOfFile(hfile
);
3230 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3232 SetLastError(0xdeadbeef);
3233 hmap
= CreateFileMappingW(hfile
, NULL
, td
[i
].prot
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3239 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, td
[i
].prot
, GetLastError());
3240 /* NT4 and win2k don't support EXEC on file mappings */
3241 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3243 page_exec_supported
= FALSE
;
3244 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3247 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3248 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3250 page_exec_supported
= FALSE
;
3251 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3255 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, td
[i
].prot
, GetLastError());
3257 base
= MapViewOfFile(hmap
, FILE_MAP_READ
, 0, 0, 0);
3258 ok(base
!= NULL
, "%d: MapViewOfFile failed %d\n", i
, GetLastError());
3260 SetLastError(0xdeadbeef);
3261 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3262 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3263 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3264 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3265 ok(info
.Protect
== PAGE_READONLY
, "%d: got %#x != expected PAGE_READONLY\n", i
, info
.Protect
);
3266 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3267 ok(info
.AllocationProtect
== PAGE_READONLY
, "%d: %#x != PAGE_READONLY\n", i
, info
.AllocationProtect
);
3268 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3269 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3271 if (is_mem_writable(info
.Protect
))
3275 SetLastError(0xdeadbeef);
3276 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3277 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3278 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3281 SetLastError(0xdeadbeef);
3282 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3283 ok(!ptr
, "%d: VirtualAlloc(%02x) should fail\n", i
, td
[i
].prot
);
3284 /* FIXME: remove once Wine is fixed */
3285 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3286 ok(GetLastError() == ERROR_ACCESS_DENIED
, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i
, GetLastError());
3288 SetLastError(0xdeadbeef);
3289 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3290 if (td
[i
].prot
== PAGE_READONLY
|| td
[i
].prot
== PAGE_WRITECOPY
)
3291 ok(ret
, "%d: VirtualProtect(%02x) error %d\n", i
, td
[i
].prot
, GetLastError());
3294 ok(!ret
, "%d: VirtualProtect(%02x) should fail\n", i
, td
[i
].prot
);
3295 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3298 UnmapViewOfFile(base
);
3303 ok(!hmap
, "%d: CreateFileMapping should fail\n", i
);
3304 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3308 if (page_exec_supported
) alloc_prot
= PAGE_EXECUTE_READWRITE
;
3309 else alloc_prot
= PAGE_READWRITE
;
3310 SetLastError(0xdeadbeef);
3311 hmap
= CreateFileMappingW(hfile
, NULL
, alloc_prot
, 0, si
.dwPageSize
, NULL
);
3312 ok(hmap
!= 0, "%d: CreateFileMapping error %d\n", i
, GetLastError());
3314 SetLastError(0xdeadbeef);
3315 base
= MapViewOfFile(hmap
, FILE_MAP_READ
| FILE_MAP_WRITE
| (page_exec_supported
? FILE_MAP_EXECUTE
: 0), 0, 0, 0);
3316 ok(base
!= NULL
, "MapViewOfFile failed %d\n", GetLastError());
3318 old_prot
= 0xdeadbeef;
3319 SetLastError(0xdeadbeef);
3320 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3321 ok(ret
, "VirtualProtect error %d\n", GetLastError());
3322 ok(old_prot
== alloc_prot
, "got %#x != expected %#x\n", old_prot
, alloc_prot
);
3324 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3326 SetLastError(0xdeadbeef);
3327 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3328 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3329 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3330 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3331 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
3332 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3333 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3334 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3335 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3337 old_prot
= 0xdeadbeef;
3338 SetLastError(0xdeadbeef);
3339 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3340 if (td
[i
].success
|| td
[i
].prot
== PAGE_NOACCESS
|| td
[i
].prot
== PAGE_EXECUTE
)
3344 /* win2k and XP don't support EXEC on file mappings */
3345 if (td
[i
].prot
== PAGE_EXECUTE
)
3347 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3350 /* NT4 and win2k don't support EXEC on file mappings */
3351 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3353 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3356 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3357 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3359 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3364 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3365 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
3368 /* looks strange but Windows doesn't do this for PAGE_WRITECOPY */
3369 if (prot
== PAGE_EXECUTE_WRITECOPY
) prot
= PAGE_EXECUTE_READWRITE
;
3371 SetLastError(0xdeadbeef);
3372 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3373 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3374 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3375 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3376 /* FIXME: remove the condition below once Wine is fixed */
3377 todo_wine_if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3378 ok(info
.Protect
== prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, prot
);
3379 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3380 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3381 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3382 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3384 if (is_mem_writable(info
.Protect
))
3388 SetLastError(0xdeadbeef);
3389 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3390 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3391 /* FIXME: remove the condition below once Wine is fixed */
3392 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3393 ok(info
.Protect
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_after_write
);
3398 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
3399 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3403 old_prot
= 0xdeadbeef;
3404 SetLastError(0xdeadbeef);
3405 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3406 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3407 /* FIXME: remove the condition below once Wine is fixed */
3408 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3409 ok(old_prot
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_after_write
);
3412 UnmapViewOfFile(base
);
3416 DeleteFileA(file_name
);
3419 #define ACCESS_READ 0x01
3420 #define ACCESS_WRITE 0x02
3421 #define ACCESS_EXECUTE 0x04
3422 #define ACCESS_WRITECOPY 0x08
3424 static DWORD
page_prot_to_access(DWORD prot
)
3428 case PAGE_READWRITE
:
3429 return ACCESS_READ
| ACCESS_WRITE
;
3432 case PAGE_EXECUTE_READ
:
3433 return ACCESS_READ
| ACCESS_EXECUTE
;
3435 case PAGE_EXECUTE_READWRITE
:
3436 return ACCESS_READ
| ACCESS_WRITE
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3438 case PAGE_EXECUTE_WRITECOPY
:
3439 return ACCESS_READ
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3444 case PAGE_WRITECOPY
:
3452 static BOOL
is_compatible_protection(DWORD map_prot
, DWORD view_prot
, DWORD prot
)
3454 DWORD map_access
, view_access
, prot_access
;
3456 map_access
= page_prot_to_access(map_prot
);
3457 view_access
= page_prot_to_access(view_prot
);
3458 prot_access
= page_prot_to_access(prot
);
3460 if (view_access
== prot_access
) return TRUE
;
3461 if (!view_access
) return FALSE
;
3463 if ((view_access
& prot_access
) != prot_access
) return FALSE
;
3464 if ((map_access
& prot_access
) == prot_access
) return TRUE
;
3469 static DWORD
map_prot_to_access(DWORD prot
)
3473 case PAGE_READWRITE
:
3474 case PAGE_EXECUTE_READWRITE
:
3475 return SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3477 case PAGE_WRITECOPY
:
3479 case PAGE_EXECUTE_READ
:
3480 case PAGE_EXECUTE_WRITECOPY
:
3481 return SECTION_MAP_READ
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3487 static BOOL
is_compatible_access(DWORD map_prot
, DWORD view_prot
)
3489 DWORD access
= map_prot_to_access(map_prot
);
3490 if (!view_prot
) view_prot
= SECTION_MAP_READ
;
3491 return (view_prot
& access
) == view_prot
;
3494 static void *map_view_of_file(HANDLE handle
, DWORD access
)
3497 LARGE_INTEGER offset
;
3503 if (!pNtMapViewOfSection
) return NULL
;
3506 offset
.u
.LowPart
= 0;
3507 offset
.u
.HighPart
= 0;
3509 exec
= access
& FILE_MAP_EXECUTE
;
3510 access
&= ~FILE_MAP_EXECUTE
;
3512 if (access
== FILE_MAP_COPY
)
3515 protect
= PAGE_EXECUTE_WRITECOPY
;
3517 protect
= PAGE_WRITECOPY
;
3519 else if (access
& FILE_MAP_WRITE
)
3522 protect
= PAGE_EXECUTE_READWRITE
;
3524 protect
= PAGE_READWRITE
;
3526 else if (access
& FILE_MAP_READ
)
3529 protect
= PAGE_EXECUTE_READ
;
3531 protect
= PAGE_READONLY
;
3533 else protect
= PAGE_NOACCESS
;
3536 status
= pNtMapViewOfSection(handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
3537 &count
, 1 /* ViewShare */, 0, protect
);
3540 /* for simplicity */
3541 SetLastError(ERROR_ACCESS_DENIED
);
3547 static void test_mapping(void)
3549 static const DWORD page_prot
[] =
3551 PAGE_NOACCESS
, PAGE_READONLY
, PAGE_READWRITE
, PAGE_WRITECOPY
,
3552 PAGE_EXECUTE_READ
, PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_WRITECOPY
3559 { 0, PAGE_NOACCESS
}, /* 0x00 */
3560 { FILE_MAP_COPY
, PAGE_WRITECOPY
}, /* 0x01 */
3561 { FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x02 */
3562 { FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x03 */
3563 { FILE_MAP_READ
, PAGE_READONLY
}, /* 0x04 */
3564 { FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x05 */
3565 { FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x06 */
3566 { FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x07 */
3567 { SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x08 */
3568 { SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x09 */
3569 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0a */
3570 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0b */
3571 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_READONLY
}, /* 0x0c */
3572 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x0d */
3573 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0e */
3574 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0f */
3575 { FILE_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x20 */
3576 { FILE_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_EXECUTE_WRITECOPY
}, /* 0x21 */
3577 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x22 */
3578 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x23 */
3579 { FILE_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x24 */
3580 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x25 */
3581 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x26 */
3582 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x27 */
3583 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x28 */
3584 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x29 */
3585 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2a */
3586 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x2b */
3587 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x2c */
3588 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x2d */
3589 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2e */
3590 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
} /* 0x2f */
3592 void *base
, *nt_base
, *ptr
;
3593 DWORD i
, j
, k
, ret
, old_prot
, prev_prot
;
3595 char temp_path
[MAX_PATH
];
3596 char file_name
[MAX_PATH
];
3598 MEMORY_BASIC_INFORMATION info
, nt_info
;
3601 trace("system page size %#x\n", si
.dwPageSize
);
3603 GetTempPathA(MAX_PATH
, temp_path
);
3604 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3606 SetLastError(0xdeadbeef);
3607 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3608 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3609 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3610 SetEndOfFile(hfile
);
3612 for (i
= 0; i
< sizeof(page_prot
)/sizeof(page_prot
[0]); i
++)
3614 SetLastError(0xdeadbeef);
3615 hmap
= CreateFileMappingW(hfile
, NULL
, page_prot
[i
] | SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3617 if (page_prot
[i
] == PAGE_NOACCESS
)
3621 ok(!hmap
, "CreateFileMapping(PAGE_NOACCESS) should fail\n");
3622 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3624 /* A trick to create a not accessible mapping */
3625 SetLastError(0xdeadbeef);
3626 hmap
= CreateFileMappingW(hfile
, NULL
, PAGE_READWRITE
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3627 ok(hmap
!= 0, "CreateFileMapping(PAGE_READWRITE) error %d\n", GetLastError());
3628 SetLastError(0xdeadbeef);
3629 ret
= DuplicateHandle(GetCurrentProcess(), hmap
, GetCurrentProcess(), &hmap2
, 0, FALSE
, 0);
3630 ok(ret
, "DuplicateHandle error %d\n", GetLastError());
3637 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, page_prot
[i
], GetLastError());
3639 /* NT4 and win2k don't support EXEC on file mappings */
3640 if (page_prot
[i
] == PAGE_EXECUTE_READ
|| page_prot
[i
] == PAGE_EXECUTE_READWRITE
)
3642 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3645 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3646 if (page_prot
[i
] == PAGE_EXECUTE_WRITECOPY
)
3648 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3653 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, page_prot
[i
], GetLastError());
3655 for (j
= 0; j
< sizeof(view
)/sizeof(view
[0]); j
++)
3657 nt_base
= map_view_of_file(hmap
, view
[j
].access
);
3660 SetLastError(0xdeadbeef);
3661 ret
= VirtualQuery(nt_base
, &nt_info
, sizeof(nt_info
));
3662 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3663 UnmapViewOfFile(nt_base
);
3666 SetLastError(0xdeadbeef);
3667 base
= MapViewOfFile(hmap
, view
[j
].access
, 0, 0, 0);
3669 /* Vista+ supports FILE_MAP_EXECUTE properly, earlier versions don't */
3670 ok(!nt_base
== !base
||
3671 broken((view
[j
].access
& FILE_MAP_EXECUTE
) && !nt_base
!= !base
),
3672 "%d: (%04x/%04x) NT %p kernel %p\n", j
, page_prot
[i
], view
[j
].access
, nt_base
, base
);
3674 if (!is_compatible_access(page_prot
[i
], view
[j
].access
))
3676 ok(!base
, "%d: MapViewOfFile(%04x/%04x) should fail\n", j
, page_prot
[i
], view
[j
].access
);
3677 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %d\n", GetLastError());
3681 /* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */
3682 if (!base
&& (view
[j
].access
& FILE_MAP_EXECUTE
))
3684 ok(broken(!base
), "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3688 ok(base
!= NULL
, "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3690 SetLastError(0xdeadbeef);
3691 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3692 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3693 ok(info
.BaseAddress
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.BaseAddress
, base
);
3694 ok(info
.RegionSize
== si
.dwPageSize
, "%d: (%04x) got %#lx != expected %#x\n", j
, view
[j
].access
, info
.RegionSize
, si
.dwPageSize
);
3695 ok(info
.Protect
== view
[j
].prot
||
3696 broken(view
[j
].prot
== PAGE_EXECUTE_READ
&& info
.Protect
== PAGE_READONLY
) || /* win2k */
3697 broken(view
[j
].prot
== PAGE_EXECUTE_READWRITE
&& info
.Protect
== PAGE_READWRITE
) || /* win2k */
3698 broken(view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3699 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.Protect
, view
[j
].prot
);
3700 ok(info
.AllocationBase
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.AllocationBase
, base
);
3701 ok(info
.AllocationProtect
== info
.Protect
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.AllocationProtect
, info
.Protect
);
3702 ok(info
.State
== MEM_COMMIT
, "%d: (%04x) got %#x, expected MEM_COMMIT\n", j
, view
[j
].access
, info
.State
);
3703 ok(info
.Type
== MEM_MAPPED
, "%d: (%04x) got %#x, expected MEM_MAPPED\n", j
, view
[j
].access
, info
.Type
);
3705 if (nt_base
&& base
)
3707 ok(nt_info
.RegionSize
== info
.RegionSize
, "%d: (%04x) got %#lx != expected %#lx\n", j
, view
[j
].access
, nt_info
.RegionSize
, info
.RegionSize
);
3708 ok(nt_info
.Protect
== info
.Protect
/* Vista+ */ ||
3709 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3710 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Protect
, info
.Protect
);
3711 ok(nt_info
.AllocationProtect
== info
.AllocationProtect
/* Vista+ */ ||
3712 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3713 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.AllocationProtect
, info
.AllocationProtect
);
3714 ok(nt_info
.State
== info
.State
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.State
, info
.State
);
3715 ok(nt_info
.Type
== info
.Type
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Type
, info
.Type
);
3718 prev_prot
= info
.Protect
;
3720 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3722 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3723 SetLastError(0xdeadbeef);
3724 old_prot
= 0xdeadbeef;
3725 ret
= VirtualProtect(base
, si
.dwPageSize
, page_prot
[k
], &old_prot
);
3726 if (is_compatible_protection(page_prot
[i
], view
[j
].prot
, page_prot
[k
]))
3728 /* win2k and XP don't support EXEC on file mappings */
3729 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE
)
3731 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3734 /* NT4 and win2k don't support EXEC on file mappings */
3735 if (!ret
&& (page_prot
[k
] == PAGE_EXECUTE_READ
|| page_prot
[k
] == PAGE_EXECUTE_READWRITE
))
3737 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3740 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3741 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE_WRITECOPY
)
3743 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n");
3746 /* win2k and XP don't support PAGE_EXECUTE_WRITECOPY views properly */
3747 if (!ret
&& view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
)
3749 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY view properly\n");
3753 ok(ret
, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3754 ok(old_prot
== prev_prot
, "got %#x, expected %#x\n", old_prot
, prev_prot
);
3755 prev_prot
= page_prot
[k
];
3759 /* NT4 doesn't fail on incompatible map and view */
3762 ok(broken(ret
), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3763 skip("Incompatible map and view are not properly handled on this platform\n");
3764 break; /* NT4 won't pass remaining tests */
3767 ok(!ret
, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3768 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3772 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3774 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3775 SetLastError(0xdeadbeef);
3776 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, page_prot
[k
]);
3777 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", page_prot
[k
]);
3778 /* FIXME: remove once Wine is fixed */
3779 todo_wine_if (page_prot
[k
] == PAGE_WRITECOPY
|| page_prot
[k
] == PAGE_EXECUTE_WRITECOPY
)
3780 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3783 UnmapViewOfFile(base
);
3790 DeleteFileA(file_name
);
3793 static void test_shared_memory(BOOL is_child
)
3798 SetLastError(0xdeadbef);
3799 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c");
3800 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3802 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3804 SetLastError(0xdeadbef);
3805 p
= MapViewOfFile(mapping
, FILE_MAP_READ
|FILE_MAP_WRITE
, 0, 0, 4096);
3806 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3810 ok(*p
== 0x1a2b3c4d, "expected 0x1a2b3c4d in child, got %#x\n", *p
);
3815 char cmdline
[MAX_PATH
];
3816 PROCESS_INFORMATION pi
;
3817 STARTUPINFOA si
= { sizeof(si
) };
3822 winetest_get_mainargs(&argv
);
3823 sprintf(cmdline
, "\"%s\" virtual sharedmem", argv
[0]);
3824 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3825 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3826 winetest_wait_child_process(pi
.hProcess
);
3827 CloseHandle(pi
.hThread
);
3828 CloseHandle(pi
.hProcess
);
3832 CloseHandle(mapping
);
3835 static void test_shared_memory_ro(BOOL is_child
, DWORD child_access
)
3840 SetLastError(0xdeadbef);
3841 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c_ro");
3842 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3844 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3846 SetLastError(0xdeadbef);
3847 p
= MapViewOfFile(mapping
, is_child
? child_access
: FILE_MAP_READ
, 0, 0, 4096);
3848 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3857 char cmdline
[MAX_PATH
];
3858 PROCESS_INFORMATION pi
;
3859 STARTUPINFOA si
= { sizeof(si
) };
3862 winetest_get_mainargs(&argv
);
3863 sprintf(cmdline
, "\"%s\" virtual sharedmemro %x", argv
[0], child_access
);
3864 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3865 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3866 winetest_wait_child_process(pi
.hProcess
);
3867 CloseHandle(pi
.hThread
);
3868 CloseHandle(pi
.hProcess
);
3870 if(child_access
& FILE_MAP_WRITE
)
3871 ok(*p
== 0xdeadbeef, "*p = %x, expected 0xdeadbeef\n", *p
);
3873 ok(!*p
, "*p = %x, expected 0\n", *p
);
3877 CloseHandle(mapping
);
3880 static void test_NtQuerySection(void)
3882 char path
[MAX_PATH
];
3883 HANDLE file
, mapping
;
3888 SECTION_BASIC_INFORMATION basic
;
3889 SECTION_IMAGE_INFORMATION image
;
3892 IMAGE_NT_HEADERS
*nt
;
3894 SIZE_T fsize
, image_size
;
3897 if (!pNtQuerySection
)
3899 win_skip("NtQuerySection is not available\n");
3904 page_mask
= si
.dwPageSize
- 1;
3906 GetSystemDirectoryA(path
, sizeof(path
));
3907 strcat(path
, "\\kernel32.dll");
3909 SetLastError(0xdeadbef);
3910 file
= CreateFileA(path
, GENERIC_READ
|GENERIC_EXECUTE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
3911 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError());
3913 fsize
= GetFileSize(file
, NULL
);
3915 SetLastError(0xdeadbef);
3916 mapping
= CreateFileMappingA(file
, NULL
, PAGE_EXECUTE_READ
, 0, 0, NULL
);
3917 /* NT4 and win2k don't support EXEC on file mappings */
3919 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
3920 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
3922 status
= pNtQuerySection(mapping
, SectionBasicInformation
, NULL
, sizeof(info
), &ret
);
3923 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status
);
3925 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, 0, NULL
);
3926 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3928 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, 0, &ret
);
3929 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3931 memset(&info
, 0x55, sizeof(info
));
3933 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3934 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3935 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3936 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3937 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
3938 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3940 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
.basic
), &ret
);
3941 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3943 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
), &ret
);
3944 ok(status
== STATUS_SECTION_NOT_IMAGE
, "expected STATUS_SECTION_NOT_IMAGE, got %#x\n", status
);
3946 SetLastError(0xdeadbef);
3947 p
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
3948 ok(p
!= NULL
, "MapViewOfFile error %u\n", GetLastError());
3950 nt
= image_nt_header(p
);
3951 image_size
= ROUND_SIZE(p
, nt
->OptionalHeader
.SizeOfImage
);
3953 memset(&info
, 0x55, sizeof(info
));
3955 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3956 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3957 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3958 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3959 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
3960 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3963 CloseHandle(mapping
);
3965 SetLastError(0xdeadbef);
3966 mapping
= CreateFileMappingA(file
, NULL
, PAGE_EXECUTE_READ
|SEC_IMAGE
, 0, 0, NULL
);
3967 /* NT4 and win2k don't support EXEC on file mappings */
3969 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
|SEC_IMAGE
, 0, 0, NULL
);
3970 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
3972 memset(&info
, 0x55, sizeof(info
));
3974 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3975 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3976 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3977 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3978 ok(info
.basic
.Attributes
== (SEC_FILE
|SEC_IMAGE
), "expected SEC_FILE|SEC_IMAGE, got %#x\n", info
.basic
.Attributes
);
3979 ok(info
.basic
.Size
.QuadPart
== image_size
, "expected %#lx, got %#x/%08x\n", image_size
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3981 status
= pNtQuerySection(mapping
, SectionImageInformation
, NULL
, sizeof(info
), &ret
);
3982 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status
);
3984 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, 0, NULL
);
3985 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3987 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, 0, &ret
);
3988 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3990 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
.basic
), &ret
);
3991 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3993 SetLastError(0xdeadbef);
3994 p
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
3995 ok(p
!= NULL
, "MapViewOfFile error %u\n", GetLastError());
3997 nt
= image_nt_header(p
);
3999 memset(&info
, 0x55, sizeof(info
));
4001 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
), &ret
);
4002 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4003 ok(ret
== sizeof(info
.image
), "wrong returned size %u\n", ret
);
4004 ok((ULONG_PTR
)info
.image
.TransferAddress
== nt
->OptionalHeader
.ImageBase
+ nt
->OptionalHeader
.AddressOfEntryPoint
,
4005 "expected %#lx, got %p\n", (SIZE_T
)(nt
->OptionalHeader
.ImageBase
+ nt
->OptionalHeader
.AddressOfEntryPoint
), info
.image
.TransferAddress
);
4006 ok(info
.image
.ZeroBits
== 0, "expected 0, got %#x\n", info
.image
.ZeroBits
);
4007 ok(info
.image
.MaximumStackSize
== nt
->OptionalHeader
.SizeOfStackReserve
, "expected %#lx, got %#lx\n", (SIZE_T
)nt
->OptionalHeader
.SizeOfStackReserve
, info
.image
.MaximumStackSize
);
4008 ok(info
.image
.CommittedStackSize
== nt
->OptionalHeader
.SizeOfStackCommit
, "expected %#lx, got %#lx\n", (SIZE_T
)nt
->OptionalHeader
.SizeOfStackCommit
, info
.image
.CommittedStackSize
);
4009 ok(info
.image
.SubSystemType
== nt
->OptionalHeader
.Subsystem
, "expected %#x, got %#x\n", nt
->OptionalHeader
.Subsystem
, info
.image
.SubSystemType
);
4010 ok(info
.image
.SubsystemVersionLow
== nt
->OptionalHeader
.MinorSubsystemVersion
, "expected %#x, got %#x\n", nt
->OptionalHeader
.MinorSubsystemVersion
, info
.image
.SubsystemVersionLow
);
4011 ok(info
.image
.SubsystemVersionHigh
== nt
->OptionalHeader
.MajorSubsystemVersion
, "expected %#x, got %#x\n", nt
->OptionalHeader
.MajorSubsystemVersion
, info
.image
.SubsystemVersionHigh
);
4012 ok(info
.image
.ImageCharacteristics
== nt
->FileHeader
.Characteristics
, "expected %#x, got %#x\n", nt
->FileHeader
.Characteristics
, info
.image
.ImageCharacteristics
);
4013 ok(info
.image
.DllCharacteristics
== nt
->OptionalHeader
.DllCharacteristics
, "expected %#x, got %#x\n", nt
->OptionalHeader
.DllCharacteristics
, info
.image
.DllCharacteristics
);
4014 ok(info
.image
.Machine
== nt
->FileHeader
.Machine
, "expected %#x, got %#x\n", nt
->FileHeader
.Machine
, info
.image
.Machine
);
4016 ok(info
.image
.ImageContainsCode
== TRUE
, "expected 1, got %#x\n", info
.image
.ImageContainsCode
);
4018 memset(&info
, 0x55, sizeof(info
));
4020 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4021 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4022 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4023 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4024 ok(info
.basic
.Attributes
== (SEC_FILE
|SEC_IMAGE
), "expected SEC_FILE|SEC_IMAGE, got %#x\n", info
.basic
.Attributes
);
4025 ok(info
.basic
.Size
.QuadPart
== image_size
, "expected %#lx, got %#x/%08x\n", image_size
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4028 CloseHandle(mapping
);
4030 SetLastError(0xdeadbef);
4031 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
|SEC_COMMIT
|SEC_NOCACHE
, 0, 0, NULL
);
4032 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
4034 memset(&info
, 0x55, sizeof(info
));
4036 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4037 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4038 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4039 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4041 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
4042 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4044 CloseHandle(mapping
);
4046 SetLastError(0xdeadbef);
4047 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
|SEC_RESERVE
, 0, 0, NULL
);
4048 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
4050 memset(&info
, 0x55, sizeof(info
));
4052 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4053 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4054 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4055 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4056 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
4057 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4059 CloseHandle(mapping
);
4062 SetLastError(0xdeadbef);
4063 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
|SEC_COMMIT
, 0, 4096, NULL
);
4064 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
4066 memset(&info
, 0x55, sizeof(info
));
4068 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4069 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4070 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4071 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4072 ok(info
.basic
.Attributes
== SEC_COMMIT
, "expected SEC_COMMIT, got %#x\n", info
.basic
.Attributes
);
4073 ok(info
.basic
.Size
.QuadPart
== 4096, "expected 4096, got %#x/%08x\n", info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4075 SetLastError(0xdeadbef);
4076 p
= MapViewOfFile(mapping
, FILE_MAP_READ
|FILE_MAP_WRITE
, 0, 0, 0);
4077 ok(p
!= NULL
, "MapViewOfFile error %u\n", GetLastError());
4079 memset(&info
, 0x55, sizeof(info
));
4081 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4082 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4083 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4084 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4085 ok(info
.basic
.Attributes
== SEC_COMMIT
, "expected SEC_COMMIT, got %#x\n", info
.basic
.Attributes
);
4086 ok(info
.basic
.Size
.QuadPart
== 4096, "expected 4096, got %#x/%08x\n", info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4089 CloseHandle(mapping
);
4091 SetLastError(0xdeadbef);
4092 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READONLY
|SEC_RESERVE
, 0, 4096, NULL
);
4093 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
4095 memset(&info
, 0x55, sizeof(info
));
4097 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4098 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4099 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4100 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4101 ok(info
.basic
.Attributes
== SEC_RESERVE
, "expected SEC_RESERVE, got %#x\n", info
.basic
.Attributes
);
4102 ok(info
.basic
.Size
.QuadPart
== 4096, "expected 4096, got %#x/%08x\n", info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4104 CloseHandle(mapping
);
4111 argc
= winetest_get_mainargs( &argv
);
4115 if (!strcmp(argv
[2], "sleep"))
4117 Sleep(5000); /* spawned process runs for at most 5 seconds */
4120 if (!strcmp(argv
[2], "sharedmem"))
4122 test_shared_memory(TRUE
);
4125 if (!strcmp(argv
[2], "sharedmemro"))
4127 test_shared_memory_ro(TRUE
, strtol(argv
[3], NULL
, 16));
4134 mem
= VirtualAlloc(NULL
, 1<<20, MEM_COMMIT
|MEM_RESERVE
,
4135 PAGE_EXECUTE_READWRITE
);
4136 ok(mem
!= NULL
, "VirtualAlloc failed %u\n", GetLastError());
4137 if (mem
== NULL
) break;
4138 ret
= VirtualFree(mem
, 0, MEM_RELEASE
);
4139 ok(ret
, "VirtualFree failed %u\n", GetLastError());
4145 hkernel32
= GetModuleHandleA("kernel32.dll");
4146 hntdll
= GetModuleHandleA("ntdll.dll");
4148 pVirtualAllocEx
= (void *) GetProcAddress(hkernel32
, "VirtualAllocEx");
4149 pVirtualFreeEx
= (void *) GetProcAddress(hkernel32
, "VirtualFreeEx");
4150 pGetWriteWatch
= (void *) GetProcAddress(hkernel32
, "GetWriteWatch");
4151 pResetWriteWatch
= (void *) GetProcAddress(hkernel32
, "ResetWriteWatch");
4152 pGetProcessDEPPolicy
= (void *)GetProcAddress( hkernel32
, "GetProcessDEPPolicy" );
4153 pIsWow64Process
= (void *)GetProcAddress( hkernel32
, "IsWow64Process" );
4154 pNtAreMappedFilesTheSame
= (void *)GetProcAddress( hntdll
, "NtAreMappedFilesTheSame" );
4155 pNtCreateSection
= (void *)GetProcAddress( hntdll
, "NtCreateSection" );
4156 pNtMapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtMapViewOfSection" );
4157 pNtUnmapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtUnmapViewOfSection" );
4158 pNtQuerySection
= (void *)GetProcAddress( hntdll
, "NtQuerySection" );
4159 pRtlAddVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlAddVectoredExceptionHandler" );
4160 pRtlRemoveVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlRemoveVectoredExceptionHandler" );
4161 pNtProtectVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtProtectVirtualMemory" );
4162 pNtAllocateVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtAllocateVirtualMemory" );
4163 pNtFreeVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtFreeVirtualMemory" );
4165 test_shared_memory(FALSE
);
4166 test_shared_memory_ro(FALSE
, FILE_MAP_READ
|FILE_MAP_WRITE
);
4167 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
);
4168 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
|FILE_MAP_WRITE
);
4170 test_NtQuerySection();
4171 test_CreateFileMapping_protection();
4172 test_VirtualAlloc_protection();
4173 test_VirtualProtect();
4174 test_VirtualAllocEx();
4175 test_VirtualAlloc();
4176 test_MapViewOfFile();
4177 test_NtMapViewOfSection();
4178 test_NtAreMappedFilesTheSame();
4179 test_CreateFileMapping();
4180 test_IsBadReadPtr();
4181 test_IsBadWritePtr();
4182 test_IsBadCodePtr();
4184 #if defined(__i386__) || defined(__x86_64__)
4185 test_stack_commit();
4189 /* The following tests should be executed as a last step, and in exactly this
4190 * order, since ATL thunk emulation cannot be enabled anymore on Windows. */
4191 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE
);
4192 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
);
4193 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
| MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
);