2 * Unit test suite for Virtual* family of APIs.
4 * Copyright 2004 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WIN32_NO_STATUS
29 #include "wine/winternl.h"
32 #include "wine/exception.h"
33 #include "wine/test.h"
36 #define MAPPING_SIZE 0x100000
38 static HINSTANCE hkernel32
, hntdll
;
39 static LPVOID (WINAPI
*pVirtualAllocEx
)(HANDLE
, LPVOID
, SIZE_T
, DWORD
, DWORD
);
40 static BOOL (WINAPI
*pVirtualFreeEx
)(HANDLE
, LPVOID
, SIZE_T
, DWORD
);
41 static UINT (WINAPI
*pGetWriteWatch
)(DWORD
,LPVOID
,SIZE_T
,LPVOID
*,ULONG_PTR
*,ULONG
*);
42 static UINT (WINAPI
*pResetWriteWatch
)(LPVOID
,SIZE_T
);
43 static NTSTATUS (WINAPI
*pNtAreMappedFilesTheSame
)(PVOID
,PVOID
);
44 static NTSTATUS (WINAPI
*pNtCreateSection
)(HANDLE
*, ACCESS_MASK
, const OBJECT_ATTRIBUTES
*,
45 const LARGE_INTEGER
*, ULONG
, ULONG
, HANDLE
);
46 static NTSTATUS (WINAPI
*pNtMapViewOfSection
)(HANDLE
, HANDLE
, PVOID
*, ULONG
, SIZE_T
, const LARGE_INTEGER
*, SIZE_T
*, ULONG
, ULONG
, ULONG
);
47 static DWORD (WINAPI
*pNtUnmapViewOfSection
)(HANDLE
, PVOID
);
48 static NTSTATUS (WINAPI
*pNtQuerySection
)(HANDLE
, SECTION_INFORMATION_CLASS
, void *, ULONG
, ULONG
*);
49 static PVOID (WINAPI
*pRtlAddVectoredExceptionHandler
)(ULONG
, PVECTORED_EXCEPTION_HANDLER
);
50 static ULONG (WINAPI
*pRtlRemoveVectoredExceptionHandler
)(PVOID
);
51 static BOOL (WINAPI
*pGetProcessDEPPolicy
)(HANDLE
, LPDWORD
, PBOOL
);
52 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
53 static NTSTATUS (WINAPI
*pNtProtectVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
, ULONG
*);
54 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG
, SIZE_T
*, ULONG
, ULONG
);
55 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
57 /* ############################### */
59 static UINT_PTR page_mask
= 0xfff;
60 #define ROUND_SIZE(addr,size) \
61 (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
63 static PIMAGE_NT_HEADERS
image_nt_header(HMODULE module
)
65 IMAGE_NT_HEADERS
*ret
= NULL
;
66 IMAGE_DOS_HEADER
*dos
= (IMAGE_DOS_HEADER
*)module
;
68 if (dos
->e_magic
== IMAGE_DOS_SIGNATURE
)
70 ret
= (IMAGE_NT_HEADERS
*)((char *)dos
+ dos
->e_lfanew
);
71 if (ret
->Signature
!= IMAGE_NT_SIGNATURE
) ret
= NULL
;
76 static HANDLE
create_target_process(const char *arg
)
79 char cmdline
[MAX_PATH
];
80 PROCESS_INFORMATION pi
;
82 STARTUPINFOA si
= { 0 };
85 winetest_get_mainargs( &argv
);
86 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], arg
);
87 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
88 ok(ret
, "error: %u\n", GetLastError());
89 ret
= CloseHandle(pi
.hThread
);
90 ok(ret
, "error %u\n", GetLastError());
94 static void test_VirtualAllocEx(void)
96 const unsigned int alloc_size
= 1<<15;
98 SIZE_T bytes_written
= 0, bytes_read
= 0, i
;
102 MEMORY_BASIC_INFORMATION info
;
105 /* not exported in all windows-versions */
106 if ((!pVirtualAllocEx
) || (!pVirtualFreeEx
)) {
107 win_skip("Virtual{Alloc,Free}Ex not available\n");
111 hProcess
= create_target_process("sleep");
112 ok(hProcess
!= NULL
, "Can't start process\n");
114 SetLastError(0xdeadbeef);
115 addr1
= pVirtualAllocEx(hProcess
, NULL
, alloc_size
, MEM_COMMIT
,
116 PAGE_EXECUTE_READWRITE
);
117 ok(addr1
!= NULL
, "VirtualAllocEx error %u\n", GetLastError());
119 src
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
120 dst
= VirtualAlloc( NULL
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
121 for (i
= 0; i
< alloc_size
; i
++)
124 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
125 ok(b
&& (bytes_written
== alloc_size
), "%lu bytes written\n",
127 b
= ReadProcessMemory(hProcess
, addr1
, dst
, alloc_size
, &bytes_read
);
128 ok(b
&& (bytes_read
== alloc_size
), "%lu bytes read\n", bytes_read
);
129 ok(!memcmp(src
, dst
, alloc_size
), "Data from remote process differs\n");
131 /* test invalid source buffers */
133 b
= VirtualProtect( src
+ 0x2000, 0x2000, PAGE_NOACCESS
, &old_prot
);
134 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
135 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
136 ok( !b
, "WriteProcessMemory succeeded\n" );
137 ok( GetLastError() == ERROR_NOACCESS
||
138 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
139 "wrong error %u\n", GetLastError() );
140 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
141 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
142 ok( !b
, "ReadProcessMemory succeeded\n" );
143 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
144 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
146 b
= VirtualProtect( src
, 0x2000, PAGE_NOACCESS
, &old_prot
);
147 ok( b
, "VirtualProtect failed error %u\n", GetLastError() );
148 b
= WriteProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_written
);
149 ok( !b
, "WriteProcessMemory succeeded\n" );
150 ok( GetLastError() == ERROR_NOACCESS
||
151 GetLastError() == ERROR_PARTIAL_COPY
, /* vista */
152 "wrong error %u\n", GetLastError() );
153 ok( bytes_written
== 0, "%lu bytes written\n", bytes_written
);
154 b
= ReadProcessMemory(hProcess
, addr1
, src
, alloc_size
, &bytes_read
);
155 ok( !b
, "ReadProcessMemory succeeded\n" );
156 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
157 ok( bytes_read
== 0, "%lu bytes written\n", bytes_read
);
159 b
= pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
);
160 ok(b
!= 0, "VirtualFreeEx, error %u\n", GetLastError());
162 VirtualFree( src
, 0, MEM_RELEASE
);
163 VirtualFree( dst
, 0, MEM_RELEASE
);
166 * The following tests parallel those in test_VirtualAlloc()
169 SetLastError(0xdeadbeef);
170 addr1
= pVirtualAllocEx(hProcess
, 0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
171 ok(addr1
== NULL
, "VirtualAllocEx should fail on zero-sized allocation\n");
172 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
173 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
175 addr1
= pVirtualAllocEx(hProcess
, 0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
176 ok(addr1
!= NULL
, "VirtualAllocEx failed\n");
178 /* test a not committed memory */
179 memset(&info
, 'q', sizeof(info
));
180 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
), "VirtualQueryEx failed\n");
181 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
182 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
183 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
184 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
185 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
186 ok(info
.Protect
== 0, "%x != PAGE_NOACCESS\n", info
.Protect
);
187 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
189 SetLastError(0xdeadbeef);
190 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
191 "VirtualProtectEx should fail on a not committed memory\n");
192 ok(GetLastError() == ERROR_INVALID_ADDRESS
,
193 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
195 addr2
= pVirtualAllocEx(hProcess
, addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
196 ok(addr1
== addr2
, "VirtualAllocEx failed\n");
198 /* test a committed memory */
199 ok(VirtualQueryEx(hProcess
, addr1
, &info
, sizeof(info
)) == sizeof(info
),
200 "VirtualQueryEx failed\n");
201 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
202 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
203 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
204 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
205 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
206 /* this time NT reports PAGE_NOACCESS as well */
207 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
208 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
210 /* this should fail, since not the whole range is committed yet */
211 SetLastError(0xdeadbeef);
212 ok(!VirtualProtectEx(hProcess
, addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
213 "VirtualProtectEx should fail on a not committed memory\n");
214 ok(GetLastError() == ERROR_INVALID_ADDRESS
,
215 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
218 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtectEx failed\n");
219 ok(old_prot
== PAGE_NOACCESS
, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
222 ok(VirtualProtectEx(hProcess
, addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtectEx failed\n");
223 ok(old_prot
== PAGE_READONLY
, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
225 ok(!pVirtualFreeEx(hProcess
, addr1
, 0x10000, 0),
226 "VirtualFreeEx should fail with type 0\n");
227 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
228 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
230 ok(pVirtualFreeEx(hProcess
, addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFreeEx failed\n");
232 /* if the type is MEM_RELEASE, size must be 0 */
233 ok(!pVirtualFreeEx(hProcess
, addr1
, 1, MEM_RELEASE
),
234 "VirtualFreeEx should fail\n");
235 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
236 "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
238 ok(pVirtualFreeEx(hProcess
, addr1
, 0, MEM_RELEASE
), "VirtualFreeEx failed\n");
240 TerminateProcess(hProcess
, 0);
241 CloseHandle(hProcess
);
244 static void test_VirtualAlloc(void)
248 MEMORY_BASIC_INFORMATION info
;
252 SetLastError(0xdeadbeef);
253 addr1
= VirtualAlloc(0, 0, MEM_RESERVE
, PAGE_NOACCESS
);
254 ok(addr1
== NULL
, "VirtualAlloc should fail on zero-sized allocation\n");
255 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
256 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
258 addr1
= VirtualAlloc(0, 0xFFFC, MEM_RESERVE
, PAGE_NOACCESS
);
259 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
261 /* test a not committed memory */
262 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
263 "VirtualQuery failed\n");
264 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
265 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
266 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
267 ok(info
.RegionSize
== 0x10000, "%lx != 0x10000\n", info
.RegionSize
);
268 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
269 ok(info
.Protect
== 0, "%x != PAGE_NOACCESS\n", info
.Protect
);
270 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
272 SetLastError(0xdeadbeef);
273 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
274 "VirtualProtect should fail on a not committed memory\n");
275 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
276 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
278 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_NOACCESS
);
279 ok(addr1
== addr2
, "VirtualAlloc failed\n");
281 /* test a committed memory */
282 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
283 "VirtualQuery failed\n");
284 ok(info
.BaseAddress
== addr1
, "%p != %p\n", info
.BaseAddress
, addr1
);
285 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
286 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.AllocationProtect
);
287 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
288 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
289 /* this time NT reports PAGE_NOACCESS as well */
290 ok(info
.Protect
== PAGE_NOACCESS
, "%x != PAGE_NOACCESS\n", info
.Protect
);
291 ok(info
.Type
== MEM_PRIVATE
, "%x != MEM_PRIVATE\n", info
.Type
);
293 /* this should fail, since not the whole range is committed yet */
294 SetLastError(0xdeadbeef);
295 ok(!VirtualProtect(addr1
, 0xFFFC, PAGE_READONLY
, &old_prot
),
296 "VirtualProtect should fail on a not committed memory\n");
297 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
298 "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
300 ok(VirtualProtect(addr1
, 0x1000, PAGE_READONLY
, &old_prot
), "VirtualProtect failed\n");
301 ok(old_prot
== PAGE_NOACCESS
,
302 "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot
);
304 ok(VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
, &old_prot
), "VirtualProtect failed\n");
305 ok(old_prot
== PAGE_READONLY
,
306 "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot
);
308 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
309 "VirtualQuery failed\n");
310 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
311 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
312 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
313 memset( addr1
, 0x55, 20 );
314 ok( *(DWORD
*)addr1
== 0x55555555, "wrong data %x\n", *(DWORD
*)addr1
);
316 addr2
= VirtualAlloc( addr1
, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
317 ok( addr2
== addr1
, "VirtualAlloc failed err %u\n", GetLastError() );
318 ok( *(DWORD
*)addr1
== 0x55555555 || *(DWORD
*)addr1
== 0, "wrong data %x\n", *(DWORD
*)addr1
);
319 ok(VirtualQuery(addr1
, &info
, sizeof(info
)) == sizeof(info
),
320 "VirtualQuery failed\n");
321 ok(info
.RegionSize
== 0x1000, "%lx != 0x1000\n", info
.RegionSize
);
322 ok(info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
323 ok(info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
325 addr2
= VirtualAlloc( (char *)addr1
+ 0x1000, 0x1000, MEM_RESET
, PAGE_NOACCESS
);
326 ok( (char *)addr2
== (char *)addr1
+ 0x1000, "VirtualAlloc failed\n" );
328 ok(VirtualQuery(addr2
, &info
, sizeof(info
)) == sizeof(info
),
329 "VirtualQuery failed\n");
330 ok(info
.RegionSize
== 0xf000, "%lx != 0xf000\n", info
.RegionSize
);
331 ok(info
.State
== MEM_RESERVE
, "%x != MEM_RESERVE\n", info
.State
);
332 ok(info
.Protect
== 0, "%x != 0\n", info
.Protect
);
334 addr2
= VirtualAlloc( (char *)addr1
+ 0xf000, 0x2000, MEM_RESET
, PAGE_NOACCESS
);
335 ok( !addr2
, "VirtualAlloc failed\n" );
336 ok( GetLastError() == ERROR_INVALID_ADDRESS
, "wrong error %u\n", GetLastError() );
338 /* invalid protection values */
339 SetLastError(0xdeadbeef);
340 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_RESERVE
, 0);
341 ok(!addr2
, "VirtualAlloc succeeded\n");
342 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
344 SetLastError(0xdeadbeef);
345 addr2
= VirtualAlloc(NULL
, 0x1000, MEM_COMMIT
, 0);
346 ok(!addr2
, "VirtualAlloc succeeded\n");
347 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
349 SetLastError(0xdeadbeef);
350 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_COMMIT
, PAGE_READONLY
| PAGE_EXECUTE
);
351 ok(!addr2
, "VirtualAlloc succeeded\n");
352 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
354 SetLastError(0xdeadbeef);
355 ok(!VirtualProtect(addr1
, 0x1000, PAGE_READWRITE
| PAGE_EXECUTE_WRITECOPY
, &old_prot
),
356 "VirtualProtect succeeded\n");
357 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
359 SetLastError(0xdeadbeef);
360 ok(!VirtualProtect(addr1
, 0x1000, 0, &old_prot
), "VirtualProtect succeeded\n");
361 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
363 SetLastError(0xdeadbeef);
364 ok(!VirtualFree(addr1
, 0x10000, 0), "VirtualFree should fail with type 0\n");
365 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
366 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
368 SetLastError(0xdeadbeef);
369 ok(!VirtualFree(addr1
, 0, MEM_FREE
), "VirtualFree should fail with type MEM_FREE\n");
370 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
371 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
373 ok(VirtualFree(addr1
, 0x10000, MEM_DECOMMIT
), "VirtualFree failed\n");
375 /* if the type is MEM_RELEASE, size must be 0 */
376 ok(!VirtualFree(addr1
, 1, MEM_RELEASE
), "VirtualFree should fail\n");
377 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
378 "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
380 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
382 /* memory returned by VirtualAlloc should be aligned to 64k */
383 addr1
= VirtualAlloc(0, 0x2000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
384 ok(addr1
!= NULL
, "VirtualAlloc failed\n");
385 ok(!((ULONG_PTR
)addr1
& 0xffff), "returned memory %p is not aligned to 64k\n", addr1
);
386 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
387 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
388 ok(addr2
== addr1
, "VirtualAlloc returned %p, expected %p\n", addr2
, addr1
);
390 /* allocation conflicts because of 64k align */
392 addr2
= (char *)addr1
+ 0x1000;
393 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
,
394 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
395 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
397 /* it should conflict, even when zero_bits is explicitly set */
399 addr2
= (char *)addr1
+ 0x1000;
400 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 12, &size
,
401 MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
403 ok(status
== STATUS_CONFLICTING_ADDRESSES
, "NtAllocateVirtualMemory returned %08x\n", status
);
404 if (status
== STATUS_SUCCESS
) ok(VirtualFree(addr2
, 0, MEM_RELEASE
), "VirtualFree failed\n");
406 /* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
407 SetLastError(0xdeadbeef);
408 addr2
= VirtualAlloc(addr1
, 0x1000, MEM_RESERVE
| MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
409 ok(!addr2
, "VirtualAlloc unexpectedly succeeded\n");
410 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
412 /* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
414 addr2
= (char *)addr1
+ 0x1000;
415 status
= pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2
, 0, &size
, MEM_RESERVE
|
416 MEM_COMMIT
| AT_ROUND_TO_PAGE
, PAGE_EXECUTE_READWRITE
);
418 ok(status
== STATUS_INVALID_PARAMETER_5
, "NtAllocateVirtualMemory returned %08x\n", status
);
420 ok(VirtualFree(addr1
, 0, MEM_RELEASE
), "VirtualFree failed\n");
423 static void test_MapViewOfFile(void)
425 static const char testfile
[] = "testfile.xxx";
427 HANDLE file
, mapping
, map2
;
428 void *ptr
, *ptr2
, *addr
;
429 SECTION_BASIC_INFORMATION section_info
;
430 SECTION_IMAGE_INFORMATION image_info
;
431 MEMORY_BASIC_INFORMATION info
;
436 LARGE_INTEGER map_size
;
438 SetLastError(0xdeadbeef);
439 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
440 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
441 SetFilePointer( file
, 12288, NULL
, FILE_BEGIN
);
442 SetEndOfFile( file
);
444 /* read/write mapping */
446 SetLastError(0xdeadbeef);
447 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
448 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
450 SetLastError(0xdeadbeef);
451 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
452 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
453 UnmapViewOfFile( ptr
);
455 SetLastError(0xdeadbeef);
456 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
457 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
458 UnmapViewOfFile( ptr
);
460 SetLastError(0xdeadbeef);
461 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
462 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
463 UnmapViewOfFile( ptr
);
465 SetLastError(0xdeadbeef);
466 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
467 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
468 UnmapViewOfFile( ptr
);
470 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
471 FILE_MAP_READ
|FILE_MAP_WRITE
, FALSE
, 0 );
472 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
473 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
474 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
475 UnmapViewOfFile( ptr
);
478 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
,
479 FILE_MAP_READ
, FALSE
, 0 );
480 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
481 SetLastError(0xdeadbeef);
482 ptr
= MapViewOfFile( map2
, FILE_MAP_WRITE
, 0, 0, 4096 );
483 ok( !ptr
, "MapViewOfFile succeeded\n" );
484 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
486 ret
= DuplicateHandle( GetCurrentProcess(), mapping
, GetCurrentProcess(), &map2
, 0, FALSE
, 0 );
487 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
488 SetLastError(0xdeadbeef);
489 ptr
= MapViewOfFile( map2
, 0, 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
,
494 FILE_MAP_READ
, FALSE
, 0 );
495 ok( ret
, "DuplicateHandle failed error %u\n", GetLastError());
496 ptr
= MapViewOfFile( map2
, 0, 0, 0, 4096 );
497 ok( ptr
!= NULL
, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
499 UnmapViewOfFile( ptr
);
501 CloseHandle( mapping
);
503 /* read-only mapping */
505 SetLastError(0xdeadbeef);
506 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
507 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
509 SetLastError(0xdeadbeef);
510 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
511 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
512 UnmapViewOfFile( ptr
);
514 SetLastError(0xdeadbeef);
515 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
516 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
517 UnmapViewOfFile( ptr
);
519 SetLastError(0xdeadbeef);
520 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
521 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
522 UnmapViewOfFile( ptr
);
524 SetLastError(0xdeadbeef);
525 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
526 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
527 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
528 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
529 CloseHandle( mapping
);
531 /* copy-on-write mapping */
533 SetLastError(0xdeadbeef);
534 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
535 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
537 SetLastError(0xdeadbeef);
538 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
539 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
540 UnmapViewOfFile( ptr
);
542 SetLastError(0xdeadbeef);
543 ptr
= MapViewOfFile( mapping
, FILE_MAP_COPY
, 0, 0, 4096 );
544 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
545 UnmapViewOfFile( ptr
);
547 SetLastError(0xdeadbeef);
548 ptr
= MapViewOfFile( mapping
, 0, 0, 0, 4096 );
549 ok( ptr
!= NULL
, "MapViewOfFile 0 error %u\n", GetLastError() );
550 UnmapViewOfFile( ptr
);
552 SetLastError(0xdeadbeef);
553 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 4096 );
554 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
555 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
556 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
557 CloseHandle( mapping
);
559 /* no access mapping */
561 SetLastError(0xdeadbeef);
562 mapping
= CreateFileMappingA( file
, NULL
, PAGE_NOACCESS
, 0, 4096, NULL
);
563 ok( !mapping
, "CreateFileMappingA succeeded\n" );
564 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "Wrong error %d\n", GetLastError() );
567 /* now try read-only file */
569 SetLastError(0xdeadbeef);
570 file
= CreateFileA( testfile
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0 );
571 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
573 SetLastError(0xdeadbeef);
574 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
575 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
576 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
577 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
579 SetLastError(0xdeadbeef);
580 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
581 ok( mapping
!= 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
582 CloseHandle( mapping
);
584 SetLastError(0xdeadbeef);
585 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
586 ok( mapping
!= 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
587 CloseHandle( mapping
);
590 /* now try no access file */
592 SetLastError(0xdeadbeef);
593 file
= CreateFileA( testfile
, 0, 0, NULL
, OPEN_EXISTING
, 0, 0 );
594 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
596 SetLastError(0xdeadbeef);
597 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
598 ok( !mapping
, "CreateFileMapping PAGE_READWRITE succeeded\n" );
599 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
600 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
602 SetLastError(0xdeadbeef);
603 mapping
= CreateFileMappingA( file
, NULL
, PAGE_WRITECOPY
, 0, 4096, NULL
);
604 ok( !mapping
, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
605 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
606 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
608 SetLastError(0xdeadbeef);
609 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
610 ok( !mapping
, "CreateFileMapping PAGE_READONLY succeeded\n" );
611 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
612 GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
615 DeleteFileA( testfile
);
617 SetLastError(0xdeadbeef);
619 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4090, name
);
620 /* nt4 doesn't have Local\\ */
621 if (!file
&& GetLastError() == ERROR_PATH_NOT_FOUND
)
624 file
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4090, name
);
626 ok( file
!= 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
628 SetLastError(0xdeadbeef);
629 mapping
= OpenFileMappingA( FILE_MAP_READ
, FALSE
, name
);
630 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
631 SetLastError(0xdeadbeef);
632 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
633 ok( !ptr
, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
634 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
635 SetLastError(0xdeadbeef);
636 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
637 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
638 SetLastError(0xdeadbeef);
639 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
640 ok( size
== sizeof(info
),
641 "VirtualQuery error %u\n", GetLastError() );
642 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
643 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
644 ok( info
.AllocationProtect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.AllocationProtect
);
645 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
646 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
647 ok( info
.Protect
== PAGE_READONLY
, "%x != PAGE_READONLY\n", info
.Protect
);
648 UnmapViewOfFile( ptr
);
649 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
650 sizeof(section_info
), &info_size
);
651 ok( status
== STATUS_ACCESS_DENIED
, "NtQuerySection failed err %x\n", status
);
652 CloseHandle( mapping
);
653 mapping
= OpenFileMappingA( FILE_MAP_READ
| SECTION_QUERY
, FALSE
, name
);
654 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
655 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
656 sizeof(section_info
), &info_size
);
657 ok( !status
, "NtQuerySection failed err %x\n", status
);
658 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
659 ok( section_info
.Attributes
== SEC_COMMIT
, "NtQuerySection wrong attr %08x\n",
660 section_info
.Attributes
);
661 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
662 ok( section_info
.Size
.QuadPart
== info
.RegionSize
, "NtQuerySection wrong size %x%08x / %08lx\n",
663 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
, info
.RegionSize
);
664 CloseHandle( mapping
);
666 SetLastError(0xdeadbeef);
667 mapping
= OpenFileMappingA( FILE_MAP_WRITE
, FALSE
, name
);
668 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
669 SetLastError(0xdeadbeef);
670 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
671 ok( !ptr
, "MapViewOfFile succeeded\n" );
672 ok( GetLastError() == ERROR_ACCESS_DENIED
, "Wrong error %d\n", GetLastError() );
673 SetLastError(0xdeadbeef);
674 ptr
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
675 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
676 SetLastError(0xdeadbeef);
677 size
= VirtualQuery( ptr
, &info
, sizeof(info
) );
678 ok( size
== sizeof(info
),
679 "VirtualQuery error %u\n", GetLastError() );
680 ok( info
.BaseAddress
== ptr
, "%p != %p\n", info
.BaseAddress
, ptr
);
681 ok( info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
682 ok( info
.AllocationProtect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.AllocationProtect
);
683 ok( info
.RegionSize
== 4096, "%lx != 4096\n", info
.RegionSize
);
684 ok( info
.State
== MEM_COMMIT
, "%x != MEM_COMMIT\n", info
.State
);
685 ok( info
.Protect
== PAGE_READWRITE
, "%x != PAGE_READWRITE\n", info
.Protect
);
686 UnmapViewOfFile( ptr
);
687 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
688 sizeof(section_info
), &info_size
);
689 ok( status
== STATUS_ACCESS_DENIED
, "NtQuerySection failed err %x\n", status
);
690 CloseHandle( mapping
);
692 mapping
= OpenFileMappingA( FILE_MAP_WRITE
| SECTION_QUERY
, FALSE
, name
);
693 ok( mapping
!= 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
694 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
695 sizeof(section_info
), &info_size
);
696 ok( !status
, "NtQuerySection failed err %x\n", status
);
697 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
698 ok( section_info
.Attributes
== SEC_COMMIT
, "NtQuerySection wrong attr %08x\n",
699 section_info
.Attributes
);
700 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
701 ok( section_info
.Size
.QuadPart
== info
.RegionSize
, "NtQuerySection wrong size %x%08x / %08lx\n",
702 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
, info
.RegionSize
);
703 CloseHandle( mapping
);
707 /* read/write mapping with SEC_RESERVE */
708 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
| SEC_RESERVE
, 0, MAPPING_SIZE
, NULL
);
709 ok(mapping
!= INVALID_HANDLE_VALUE
, "CreateFileMappingA failed with error %d\n", GetLastError());
710 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
711 sizeof(section_info
), NULL
);
712 ok( !status
, "NtQuerySection failed err %x\n", status
);
713 ok( section_info
.Attributes
== SEC_RESERVE
, "NtQuerySection wrong attr %08x\n",
714 section_info
.Attributes
);
715 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
716 ok( section_info
.Size
.QuadPart
== MAPPING_SIZE
, "NtQuerySection wrong size %x%08x / %08x\n",
717 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
, MAPPING_SIZE
);
719 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
720 ok(ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
722 ptr2
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
723 ok( ptr2
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError());
724 ok( ptr
!= ptr2
, "MapViewOfFile returned same pointer\n" );
726 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
727 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
728 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
729 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
730 ok(info
.RegionSize
== MAPPING_SIZE
, "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
731 ok(info
.State
== MEM_RESERVE
, "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
732 ok(info
.AllocationProtect
== PAGE_READWRITE
,
733 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
734 ok(info
.Protect
== 0, "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
735 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
737 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
738 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
739 ok(info
.BaseAddress
== ptr2
,
740 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
741 ok(info
.AllocationBase
== ptr2
,
742 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
743 ok(info
.AllocationProtect
== PAGE_READWRITE
,
744 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
745 ok(info
.RegionSize
== MAPPING_SIZE
,
746 "RegionSize should have been 0x%x but was 0x%lx\n", MAPPING_SIZE
, info
.RegionSize
);
747 ok(info
.State
== MEM_RESERVE
, "State should have been MEM_RESERVE instead of 0x%x\n", info
.State
);
748 ok(info
.Protect
== 0, "Protect should have been 0 instead of 0x%x\n", info
.Protect
);
749 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
751 ptr
= VirtualAlloc(ptr
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
752 ok(ptr
!= NULL
, "VirtualAlloc failed with error %d\n", GetLastError());
754 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
755 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
756 ok(info
.BaseAddress
== ptr
, "BaseAddress should have been %p but was %p instead\n", ptr
, info
.BaseAddress
);
757 ok(info
.AllocationBase
== ptr
, "AllocationBase should have been %p but was %p instead\n", ptr
, info
.AllocationBase
);
758 ok(info
.RegionSize
== 0x10000, "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
759 ok(info
.State
== MEM_COMMIT
, "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
760 ok(info
.Protect
== PAGE_READONLY
, "Protect should have been PAGE_READONLY instead of 0x%x\n", info
.Protect
);
761 ok(info
.AllocationProtect
== PAGE_READWRITE
,
762 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
763 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
765 /* shows that the VirtualAlloc above affects the mapping, not just the
766 * virtual memory in this process - it also affects all other processes
767 * with a view of the mapping, but that isn't tested here */
768 ret
= VirtualQuery(ptr2
, &info
, sizeof(info
));
769 ok(ret
, "VirtualQuery failed with error %d\n", GetLastError());
770 ok(info
.BaseAddress
== ptr2
,
771 "BaseAddress should have been %p but was %p instead\n", ptr2
, info
.BaseAddress
);
772 ok(info
.AllocationBase
== ptr2
,
773 "AllocationBase should have been %p but was %p instead\n", ptr2
, info
.AllocationBase
);
774 ok(info
.AllocationProtect
== PAGE_READWRITE
,
775 "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info
.AllocationProtect
);
776 ok(info
.RegionSize
== 0x10000,
777 "RegionSize should have been 0x10000 but was 0x%lx\n", info
.RegionSize
);
778 ok(info
.State
== MEM_COMMIT
,
779 "State should have been MEM_COMMIT instead of 0x%x\n", info
.State
);
780 ok(info
.Protect
== PAGE_READWRITE
,
781 "Protect should have been PAGE_READWRITE instead of 0x%x\n", info
.Protect
);
782 ok(info
.Type
== MEM_MAPPED
, "Type should have been MEM_MAPPED instead of 0x%x\n", info
.Type
);
784 addr
= VirtualAlloc( ptr
, MAPPING_SIZE
, MEM_RESET
, PAGE_READONLY
);
785 ok( addr
== ptr
, "VirtualAlloc failed with error %u\n", GetLastError() );
787 ret
= VirtualFree( ptr
, 0x10000, MEM_DECOMMIT
);
788 ok( !ret
, "VirtualFree succeeded\n" );
789 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "VirtualFree failed with %u\n", GetLastError() );
791 ret
= UnmapViewOfFile(ptr2
);
792 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
793 ret
= UnmapViewOfFile(ptr
);
794 ok(ret
, "UnmapViewOfFile failed with error %d\n", GetLastError());
795 CloseHandle(mapping
);
797 addr
= VirtualAlloc(NULL
, 0x10000, MEM_COMMIT
, PAGE_READONLY
);
798 ok( addr
!= NULL
, "VirtualAlloc failed with error %u\n", GetLastError() );
800 SetLastError(0xdeadbeef);
801 ok( !UnmapViewOfFile(addr
), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
802 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
803 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
804 SetLastError(0xdeadbeef);
805 ok( !UnmapViewOfFile((char *)addr
+ 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
806 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
807 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
808 SetLastError(0xdeadbeef);
809 ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
810 ok( GetLastError() == ERROR_INVALID_ADDRESS
,
811 "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
813 ok( VirtualFree(addr
, 0, MEM_RELEASE
), "VirtualFree failed\n" );
815 /* close named mapping handle without unmapping */
817 SetLastError(0xdeadbeef);
818 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
819 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
820 SetLastError(0xdeadbeef);
821 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
822 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
823 SetLastError(0xdeadbeef);
824 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
825 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
826 SetLastError(0xdeadbeef);
827 ret
= CloseHandle(map2
);
828 ok(ret
, "CloseHandle error %d\n", GetLastError());
829 SetLastError(0xdeadbeef);
830 ret
= CloseHandle(mapping
);
831 ok(ret
, "CloseHandle error %d\n", GetLastError());
833 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
834 ok( !ret
, "memory is not accessible\n" );
836 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
837 ok(ret
, "VirtualQuery error %d\n", GetLastError());
838 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
839 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
840 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
841 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
842 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
843 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
844 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
846 SetLastError(0xdeadbeef);
847 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
849 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
851 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
852 if (map2
) CloseHandle(map2
); /* FIXME: remove once Wine is fixed */
853 SetLastError(0xdeadbeef);
854 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
855 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
857 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set error %d\n", GetLastError() );
858 SetLastError(0xdeadbeef);
859 ret
= CloseHandle(mapping
);
860 ok(ret
, "CloseHandle error %d\n", GetLastError());
862 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
863 ok( !ret
, "memory is not accessible\n" );
865 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
866 ok(ret
, "VirtualQuery error %d\n", GetLastError());
867 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
868 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
869 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
870 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
871 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
872 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
873 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
875 SetLastError(0xdeadbeef);
876 ret
= UnmapViewOfFile(ptr
);
877 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
879 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
880 ok( ret
, "memory is accessible\n" );
882 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
883 ok(ret
, "VirtualQuery error %d\n", GetLastError());
884 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
885 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
886 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
887 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
888 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
889 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
891 SetLastError(0xdeadbeef);
892 file
= CreateFileA(testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
893 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
894 SetFilePointer(file
, 4096, NULL
, FILE_BEGIN
);
897 SetLastError(0xdeadbeef);
898 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
899 ok( mapping
!= 0, "CreateFileMappingA failed with error %d\n", GetLastError() );
900 SetLastError(0xdeadbeef);
901 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
, 0, 0, 0);
902 ok( ptr
!= NULL
, "MapViewOfFile failed with error %d\n", GetLastError() );
903 SetLastError(0xdeadbeef);
904 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
905 ok( map2
!= 0, "OpenFileMappingA failed with error %d\n", GetLastError() );
906 SetLastError(0xdeadbeef);
907 ret
= CloseHandle(map2
);
908 ok(ret
, "CloseHandle error %d\n", GetLastError());
909 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
910 sizeof(section_info
), &info_size
);
911 ok( !status
, "NtQuerySection failed err %x\n", status
);
912 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
913 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
914 section_info
.Attributes
);
915 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
916 ok( section_info
.Size
.QuadPart
== MAPPING_SIZE
, "NtQuerySection wrong size %x%08x\n",
917 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
918 SetLastError(0xdeadbeef);
919 ret
= CloseHandle(mapping
);
920 ok(ret
, "CloseHandle error %d\n", GetLastError());
922 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
923 ok( !ret
, "memory is not accessible\n" );
925 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
926 ok(ret
, "VirtualQuery error %d\n", GetLastError());
927 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
928 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
929 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
930 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
931 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
932 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
933 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
935 SetLastError(0xdeadbeef);
936 map2
= OpenFileMappingA(FILE_MAP_READ
, FALSE
, name
);
938 ok( map2
== 0, "OpenFileMappingA succeeded\n" );
940 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "OpenFileMappingA set error %d\n", GetLastError() );
942 SetLastError(0xdeadbeef);
943 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READWRITE
, 0, MAPPING_SIZE
, name
);
944 ok( mapping
!= 0, "CreateFileMappingA failed\n" );
946 ok( GetLastError() == ERROR_SUCCESS
, "CreateFileMappingA set error %d\n", GetLastError() );
947 SetLastError(0xdeadbeef);
948 ret
= CloseHandle(mapping
);
949 ok(ret
, "CloseHandle error %d\n", GetLastError());
951 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
952 ok( !ret
, "memory is not accessible\n" );
954 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
955 ok(ret
, "VirtualQuery error %d\n", GetLastError());
956 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
957 ok(info
.RegionSize
== MAPPING_SIZE
, "got %#lx != expected %#x\n", info
.RegionSize
, MAPPING_SIZE
);
958 ok(info
.Protect
== PAGE_READWRITE
, "got %#x != expected PAGE_READWRITE\n", info
.Protect
);
959 ok(info
.AllocationBase
== ptr
, "%p != %p\n", info
.AllocationBase
, ptr
);
960 ok(info
.AllocationProtect
== PAGE_READWRITE
, "%#x != PAGE_READWRITE\n", info
.AllocationProtect
);
961 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
962 ok(info
.Type
== MEM_MAPPED
, "%#x != MEM_MAPPED\n", info
.Type
);
964 SetLastError(0xdeadbeef);
965 ret
= UnmapViewOfFile(ptr
);
966 ok( ret
, "UnmapViewOfFile failed with error %d\n", GetLastError() );
968 ret
= IsBadReadPtr(ptr
, MAPPING_SIZE
);
969 ok( ret
, "memory is accessible\n" );
971 ret
= VirtualQuery(ptr
, &info
, sizeof(info
));
972 ok(ret
, "VirtualQuery error %d\n", GetLastError());
973 ok(info
.BaseAddress
== ptr
, "got %p != expected %p\n", info
.BaseAddress
, ptr
);
974 ok(info
.Protect
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", info
.Protect
);
975 ok(info
.AllocationBase
== NULL
, "%p != NULL\n", info
.AllocationBase
);
976 ok(info
.AllocationProtect
== 0, "%#x != 0\n", info
.AllocationProtect
);
977 ok(info
.State
== MEM_FREE
, "%#x != MEM_FREE\n", info
.State
);
978 ok(info
.Type
== 0, "%#x != 0\n", info
.Type
);
980 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 12288, NULL
);
981 ok( mapping
!= NULL
, "CreateFileMappingA failed with error %u\n", GetLastError() );
983 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 12288 );
984 ok( ptr
!= NULL
, "MapViewOfFile failed with error %u\n", GetLastError() );
986 ret
= UnmapViewOfFile( (char *)ptr
+ 100 );
987 ok( ret
, "UnmapViewOfFile failed with error %u\n", GetLastError() );
989 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 12288 );
990 ok( ptr
!= NULL
, "MapViewOfFile failed with error %u\n", GetLastError() );
992 ret
= UnmapViewOfFile( (char *)ptr
+ 4096 );
993 ok( ret
, "UnmapViewOfFile failed with error %u\n", GetLastError() );
995 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 12288 );
996 ok( ptr
!= NULL
, "MapViewOfFile failed with error %u\n", GetLastError() );
998 ret
= UnmapViewOfFile( (char *)ptr
+ 4096 + 100 );
999 ok( ret
, "UnmapViewOfFile failed with error %u\n", GetLastError() );
1001 CloseHandle(mapping
);
1003 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 36, NULL
);
1004 ok( mapping
!= NULL
, "CreateFileMappingA failed with error %u\n", GetLastError() );
1005 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
1006 sizeof(section_info
), &info_size
);
1007 ok( !status
, "NtQuerySection failed err %x\n", status
);
1008 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
1009 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
1010 section_info
.Attributes
);
1011 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
1012 ok( section_info
.Size
.QuadPart
== 36, "NtQuerySection wrong size %x%08x\n",
1013 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
1014 CloseHandle(mapping
);
1016 SetFilePointer(file
, 0x3456, NULL
, FILE_BEGIN
);
1018 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
1019 ok( mapping
!= NULL
, "CreateFileMappingA failed with error %u\n", GetLastError() );
1020 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
,
1021 sizeof(section_info
), &info_size
);
1022 ok( !status
, "NtQuerySection failed err %x\n", status
);
1023 ok( info_size
== sizeof(section_info
), "NtQuerySection wrong size %u\n", info_size
);
1024 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
1025 section_info
.Attributes
);
1026 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
1027 ok( section_info
.Size
.QuadPart
== 0x3456, "NtQuerySection wrong size %x%08x\n",
1028 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
1029 CloseHandle(mapping
);
1031 map_size
.QuadPart
= 0x3457;
1032 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1033 &map_size
, PAGE_READONLY
, SEC_COMMIT
, file
);
1034 ok( status
== STATUS_SECTION_TOO_BIG
, "NtCreateSection failed %x\n", status
);
1035 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1036 &map_size
, PAGE_READONLY
, SEC_IMAGE
, file
);
1037 ok( status
== STATUS_INVALID_IMAGE_NOT_MZ
, "NtCreateSection failed %x\n", status
);
1038 if (!status
) CloseHandle( mapping
);
1039 map_size
.QuadPart
= 0x3452;
1040 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1041 &map_size
, PAGE_READONLY
, SEC_COMMIT
, file
);
1042 ok( !status
, "NtCreateSection failed %x\n", status
);
1043 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
, sizeof(section_info
), NULL
);
1044 ok( !status
, "NtQuerySection failed err %x\n", status
);
1045 ok( section_info
.Attributes
== SEC_FILE
, "NtQuerySection wrong attr %08x\n",
1046 section_info
.Attributes
);
1047 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
1048 ok( section_info
.Size
.QuadPart
== 0x3452, "NtQuerySection wrong size %x%08x\n",
1049 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
1050 size
= map_size
.QuadPart
;
1051 status
= pNtMapViewOfSection( mapping
, GetCurrentProcess(), &ptr
, 0, 0, NULL
,
1052 &size
, ViewShare
, 0, PAGE_READONLY
);
1053 ok( !status
, "NtMapViewOfSection failed err %x\n", status
);
1054 pNtUnmapViewOfSection( GetCurrentProcess(), ptr
);
1055 size
= map_size
.QuadPart
+ 1;
1056 status
= pNtMapViewOfSection( mapping
, GetCurrentProcess(), &ptr
, 0, 0, NULL
,
1057 &size
, ViewShare
, 0, PAGE_READONLY
);
1058 ok( status
== STATUS_INVALID_VIEW_SIZE
, "NtMapViewOfSection failed err %x\n", status
);
1059 CloseHandle(mapping
);
1061 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1062 &map_size
, PAGE_READONLY
, SEC_COMMIT
, 0 );
1063 ok( !status
, "NtCreateSection failed %x\n", status
);
1064 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
, sizeof(section_info
), NULL
);
1065 ok( !status
, "NtQuerySection failed err %x\n", status
);
1066 ok( section_info
.Attributes
== SEC_COMMIT
, "NtQuerySection wrong attr %08x\n",
1067 section_info
.Attributes
);
1068 ok( section_info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", section_info
.BaseAddress
);
1069 ok( section_info
.Size
.QuadPart
== 0x4000, "NtQuerySection wrong size %x%08x\n",
1070 section_info
.Size
.u
.HighPart
, section_info
.Size
.u
.LowPart
);
1071 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
, sizeof(section_info
)-1, NULL
);
1072 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "NtQuerySection failed err %x\n", status
);
1073 status
= pNtQuerySection( mapping
, SectionBasicInformation
, §ion_info
, sizeof(section_info
)+1, NULL
);
1074 ok( !status
, "NtQuerySection failed err %x\n", status
);
1075 status
= pNtQuerySection( mapping
, SectionImageInformation
, &image_info
, sizeof(image_info
)-1, NULL
);
1076 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "NtQuerySection failed err %x\n", status
);
1077 status
= pNtQuerySection( mapping
, SectionImageInformation
, &image_info
, sizeof(image_info
), NULL
);
1078 ok( status
== STATUS_SECTION_NOT_IMAGE
, "NtQuerySection failed err %x\n", status
);
1079 status
= pNtQuerySection( mapping
, SectionImageInformation
, &image_info
, sizeof(image_info
)+1, NULL
);
1080 ok( status
== STATUS_SECTION_NOT_IMAGE
, "NtQuerySection failed err %x\n", status
);
1081 CloseHandle(mapping
);
1083 SetFilePointer(file
, 0, NULL
, FILE_BEGIN
);
1085 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1086 NULL
, PAGE_READONLY
, SEC_COMMIT
, file
);
1087 ok( status
== STATUS_MAPPED_FILE_SIZE_ZERO
, "NtCreateSection failed %x\n", status
);
1088 status
= pNtCreateSection( &mapping
, SECTION_QUERY
| SECTION_MAP_READ
, NULL
,
1089 NULL
, PAGE_READONLY
, SEC_IMAGE
, file
);
1090 ok( status
== STATUS_INVALID_FILE_FOR_SECTION
, "NtCreateSection failed %x\n", status
);
1093 DeleteFileA(testfile
);
1096 static void test_NtMapViewOfSection(void)
1100 static const char testfile
[] = "testfile.xxx";
1101 static const char data
[] = "test data for NtMapViewOfSection";
1102 char buffer
[sizeof(data
)];
1103 HANDLE file
, mapping
;
1106 DWORD status
, written
;
1107 SIZE_T size
, result
;
1108 LARGE_INTEGER offset
;
1110 if (!pNtMapViewOfSection
|| !pNtUnmapViewOfSection
)
1112 win_skip( "NtMapViewOfSection not available\n" );
1116 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1117 ok( file
!= INVALID_HANDLE_VALUE
, "Failed to create test file\n" );
1118 WriteFile( file
, data
, sizeof(data
), &written
, NULL
);
1119 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1120 SetEndOfFile( file
);
1122 /* read/write mapping */
1124 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1125 ok( mapping
!= 0, "CreateFileMapping failed\n" );
1127 hProcess
= create_target_process("sleep");
1128 ok(hProcess
!= NULL
, "Can't start process\n");
1132 offset
.QuadPart
= 0;
1133 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1134 ok( !status
, "NtMapViewOfSection failed status %x\n", status
);
1135 ok( !((ULONG_PTR
)ptr
& 0xffff), "returned memory %p is not aligned to 64k\n", ptr
);
1137 ret
= ReadProcessMemory( hProcess
, ptr
, buffer
, sizeof(buffer
), &result
);
1138 ok( ret
, "ReadProcessMemory failed\n" );
1139 ok( result
== sizeof(buffer
), "ReadProcessMemory didn't read all data (%lx)\n", result
);
1140 ok( !memcmp( buffer
, data
, sizeof(buffer
) ), "Wrong data read\n" );
1142 /* for some unknown reason NtMapViewOfSection fails with STATUS_NO_MEMORY when zero_bits != 0 ? */
1145 offset
.QuadPart
= 0;
1146 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1148 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1149 if (status
== STATUS_SUCCESS
)
1151 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1152 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1157 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1159 ok( status
== STATUS_NO_MEMORY
, "NtMapViewOfSection returned %x\n", status
);
1160 if (status
== STATUS_SUCCESS
)
1162 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1163 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1166 /* mapping at the same page conflicts */
1169 offset
.QuadPart
= 0;
1170 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1171 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1173 /* offset has to be aligned */
1176 offset
.QuadPart
= 1;
1177 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1178 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1180 /* ptr has to be aligned */
1181 ptr2
= (char *)ptr
+ 42;
1183 offset
.QuadPart
= 0;
1184 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1185 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1187 /* still not 64k aligned */
1188 ptr2
= (char *)ptr
+ 0x1000;
1190 offset
.QuadPart
= 0;
1191 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1192 ok( status
== STATUS_MAPPED_ALIGNMENT
, "NtMapViewOfSection returned %x\n", status
);
1194 /* zero_bits != 0 is not allowed when an address is set */
1195 ptr2
= (char *)ptr
+ 0x1000;
1197 offset
.QuadPart
= 0;
1198 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 12, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1199 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1201 ptr2
= (char *)ptr
+ 0x1000;
1203 offset
.QuadPart
= 0;
1204 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1205 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1207 ptr2
= (char *)ptr
+ 0x1001;
1209 offset
.QuadPart
= 0;
1210 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1211 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1213 ptr2
= (char *)ptr
+ 0x1000;
1215 offset
.QuadPart
= 1;
1216 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 16, 0, &offset
, &size
, 1, 0, PAGE_READWRITE
);
1217 ok( status
== STATUS_INVALID_PARAMETER_4
, "NtMapViewOfSection returned %x\n", status
);
1219 if (sizeof(void *) == sizeof(int) && (!pIsWow64Process
||
1220 !pIsWow64Process( GetCurrentProcess(), &is_wow64
) || !is_wow64
))
1222 /* new memory region conflicts with previous mapping */
1225 offset
.QuadPart
= 0;
1226 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1227 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1228 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1230 ptr2
= (char *)ptr
+ 42;
1232 offset
.QuadPart
= 0;
1233 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1234 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1235 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtMapViewOfSection returned %x\n", status
);
1237 /* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
1238 ptr2
= (char *)ptr
+ 0x1000;
1240 offset
.QuadPart
= 0;
1241 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1242 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1243 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1244 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1245 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1246 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1247 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1249 /* the address is rounded down if not on a page boundary */
1250 ptr2
= (char *)ptr
+ 0x1001;
1252 offset
.QuadPart
= 0;
1253 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1254 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1255 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1256 ok( (char *)ptr2
== (char *)ptr
+ 0x1000,
1257 "expected address %p, got %p\n", (char *)ptr
+ 0x1000, ptr2
);
1258 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1259 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1261 ptr2
= (char *)ptr
+ 0x2000;
1263 offset
.QuadPart
= 0;
1264 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1265 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1266 ok( status
== STATUS_SUCCESS
, "NtMapViewOfSection returned %x\n", status
);
1267 ok( (char *)ptr2
== (char *)ptr
+ 0x2000,
1268 "expected address %p, got %p\n", (char *)ptr
+ 0x2000, ptr2
);
1269 status
= pNtUnmapViewOfSection( hProcess
, ptr2
);
1270 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1274 ptr2
= (char *)ptr
+ 0x1000;
1276 offset
.QuadPart
= 0;
1277 status
= pNtMapViewOfSection( mapping
, hProcess
, &ptr2
, 0, 0, &offset
,
1278 &size
, 1, AT_ROUND_TO_PAGE
, PAGE_READWRITE
);
1280 ok( status
== STATUS_INVALID_PARAMETER_9
, "NtMapViewOfSection returned %x\n", status
);
1283 status
= pNtUnmapViewOfSection( hProcess
, ptr
);
1284 ok( !status
, "NtUnmapViewOfSection failed status %x\n", status
);
1286 CloseHandle( mapping
);
1287 CloseHandle( file
);
1288 DeleteFileA( testfile
);
1290 TerminateProcess(hProcess
, 0);
1291 CloseHandle(hProcess
);
1294 static void test_NtAreMappedFilesTheSame(void)
1296 static const char testfile
[] = "testfile.xxx";
1297 HANDLE file
, file2
, mapping
, map2
;
1300 char path
[MAX_PATH
];
1302 if (!pNtAreMappedFilesTheSame
)
1304 win_skip( "NtAreMappedFilesTheSame not available\n" );
1308 file
= CreateFileA( testfile
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1309 NULL
, CREATE_ALWAYS
, 0, 0 );
1310 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1311 SetFilePointer( file
, 4096, NULL
, FILE_BEGIN
);
1312 SetEndOfFile( file
);
1314 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
1315 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1317 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1318 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1320 file2
= CreateFileA( testfile
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1321 NULL
, OPEN_EXISTING
, 0, 0 );
1322 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1324 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1325 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1326 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1327 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1328 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1329 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1330 UnmapViewOfFile( ptr2
);
1332 ptr2
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1333 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1334 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1335 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1336 UnmapViewOfFile( ptr2
);
1337 CloseHandle( map2
);
1339 map2
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1340 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1341 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 4096 );
1342 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1343 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1344 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1345 UnmapViewOfFile( ptr2
);
1346 CloseHandle( map2
);
1347 CloseHandle( file2
);
1349 status
= pNtAreMappedFilesTheSame( ptr
, ptr
);
1350 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1351 "NtAreMappedFilesTheSame returned %x\n", status
);
1353 status
= pNtAreMappedFilesTheSame( ptr
, (char *)ptr
+ 30 );
1354 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_NOT_SAME_DEVICE
),
1355 "NtAreMappedFilesTheSame returned %x\n", status
);
1357 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1358 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1360 status
= pNtAreMappedFilesTheSame( ptr
, (void *)0xdeadbeef );
1361 ok( status
== STATUS_CONFLICTING_ADDRESSES
|| status
== STATUS_INVALID_ADDRESS
,
1362 "NtAreMappedFilesTheSame returned %x\n", status
);
1364 status
= pNtAreMappedFilesTheSame( ptr
, NULL
);
1365 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1367 status
= pNtAreMappedFilesTheSame( ptr
, (void *)GetProcessHeap() );
1368 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1370 status
= pNtAreMappedFilesTheSame( NULL
, NULL
);
1371 ok( status
== STATUS_INVALID_ADDRESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1373 ptr2
= VirtualAlloc( NULL
, 0x10000, MEM_COMMIT
, PAGE_READWRITE
);
1374 ok( ptr2
!= NULL
, "VirtualAlloc error %u\n", GetLastError() );
1375 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1376 ok( status
== STATUS_CONFLICTING_ADDRESSES
, "NtAreMappedFilesTheSame returned %x\n", status
);
1377 VirtualFree( ptr2
, 0, MEM_RELEASE
);
1379 UnmapViewOfFile( ptr
);
1380 CloseHandle( mapping
);
1381 CloseHandle( file
);
1383 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
1384 GetModuleHandleA("kernel32.dll") );
1385 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1386 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1387 GetModuleHandleA("kernel32.dll") );
1388 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1389 status
= pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
1390 (char *)GetModuleHandleA("kernel32.dll") + 4096 );
1391 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1393 GetSystemDirectoryA( path
, MAX_PATH
);
1394 strcat( path
, "\\kernel32.dll" );
1395 file
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1396 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1398 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 4096, NULL
);
1399 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1400 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4096 );
1401 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1402 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1403 ok( status
== STATUS_NOT_SAME_DEVICE
, "NtAreMappedFilesTheSame returned %x\n", status
);
1404 UnmapViewOfFile( ptr
);
1405 CloseHandle( mapping
);
1407 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1408 ok( mapping
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1409 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
1410 ok( ptr
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1411 status
= pNtAreMappedFilesTheSame( ptr
, GetModuleHandleA("kernel32.dll") );
1413 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1415 file2
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
1416 ok( file2
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError() );
1417 map2
= CreateFileMappingA( file2
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, NULL
);
1418 ok( map2
!= 0, "CreateFileMapping error %u\n", GetLastError() );
1419 ptr2
= MapViewOfFile( map2
, FILE_MAP_READ
, 0, 0, 0 );
1420 ok( ptr2
!= NULL
, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
1421 status
= pNtAreMappedFilesTheSame( ptr
, ptr2
);
1422 ok( status
== STATUS_SUCCESS
, "NtAreMappedFilesTheSame returned %x\n", status
);
1423 UnmapViewOfFile( ptr2
);
1424 CloseHandle( map2
);
1425 CloseHandle( file2
);
1427 UnmapViewOfFile( ptr
);
1428 CloseHandle( mapping
);
1430 CloseHandle( file
);
1431 DeleteFileA( testfile
);
1434 static void test_CreateFileMapping(void)
1436 HANDLE handle
, handle2
;
1438 /* test case sensitivity */
1440 SetLastError(0xdeadbeef);
1441 handle
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1442 "Wine Test Mapping");
1443 ok( handle
!= NULL
, "CreateFileMapping failed with error %u\n", GetLastError());
1444 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1446 SetLastError(0xdeadbeef);
1447 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1448 "Wine Test Mapping");
1449 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1450 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
1451 CloseHandle( handle2
);
1453 SetLastError(0xdeadbeef);
1454 handle2
= CreateFileMappingA( INVALID_HANDLE_VALUE
, NULL
, SEC_COMMIT
| PAGE_READWRITE
, 0, 0x1000,
1455 "WINE TEST MAPPING");
1456 ok( handle2
!= NULL
, "CreateFileMapping failed with error %d\n", GetLastError());
1457 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1458 CloseHandle( handle2
);
1460 SetLastError(0xdeadbeef);
1461 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "Wine Test Mapping");
1462 ok( handle2
!= NULL
, "OpenFileMapping failed with error %d\n", GetLastError());
1463 CloseHandle( handle2
);
1465 SetLastError(0xdeadbeef);
1466 handle2
= OpenFileMappingA( FILE_MAP_ALL_ACCESS
, FALSE
, "WINE TEST MAPPING");
1467 ok( !handle2
, "OpenFileMapping succeeded\n");
1468 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
1470 CloseHandle( handle
);
1473 static void test_IsBadReadPtr(void)
1476 void *ptr
= (void *)0xdeadbeef;
1479 ret
= IsBadReadPtr(NULL
, 0);
1480 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1482 ret
= IsBadReadPtr(NULL
, 1);
1483 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1485 ret
= IsBadReadPtr(ptr
, 0);
1486 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1488 ret
= IsBadReadPtr(ptr
, 1);
1489 ok(ret
== TRUE
, "Expected IsBadReadPtr to return TRUE, got %d\n", ret
);
1491 ret
= IsBadReadPtr(&stackvar
, 0);
1492 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1494 ret
= IsBadReadPtr(&stackvar
, sizeof(char));
1495 ok(ret
== FALSE
, "Expected IsBadReadPtr to return FALSE, got %d\n", ret
);
1498 static void test_IsBadWritePtr(void)
1501 void *ptr
= (void *)0xdeadbeef;
1504 ret
= IsBadWritePtr(NULL
, 0);
1505 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1507 ret
= IsBadWritePtr(NULL
, 1);
1508 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1510 ret
= IsBadWritePtr(ptr
, 0);
1511 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1513 ret
= IsBadWritePtr(ptr
, 1);
1514 ok(ret
== TRUE
, "Expected IsBadWritePtr to return TRUE, got %d\n", ret
);
1516 ret
= IsBadWritePtr(&stackval
, 0);
1517 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1519 ret
= IsBadWritePtr(&stackval
, sizeof(char));
1520 ok(ret
== FALSE
, "Expected IsBadWritePtr to return FALSE, got %d\n", ret
);
1523 static void test_IsBadCodePtr(void)
1526 void *ptr
= (void *)0xdeadbeef;
1529 ret
= IsBadCodePtr(NULL
);
1530 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1532 ret
= IsBadCodePtr(ptr
);
1533 ok(ret
== TRUE
, "Expected IsBadCodePtr to return TRUE, got %d\n", ret
);
1535 ret
= IsBadCodePtr((void *)&stackval
);
1536 ok(ret
== FALSE
, "Expected IsBadCodePtr to return FALSE, got %d\n", ret
);
1539 static void test_write_watch(void)
1541 static const char pipename
[] = "\\\\.\\pipe\\test_write_watch_pipe";
1542 static const char testdata
[] = "Hello World";
1543 DWORD ret
, size
, old_prot
, num_bytes
;
1544 MEMORY_BASIC_INFORMATION info
;
1545 HANDLE readpipe
, writepipe
;
1546 OVERLAPPED overlapped
;
1553 if (!pGetWriteWatch
|| !pResetWriteWatch
)
1555 win_skip( "GetWriteWatch not supported\n" );
1560 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1562 (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
1564 win_skip( "MEM_WRITE_WATCH not supported\n" );
1567 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1568 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1569 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1570 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1571 ok( info
.AllocationProtect
== PAGE_READWRITE
, "wrong AllocationProtect %x\n", info
.AllocationProtect
);
1572 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1573 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1574 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1575 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
1578 SetLastError( 0xdeadbeef );
1579 ret
= pGetWriteWatch( 0, NULL
, size
, results
, &count
, &pagesize
);
1580 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1581 ok( GetLastError() == ERROR_INVALID_PARAMETER
||
1582 broken( GetLastError() == 0xdeadbeef ), /* win98 */
1583 "wrong error %u\n", GetLastError() );
1585 SetLastError( 0xdeadbeef );
1586 ret
= pGetWriteWatch( 0, GetModuleHandleW(NULL
), size
, results
, &count
, &pagesize
);
1589 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1590 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1594 ok( count
== 0, "wrong count %lu\n", count
);
1597 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1598 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1599 ok( count
== 0, "wrong count %lu\n", count
);
1601 base
[pagesize
+ 1] = 0x44;
1604 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1605 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1606 ok( count
== 1, "wrong count %lu\n", count
);
1607 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1610 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1611 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1612 ok( count
== 1, "wrong count %lu\n", count
);
1613 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1616 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1617 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1618 ok( count
== 0, "wrong count %lu\n", count
);
1620 base
[2*pagesize
+ 3] = 0x11;
1621 base
[4*pagesize
+ 8] = 0x11;
1624 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1625 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1626 ok( count
== 2, "wrong count %lu\n", count
);
1627 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1628 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1631 ret
= pGetWriteWatch( 0, base
+ 3*pagesize
, 2*pagesize
, results
, &count
, &pagesize
);
1632 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1633 ok( count
== 1, "wrong count %lu\n", count
);
1634 ok( results
[0] == base
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1636 ret
= pResetWriteWatch( base
, 3*pagesize
);
1637 ok( !ret
, "pResetWriteWatch failed %u\n", GetLastError() );
1640 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1641 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1642 ok( count
== 1, "wrong count %lu\n", count
);
1643 ok( results
[0] == base
+ 4*pagesize
, "wrong result %p\n", results
[0] );
1645 *(DWORD
*)(base
+ 2*pagesize
- 2) = 0xdeadbeef;
1648 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1649 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1650 ok( count
== 3, "wrong count %lu\n", count
);
1651 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1652 ok( results
[1] == base
+ 2*pagesize
, "wrong result %p\n", results
[1] );
1653 ok( results
[2] == base
+ 4*pagesize
, "wrong result %p\n", results
[2] );
1656 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1657 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1658 ok( count
== 1, "wrong count %lu\n", count
);
1659 ok( results
[0] == base
+ pagesize
, "wrong result %p\n", results
[0] );
1662 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1663 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1664 ok( count
== 2, "wrong count %lu\n", count
);
1665 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1666 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
1668 /* changing protections doesn't affect watches */
1670 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READONLY
, &old_prot
);
1671 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1672 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1674 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
1675 ok(ret
, "VirtualQuery failed %u\n", GetLastError());
1676 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
1677 ok( info
.RegionSize
== 3*pagesize
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
1678 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
1679 ok( info
.Protect
== PAGE_READONLY
, "wrong Protect 0x%x\n", info
.Protect
);
1681 ret
= VirtualProtect( base
, 3*pagesize
, PAGE_READWRITE
, &old_prot
);
1682 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1683 ok( old_prot
== PAGE_READONLY
, "wrong old prot %x\n", old_prot
);
1686 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1687 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1688 ok( count
== 2, "wrong count %lu\n", count
);
1689 ok( results
[0] == base
+ 2*pagesize
, "wrong result %p\n", results
[0] );
1690 ok( results
[1] == base
+ 4*pagesize
, "wrong result %p\n", results
[1] );
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
== size
, "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_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
1699 /* ReadFile should trigger write watches */
1701 memset( &overlapped
, 0, sizeof(overlapped
) );
1702 overlapped
.hEvent
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1704 readpipe
= CreateNamedPipeA( pipename
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_INBOUND
,
1705 PIPE_TYPE_BYTE
| PIPE_WAIT
, 1, 1024, 1024,
1706 NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1707 ok( readpipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipeA failed %u\n", GetLastError() );
1709 success
= ConnectNamedPipe( readpipe
, &overlapped
);
1710 ok( !success
, "ConnectNamedPipe unexpectedly succeeded\n" );
1711 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1713 writepipe
= CreateFileA( pipename
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
1714 ok( writepipe
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %u\n", GetLastError() );
1716 ret
= WaitForSingleObject( overlapped
.hEvent
, 1000 );
1717 ok( ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", ret
);
1719 memset( base
, 0, size
);
1722 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1723 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1724 ok( count
== 16, "wrong count %lu\n", count
);
1726 success
= ReadFile( readpipe
, base
, size
, NULL
, &overlapped
);
1727 ok( !success
, "ReadFile unexpectedly succeeded\n" );
1728 ok( GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
1731 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1732 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1733 ok( count
== 16, "wrong count %lu\n", count
);
1736 success
= WriteFile( writepipe
, testdata
, sizeof(testdata
), &num_bytes
, NULL
);
1737 ok( success
, "WriteFile failed %u\n", GetLastError() );
1738 ok( num_bytes
== sizeof(testdata
), "wrong number of bytes written\n" );
1741 success
= GetOverlappedResult( readpipe
, &overlapped
, &num_bytes
, TRUE
);
1742 ok( success
, "GetOverlappedResult failed %u\n", GetLastError() );
1743 ok( num_bytes
== sizeof(testdata
), "wrong number of bytes read\n" );
1744 ok( !memcmp( base
, testdata
, sizeof(testdata
)), "didn't receive expected data\n" );
1747 memset( results
, 0, sizeof(results
) );
1748 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
1749 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1750 todo_wine
ok( count
== 1, "wrong count %lu\n", count
);
1751 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
1753 CloseHandle( readpipe
);
1754 CloseHandle( writepipe
);
1755 CloseHandle( overlapped
.hEvent
);
1757 /* some invalid parameter tests */
1759 SetLastError( 0xdeadbeef );
1761 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1764 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1765 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1767 SetLastError( 0xdeadbeef );
1768 ret
= pGetWriteWatch( 0, base
, size
, results
, NULL
, &pagesize
);
1769 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1770 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1772 SetLastError( 0xdeadbeef );
1774 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, NULL
);
1775 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1776 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1778 SetLastError( 0xdeadbeef );
1780 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1781 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1782 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1784 SetLastError( 0xdeadbeef );
1786 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1787 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1788 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1790 SetLastError( 0xdeadbeef );
1792 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1793 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1794 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1796 SetLastError( 0xdeadbeef );
1798 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1799 ok( ret
== ~0u, "GetWriteWatch succeeded %u\n", ret
);
1800 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1802 SetLastError( 0xdeadbeef );
1804 ret
= pGetWriteWatch( 0, base
, size
* 2, results
, &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( 0, base
+ size
- pagesize
, pagesize
+ 1, 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 );
1815 ret
= pResetWriteWatch( base
, 0 );
1816 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1817 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1819 SetLastError( 0xdeadbeef );
1820 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1821 ok( ret
== ~0u, "ResetWriteWatch succeeded %u\n", ret
);
1822 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1824 else /* win98 is completely different */
1826 SetLastError( 0xdeadbeef );
1828 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1829 ok( ret
== ERROR_INVALID_PARAMETER
, "GetWriteWatch succeeded %u\n", ret
);
1830 ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
1833 ret
= pGetWriteWatch( 0, base
, size
, NULL
, &count
, &pagesize
);
1834 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1837 ret
= pGetWriteWatch( 0xdeadbeef, base
, size
, results
, &count
, &pagesize
);
1838 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1841 ret
= pGetWriteWatch( 0, base
, 0, results
, &count
, &pagesize
);
1842 ok( !ret
, "GetWriteWatch failed %u\n", ret
);
1844 ret
= pResetWriteWatch( base
, 0 );
1845 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1847 ret
= pResetWriteWatch( GetModuleHandleW(NULL
), size
);
1848 ok( !ret
, "ResetWriteWatch failed %u\n", ret
);
1851 VirtualFree( base
, 0, MEM_RELEASE
);
1853 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
1854 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1855 VirtualFree( base
, 0, MEM_RELEASE
);
1857 base
= VirtualAlloc( 0, size
, MEM_WRITE_WATCH
, PAGE_READWRITE
);
1858 ok( !base
, "VirtualAlloc succeeded\n" );
1859 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1861 /* initial protect doesn't matter */
1863 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_WRITE_WATCH
, PAGE_NOACCESS
);
1864 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1865 base
= VirtualAlloc( base
, size
, MEM_COMMIT
, PAGE_NOACCESS
);
1866 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1869 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1870 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1871 ok( count
== 0, "wrong count %lu\n", count
);
1873 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_READWRITE
, &old_prot
);
1874 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1875 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
1877 base
[5*pagesize
+ 200] = 3;
1879 ret
= VirtualProtect( base
, 6*pagesize
, PAGE_NOACCESS
, &old_prot
);
1880 ok( ret
, "VirtualProtect failed error %u\n", GetLastError() );
1881 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
1884 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1885 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1886 ok( count
== 1, "wrong count %lu\n", count
);
1887 ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1889 ret
= VirtualFree( base
, size
, MEM_DECOMMIT
);
1890 ok( ret
, "VirtualFree failed %u\n", GetLastError() );
1893 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
1894 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
1895 ok( count
== 1 || broken(count
== 0), /* win98 */
1896 "wrong count %lu\n", count
);
1897 if (count
) ok( results
[0] == base
+ 5*pagesize
, "wrong result %p\n", results
[0] );
1899 VirtualFree( base
, 0, MEM_RELEASE
);
1902 #if defined(__i386__) || defined(__x86_64__)
1904 static DWORD WINAPI
stack_commit_func( void *arg
)
1906 volatile char *p
= (char *)&p
;
1908 /* trigger all guard pages, to ensure that the pages are committed */
1909 while (p
>= (char *)NtCurrentTeb()->DeallocationStack
+ 4 * 0x1000)
1915 ok( arg
== (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg
);
1919 static void test_stack_commit(void)
1922 static const char code_call_on_stack
[] = {
1923 0x55, /* pushl %ebp */
1924 0x56, /* pushl %esi */
1925 0x89, 0xe6, /* movl %esp,%esi */
1926 0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */
1927 0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */
1928 0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */
1929 0x83, 0xe0, 0xf0, /* andl $~15,%eax */
1930 0x83, 0xe8, 0x0c, /* subl $12,%eax */
1931 0x89, 0xc4, /* movl %eax,%esp */
1932 0x52, /* pushl %edx */
1933 0x31, 0xed, /* xorl %ebp,%ebp */
1934 0xff, 0xd1, /* call *%ecx */
1935 0x89, 0xf4, /* movl %esi,%esp */
1936 0x5e, /* popl %esi */
1937 0x5d, /* popl %ebp */
1938 0xc2, 0x0c, 0x00 }; /* ret $12 */
1940 static const char code_call_on_stack
[] = {
1941 0x55, /* pushq %rbp */
1942 0x48, 0x89, 0xe5, /* movq %rsp,%rbp */
1943 /* %rcx - func, %rdx - arg, %r8 - stack */
1944 0x48, 0x87, 0xca, /* xchgq %rcx,%rdx */
1945 0x49, 0x83, 0xe0, 0xf0, /* andq $~15,%r8 */
1946 0x49, 0x83, 0xe8, 0x20, /* subq $0x20,%r8 */
1947 0x4c, 0x89, 0xc4, /* movq %r8,%rsp */
1948 0xff, 0xd2, /* callq *%rdx */
1949 0x48, 0x89, 0xec, /* movq %rbp,%rsp */
1950 0x5d, /* popq %rbp */
1953 DWORD (WINAPI
*call_on_stack
)( DWORD (WINAPI
*func
)(void *), void *arg
, void *stack
);
1954 void *old_stack
, *old_stack_base
, *old_stack_limit
;
1955 void *new_stack
, *new_stack_base
;
1958 call_on_stack
= VirtualAlloc( 0, 0x1000, MEM_RESERVE
| MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
1959 ok( call_on_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1960 memcpy( call_on_stack
, code_call_on_stack
, sizeof(code_call_on_stack
) );
1962 /* allocate a new stack, only the first guard page is committed */
1963 new_stack
= VirtualAlloc( 0, 0x400000, MEM_RESERVE
, PAGE_READWRITE
);
1964 ok( new_stack
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
1965 new_stack_base
= (char *)new_stack
+ 0x400000;
1966 VirtualAlloc( (char *)new_stack_base
- 0x1000, 0x1000, MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
1968 old_stack
= NtCurrentTeb()->DeallocationStack
;
1969 old_stack_base
= NtCurrentTeb()->Tib
.StackBase
;
1970 old_stack_limit
= NtCurrentTeb()->Tib
.StackLimit
;
1972 NtCurrentTeb()->DeallocationStack
= new_stack
;
1973 NtCurrentTeb()->Tib
.StackBase
= new_stack_base
;
1974 NtCurrentTeb()->Tib
.StackLimit
= new_stack_base
;
1976 result
= call_on_stack( stack_commit_func
, (void *)0xdeadbeef, new_stack_base
);
1978 NtCurrentTeb()->DeallocationStack
= old_stack
;
1979 NtCurrentTeb()->Tib
.StackBase
= old_stack_base
;
1980 NtCurrentTeb()->Tib
.StackLimit
= old_stack_limit
;
1982 ok( result
== 42, "expected 42, got %u\n", result
);
1984 VirtualFree( new_stack
, 0, MEM_RELEASE
);
1985 VirtualFree( call_on_stack
, 0, MEM_RELEASE
);
1988 #endif /* defined(__i386__) || defined(__x86_64__) */
1991 static LONG num_guard_page_calls
;
1993 static DWORD
guard_page_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
1994 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
1996 trace( "exception: %08x flags:%x addr:%p\n",
1997 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
);
1999 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2000 ok( rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
, "ExceptionCode is %08x instead of %08x\n",
2001 rec
->ExceptionCode
, STATUS_GUARD_PAGE_VIOLATION
);
2003 InterlockedIncrement( &num_guard_page_calls
);
2004 *(int *)rec
->ExceptionInformation
[1] += 0x100;
2006 return ExceptionContinueExecution
;
2009 static void test_guard_page(void)
2011 EXCEPTION_REGISTRATION_RECORD frame
;
2012 MEMORY_BASIC_INFORMATION info
;
2013 DWORD ret
, size
, old_prot
;
2014 int *value
, old_value
;
2022 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
| PAGE_GUARD
);
2023 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2024 value
= (int *)base
;
2026 /* verify info structure */
2027 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2028 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
2029 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
2030 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
2031 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
2032 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
2033 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
2034 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
2036 /* put some initial value into the memory */
2037 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2038 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2039 ok( old_prot
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong old prot %x\n", old_prot
);
2044 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2045 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2046 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2048 /* test behaviour of VirtualLock - first attempt should fail */
2049 SetLastError( 0xdeadbeef );
2050 success
= VirtualLock( base
, size
);
2051 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
2053 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
2055 success
= VirtualLock( base
, size
);
2057 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2060 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2061 success
= VirtualUnlock( base
, size
);
2062 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2065 /* check info structure again, PAGE_GUARD should be removed now */
2066 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2067 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
2068 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
2069 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
2070 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
2071 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
2073 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
2074 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
2076 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2077 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2079 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2081 /* test directly accessing the memory - we need to setup an exception handler first */
2082 frame
.Handler
= guard_page_handler
;
2083 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2084 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2086 InterlockedExchange( &num_guard_page_calls
, 0 );
2087 InterlockedExchange( &old_value
, *value
); /* exception handler increments value by 0x100 */
2089 ok( old_value
== 0x101, "memory block contains wrong value, expected 0x101, got 0x%x\n", old_value
);
2090 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2092 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2094 /* check info structure again, PAGE_GUARD should be removed now */
2095 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2096 ok( ret
, "VirtualQuery failed %u\n", GetLastError());
2097 ok( info
.Protect
== PAGE_READWRITE
, "wrong Protect 0x%x\n", info
.Protect
);
2099 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2100 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2101 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2103 /* test accessing second integer in memory */
2104 frame
.Handler
= guard_page_handler
;
2105 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2106 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2108 InterlockedExchange( &num_guard_page_calls
, 0 );
2109 old_value
= *(value
+ 1);
2110 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
2111 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
2112 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2114 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2116 success
= VirtualLock( base
, size
);
2117 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2120 ok( *value
== 2, "memory block contains wrong value, expected 2, got 0x%x\n", *value
);
2121 success
= VirtualUnlock( base
, size
);
2122 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2125 VirtualFree( base
, 0, MEM_RELEASE
);
2127 /* combined guard page / write watch tests */
2128 if (!pGetWriteWatch
|| !pResetWriteWatch
)
2130 win_skip( "GetWriteWatch not supported, skipping combined guard page / write watch tests\n" );
2134 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
| PAGE_GUARD
);
2135 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
2137 win_skip( "MEM_WRITE_WATCH not supported\n" );
2140 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2141 value
= (int *)base
;
2143 ret
= VirtualQuery( base
, &info
, sizeof(info
) );
2144 ok( ret
, "VirtualQuery failed %u\n", GetLastError() );
2145 ok( info
.BaseAddress
== base
, "BaseAddress %p instead of %p\n", info
.BaseAddress
, base
);
2146 ok( info
.AllocationProtect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong AllocationProtect %x\n", info
.AllocationProtect
);
2147 ok( info
.RegionSize
== size
, "wrong RegionSize 0x%lx\n", info
.RegionSize
);
2148 ok( info
.State
== MEM_COMMIT
, "wrong State 0x%x\n", info
.State
);
2149 ok( info
.Protect
== (PAGE_READWRITE
| PAGE_GUARD
), "wrong Protect 0x%x\n", info
.Protect
);
2150 ok( info
.Type
== MEM_PRIVATE
, "wrong Type 0x%x\n", info
.Type
);
2153 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
2154 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2155 ok( count
== 0, "wrong count %lu\n", count
);
2157 /* writing to a page should trigger should trigger guard page, even if write watch is set */
2158 frame
.Handler
= guard_page_handler
;
2159 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2160 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2162 InterlockedExchange( &num_guard_page_calls
, 0 );
2165 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2167 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2170 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2171 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2172 ok( count
== 1, "wrong count %lu\n", count
);
2173 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2175 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2176 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2178 /* write watch is triggered from inside of the guard page handler */
2179 frame
.Handler
= guard_page_handler
;
2180 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2181 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2183 InterlockedExchange( &num_guard_page_calls
, 0 );
2184 old_value
= *(value
+ 1); /* doesn't trigger write watch */
2185 ok( old_value
== 0x102, "memory block contains wrong value, expected 0x102, got 0x%x\n", old_value
);
2186 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2187 ok( num_guard_page_calls
== 1, "expected one callback of guard page handler, got %d calls\n", num_guard_page_calls
);
2189 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2192 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2193 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2194 ok( count
== 1, "wrong count %lu\n", count
);
2195 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2197 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2198 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2200 /* test behaviour of VirtualLock - first attempt should fail without triggering write watches */
2201 SetLastError( 0xdeadbeef );
2202 success
= VirtualLock( base
, size
);
2203 ok( !success
, "VirtualLock unexpectedly succeeded\n" );
2205 ok( GetLastError() == STATUS_GUARD_PAGE_VIOLATION
, "wrong error %u\n", GetLastError() );
2208 ret
= pGetWriteWatch( 0, base
, size
, results
, &count
, &pagesize
);
2209 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2210 ok( count
== 0, "wrong count %lu\n", count
);
2212 success
= VirtualLock( base
, size
);
2214 ok( success
, "VirtualLock failed %u\n", GetLastError() );
2217 ok( *value
== 1, "memory block contains wrong value, expected 1, got 0x%x\n", *value
);
2218 success
= VirtualUnlock( base
, size
);
2219 ok( success
, "VirtualUnlock failed %u\n", GetLastError() );
2223 results
[0] = (void *)0xdeadbeef;
2224 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2225 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2227 ok( count
== 1 || broken(count
== 0) /* Windows 8 */, "wrong count %lu\n", count
);
2229 ok( results
[0] == base
|| broken(results
[0] == (void *)0xdeadbeef) /* Windows 8 */, "wrong result %p\n", results
[0] );
2231 VirtualFree( base
, 0, MEM_RELEASE
);
2234 static LONG num_execute_fault_calls
;
2236 static DWORD
execute_fault_seh_handler( EXCEPTION_RECORD
*rec
, EXCEPTION_REGISTRATION_RECORD
*frame
,
2237 CONTEXT
*context
, EXCEPTION_REGISTRATION_RECORD
**dispatcher
)
2239 ULONG flags
= MEM_EXECUTE_OPTION_ENABLE
;
2242 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2243 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2244 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2246 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2247 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
|| rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
,
2248 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec
->ExceptionCode
);
2250 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &flags
, sizeof(flags
), NULL
);
2252 if (rec
->ExceptionCode
== STATUS_GUARD_PAGE_VIOLATION
)
2255 err
= IsProcessorFeaturePresent( PF_NX_ENABLED
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2256 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2257 (DWORD
)rec
->ExceptionInformation
[0], err
);
2259 InterlockedIncrement( &num_guard_page_calls
);
2261 else if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2266 err
= (flags
& MEM_EXECUTE_OPTION_DISABLE
) ? EXCEPTION_EXECUTE_FAULT
: EXCEPTION_READ_FAULT
;
2267 ok( rec
->ExceptionInformation
[0] == err
, "ExceptionInformation[0] is %d instead of %d\n",
2268 (DWORD
)rec
->ExceptionInformation
[0], err
);
2270 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2271 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2272 ok( old_prot
== PAGE_READWRITE
, "wrong old prot %x\n", old_prot
);
2274 InterlockedIncrement( &num_execute_fault_calls
);
2277 return ExceptionContinueExecution
;
2280 static LONG CALLBACK
execute_fault_vec_handler( EXCEPTION_POINTERS
*ExceptionInfo
)
2282 PEXCEPTION_RECORD rec
= ExceptionInfo
->ExceptionRecord
;
2286 trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
2287 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
2288 rec
->ExceptionInformation
[0], (void *)rec
->ExceptionInformation
[1] );
2290 ok( rec
->NumberParameters
== 2, "NumberParameters is %d instead of 2\n", rec
->NumberParameters
);
2291 ok( rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
,
2292 "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec
->ExceptionCode
);
2294 if (rec
->ExceptionCode
== STATUS_ACCESS_VIOLATION
)
2295 InterlockedIncrement( &num_execute_fault_calls
);
2297 if (rec
->ExceptionInformation
[0] == EXCEPTION_READ_FAULT
)
2298 return EXCEPTION_CONTINUE_SEARCH
;
2300 success
= VirtualProtect( (void *)rec
->ExceptionInformation
[1], 16, PAGE_EXECUTE_READWRITE
, &old_prot
);
2301 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2302 ok( old_prot
== PAGE_NOACCESS
, "wrong old prot %x\n", old_prot
);
2304 return EXCEPTION_CONTINUE_EXECUTION
;
2307 static inline DWORD
send_message_excpt( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2309 EXCEPTION_REGISTRATION_RECORD frame
;
2312 frame
.Handler
= execute_fault_seh_handler
;
2313 frame
.Prev
= NtCurrentTeb()->Tib
.ExceptionList
;
2314 NtCurrentTeb()->Tib
.ExceptionList
= &frame
;
2316 InterlockedExchange( &num_guard_page_calls
, 0 );
2317 InterlockedExchange( &num_execute_fault_calls
, 0 );
2318 ret
= SendMessageA( hWnd
, uMsg
, wParam
, lParam
);
2320 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2325 static inline DWORD
call_proc_excpt( DWORD (CALLBACK
*code
)(void *), void *arg
)
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 );
2338 NtCurrentTeb()->Tib
.ExceptionList
= frame
.Prev
;
2343 static LRESULT CALLBACK
jmp_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2345 if (uMsg
== WM_USER
)
2348 return DefWindowProcA( hWnd
, uMsg
, wParam
, lParam
);
2351 static LRESULT CALLBACK
atl_test_func( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2353 DWORD arg
= (DWORD
)hWnd
;
2354 if (uMsg
== WM_USER
)
2355 ok( arg
== 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg
);
2357 ok( arg
!= 0x11223344, "arg is unexpectedly 0x11223344\n" );
2361 static DWORD CALLBACK
atl5_test_func( void )
2366 static void test_atl_thunk_emulation( ULONG dep_flags
)
2368 static const char code_jmp
[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
2369 static const char code_atl1
[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2370 static const char code_atl2
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
2371 static const char code_atl3
[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1};
2372 static const char code_atl4
[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
2373 static const char code_atl5
[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04};
2374 static const char cls_name
[] = "atl_thunk_class";
2375 DWORD ret
, size
, old_prot
;
2376 ULONG old_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2377 BOOL success
, restore_flags
= FALSE
;
2385 trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2387 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
), NULL
);
2388 if (old_flags
!= dep_flags
)
2390 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &dep_flags
, sizeof(dep_flags
) );
2391 if (ret
== STATUS_INVALID_INFO_CLASS
) /* Windows 2000 */
2393 win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags
);
2396 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2397 restore_flags
= TRUE
;
2401 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
2402 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2404 /* Check result of GetProcessDEPPolicy */
2405 if (!pGetProcessDEPPolicy
)
2406 win_skip( "GetProcessDEPPolicy not supported\n" );
2409 BOOL (WINAPI
*get_dep_policy
)(HANDLE
, LPDWORD
, PBOOL
) = (void *)base
;
2410 BOOL policy_permanent
= 0xdeadbeef;
2411 DWORD policy_flags
= 0xdeadbeef;
2413 /* GetProcessDEPPolicy crashes on Windows when a NULL pointer is passed.
2414 * Moreover this function has a bug on Windows 8, which has the effect that
2415 * policy_permanent is set to the content of the CL register instead of 0,
2416 * when the policy is not permanent. To detect that we use an assembler
2417 * wrapper to call the function. */
2419 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2420 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)pGetProcessDEPPolicy
- (DWORD_PTR
)(base
+ 10);
2422 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2423 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2425 success
= get_dep_policy( GetCurrentProcess(), &policy_flags
, &policy_permanent
);
2426 ok( success
, "GetProcessDEPPolicy failed %u\n", GetLastError() );
2429 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2430 ret
|= PROCESS_DEP_ENABLE
;
2431 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
)
2432 ret
|= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
;
2434 ok( policy_flags
== ret
, "expected policy flags %d, got %d\n", ret
, policy_flags
);
2435 ok( !policy_permanent
|| broken(policy_permanent
== 0x44),
2436 "expected policy permanent FALSE, got %d\n", policy_permanent
);
2439 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2440 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2442 /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
2443 * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
2444 * where it is active, so that application which depend on that still work properly.
2445 * We have no exception handler enabled yet, so give proper EXECUTE permissions to
2446 * prevent crashes while creating the window. */
2448 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2449 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2451 memset( &wc
, 0, sizeof(wc
) );
2452 wc
.cbSize
= sizeof(wc
);
2453 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2454 wc
.hInstance
= GetModuleHandleA( 0 );
2455 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2456 wc
.hbrBackground
= NULL
;
2457 wc
.lpszClassName
= cls_name
;
2458 wc
.lpfnWndProc
= (WNDPROC
)base
;
2459 success
= RegisterClassExA(&wc
) != 0;
2460 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2462 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2463 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2465 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2466 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2468 /* At first try with an instruction which is not recognized as proper ATL thunk
2469 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2470 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2472 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2473 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2475 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2476 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2477 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2478 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !IsProcessorFeaturePresent( PF_NX_ENABLED
))
2480 trace( "DEP hardware support is not available\n" );
2481 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2482 dep_flags
= MEM_EXECUTE_OPTION_ENABLE
;
2484 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2486 trace( "DEP hardware support is available\n" );
2487 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2490 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2492 /* Now a bit more complicated, the page containing the code is protected with
2493 * PAGE_GUARD memory protection. */
2495 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2496 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2498 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2499 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2500 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2501 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2502 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2504 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2506 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2507 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2508 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2509 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2511 /* Now test with a proper ATL thunk instruction. */
2513 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2514 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2516 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2517 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2519 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2520 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2522 /* Try executing with PAGE_READWRITE protection. */
2524 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2525 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2527 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2528 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2529 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2530 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2531 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2533 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2535 /* Now a bit more complicated, the page containing the code is protected with
2536 * PAGE_GUARD memory protection. */
2538 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2539 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2541 /* the same, but with PAGE_GUARD set */
2542 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2543 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2544 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2545 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2546 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2548 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2550 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2551 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2552 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2553 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2555 /* The following test shows that on Windows, even a vectored exception handler
2556 * cannot intercept internal exceptions thrown by the ATL thunk emulation layer. */
2558 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && !(dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2560 if (pRtlAddVectoredExceptionHandler
&& pRtlRemoveVectoredExceptionHandler
)
2562 PVOID vectored_handler
;
2564 success
= VirtualProtect( base
, size
, PAGE_NOACCESS
, &old_prot
);
2565 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2567 vectored_handler
= pRtlAddVectoredExceptionHandler( TRUE
, &execute_fault_vec_handler
);
2568 ok( vectored_handler
!= 0, "RtlAddVectoredExceptionHandler failed\n" );
2570 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2572 pRtlRemoveVectoredExceptionHandler( vectored_handler
);
2574 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2575 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2578 win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" );
2581 /* Test alternative ATL thunk instructions. */
2583 memcpy( base
, code_atl2
, sizeof(code_atl2
) );
2584 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 10);
2586 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2587 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2589 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2590 /* FIXME: we don't check the content of the register ECX yet */
2591 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2592 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2593 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2594 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2596 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2598 memcpy( base
, code_atl3
, sizeof(code_atl3
) );
2599 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2601 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2602 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2604 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2605 /* FIXME: we don't check the content of the registers ECX/EDX yet */
2606 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2607 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2608 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2609 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2611 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2613 memcpy( base
, code_atl4
, sizeof(code_atl4
) );
2614 *(DWORD
*)(base
+ 6) = (DWORD_PTR
)atl_test_func
;
2616 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2617 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2619 ret
= send_message_excpt( hWnd
, WM_USER
+ 1, 0, 0 );
2620 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2621 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2622 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2623 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2624 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2625 else if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2626 ok( num_execute_fault_calls
== 0 || broken(num_execute_fault_calls
== 1) /* Windows XP */,
2627 "expected no 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_atl5
, sizeof(code_atl5
) );
2633 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2634 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2636 ret
= (DWORD_PTR
)atl5_test_func
;
2637 ret
= call_proc_excpt( (void *)base
, &ret
- 1 );
2638 /* FIXME: We don't check the content of the registers EAX/ECX yet */
2639 ok( ret
== 44, "call returned wrong result, expected 44, 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 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2651 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2652 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2654 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2655 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2657 DestroyWindow( hWnd
);
2659 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2660 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2662 VirtualFree( base
, 0, MEM_RELEASE
);
2664 /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */
2666 base
= VirtualAlloc( 0, size
, MEM_RESERVE
| MEM_COMMIT
| MEM_WRITE_WATCH
, PAGE_READWRITE
);
2667 if (!base
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_NOT_SUPPORTED
))
2669 win_skip( "MEM_WRITE_WATCH not supported\n" );
2672 ok( base
!= NULL
, "VirtualAlloc failed %u\n", GetLastError() );
2675 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2676 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2677 ok( count
== 0, "wrong count %lu\n", count
);
2679 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2680 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2683 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2684 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2685 ok( count
== 1, "wrong count %lu\n", count
);
2686 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2688 /* Create a new window class and associated Window (see above) */
2690 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2691 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2693 memset( &wc
, 0, sizeof(wc
) );
2694 wc
.cbSize
= sizeof(wc
);
2695 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2696 wc
.hInstance
= GetModuleHandleA( 0 );
2697 wc
.hCursor
= LoadCursorA( NULL
, (LPCSTR
)IDC_ARROW
);
2698 wc
.hbrBackground
= NULL
;
2699 wc
.lpszClassName
= cls_name
;
2700 wc
.lpfnWndProc
= (WNDPROC
)base
;
2701 success
= RegisterClassExA(&wc
) != 0;
2702 ok( success
, "RegisterClassExA failed %u\n", GetLastError() );
2704 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2705 ok( hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError() );
2707 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2708 ok( ret
== 42, "SendMessage returned unexpected result %d\n", ret
);
2711 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2712 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2713 ok( count
== 0, "wrong count %lu\n", count
);
2715 /* At first try with an instruction which is not recognized as proper ATL thunk
2716 * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
2717 * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
2719 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2720 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2722 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2723 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2724 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2725 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2726 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2728 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2731 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2732 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2733 ok( count
== 0, "wrong count %lu\n", count
);
2735 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2736 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2737 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2738 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2740 /* Now a bit more complicated, the page containing the code is protected with
2741 * PAGE_GUARD memory protection. */
2743 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2744 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2746 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2747 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2748 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2749 if (dep_flags
& MEM_EXECUTE_OPTION_DISABLE
)
2750 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2752 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2754 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2755 ok( ret
== 42, "call returned wrong result, expected 42, got %d\n", ret
);
2756 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2757 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2760 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2761 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2762 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2764 /* Now test with a proper ATL thunk instruction. */
2766 memcpy( base
, code_atl1
, sizeof(code_atl1
) );
2767 *(DWORD
*)(base
+ 9) = (DWORD_PTR
)atl_test_func
- (DWORD_PTR
)(base
+ 13);
2770 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2771 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2772 ok( count
== 1, "wrong count %lu\n", count
);
2773 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2775 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2776 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2778 ret
= SendMessageA(hWnd
, WM_USER
, 0, 0);
2779 ok( ret
== 43, "SendMessage returned unexpected result %d\n", ret
);
2781 /* Try executing with PAGE_READWRITE protection. */
2783 success
= VirtualProtect( base
, size
, PAGE_READWRITE
, &old_prot
);
2784 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2786 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2787 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2788 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2789 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2790 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2792 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2795 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2796 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2797 ok( count
== 0, "wrong count %lu\n", count
);
2799 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2800 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2801 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2802 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2804 /* Now a bit more complicated, the page containing the code is protected with
2805 * PAGE_GUARD memory protection. */
2807 success
= VirtualProtect( base
, size
, PAGE_READWRITE
| PAGE_GUARD
, &old_prot
);
2808 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2810 /* the same, but with PAGE_GUARD set */
2811 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2812 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2813 ok( num_guard_page_calls
== 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2814 if ((dep_flags
& MEM_EXECUTE_OPTION_DISABLE
) && (dep_flags
& MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
2815 ok( num_execute_fault_calls
== 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2817 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2819 ret
= send_message_excpt( hWnd
, WM_USER
, 0, 0 );
2820 ok( ret
== 43, "call returned wrong result, expected 43, got %d\n", ret
);
2821 ok( num_guard_page_calls
== 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls
);
2822 ok( num_execute_fault_calls
== 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls
);
2825 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2826 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2827 ok( count
== 0 || broken(count
== 1) /* Windows 8 */, "wrong count %lu\n", count
);
2829 /* Restore the JMP instruction, set to executable, and then destroy the Window */
2831 memcpy( base
, code_jmp
, sizeof(code_jmp
) );
2832 *(DWORD
*)(base
+ 1) = (DWORD_PTR
)jmp_test_func
- (DWORD_PTR
)(base
+ 5);
2835 ret
= pGetWriteWatch( WRITE_WATCH_FLAG_RESET
, base
, size
, results
, &count
, &pagesize
);
2836 ok( !ret
, "GetWriteWatch failed %u\n", GetLastError() );
2837 ok( count
== 1, "wrong count %lu\n", count
);
2838 ok( results
[0] == base
, "wrong result %p\n", results
[0] );
2840 success
= VirtualProtect( base
, size
, PAGE_EXECUTE_READWRITE
, &old_prot
);
2841 ok( success
, "VirtualProtect failed %u\n", GetLastError() );
2843 DestroyWindow( hWnd
);
2845 success
= UnregisterClassA( cls_name
, GetModuleHandleA(0) );
2846 ok( success
, "UnregisterClass failed %u\n", GetLastError() );
2848 VirtualFree( base
, 0, MEM_RELEASE
);
2853 ret
= NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &old_flags
, sizeof(old_flags
) );
2854 ok( !ret
, "NtSetInformationProcess failed with status %08x\n", ret
);
2858 #endif /* __i386__ */
2860 static void test_VirtualProtect(void)
2862 static const struct test_data
2864 DWORD prot_set
, prot_get
;
2867 { 0, 0 }, /* 0x00 */
2868 { PAGE_NOACCESS
, PAGE_NOACCESS
}, /* 0x01 */
2869 { PAGE_READONLY
, PAGE_READONLY
}, /* 0x02 */
2870 { PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x03 */
2871 { PAGE_READWRITE
, PAGE_READWRITE
}, /* 0x04 */
2872 { PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x05 */
2873 { PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x06 */
2874 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x07 */
2875 { PAGE_WRITECOPY
, 0 }, /* 0x08 */
2876 { PAGE_WRITECOPY
| PAGE_NOACCESS
, 0 }, /* 0x09 */
2877 { PAGE_WRITECOPY
| PAGE_READONLY
, 0 }, /* 0x0a */
2878 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, 0 }, /* 0x0b */
2879 { PAGE_WRITECOPY
| PAGE_READWRITE
, 0 }, /* 0x0c */
2880 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x0d */
2881 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x0e */
2882 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x0f */
2884 { PAGE_EXECUTE
, PAGE_EXECUTE
}, /* 0x10 */
2885 { PAGE_EXECUTE_READ
, PAGE_EXECUTE_READ
}, /* 0x20 */
2886 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x30 */
2887 { PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
2888 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0x50 */
2889 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0x60 */
2890 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x70 */
2891 { PAGE_EXECUTE_WRITECOPY
, 0 }, /* 0x80 */
2892 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, 0 }, /* 0x90 */
2893 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, 0 }, /* 0xa0 */
2894 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0xb0 */
2895 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, 0 }, /* 0xc0 */
2896 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0xd0 */
2897 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0xe0 */
2898 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 } /* 0xf0 */
2901 DWORD ret
, old_prot
, rw_prot
, exec_prot
, i
, j
;
2902 MEMORY_BASIC_INFORMATION info
;
2909 trace("system page size %#x\n", si
.dwPageSize
);
2911 SetLastError(0xdeadbeef);
2912 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_RESERVE
| MEM_COMMIT
, PAGE_NOACCESS
);
2913 ok(base
!= NULL
, "VirtualAlloc failed %d\n", GetLastError());
2915 SetLastError(0xdeadbeef);
2916 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_READONLY
, NULL
);
2917 ok(!ret
, "VirtualProtect should fail\n");
2918 ok(GetLastError() == ERROR_NOACCESS
, "expected ERROR_NOACCESS, got %d\n", GetLastError());
2919 old_prot
= 0xdeadbeef;
2920 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2921 ok(ret
, "VirtualProtect failed %d\n", GetLastError());
2922 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2925 size
= si
.dwPageSize
;
2926 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_READONLY
, NULL
);
2927 ok(status
== STATUS_ACCESS_VIOLATION
, "NtProtectVirtualMemory should fail, got %08x\n", status
);
2929 size
= si
.dwPageSize
;
2930 old_prot
= 0xdeadbeef;
2931 status
= pNtProtectVirtualMemory(GetCurrentProcess(), &addr
, &size
, PAGE_NOACCESS
, &old_prot
);
2932 ok(status
== STATUS_SUCCESS
, "NtProtectVirtualMemory should succeed, got %08x\n", status
);
2933 ok(old_prot
== PAGE_NOACCESS
, "got %#x != expected PAGE_NOACCESS\n", old_prot
);
2935 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
2937 SetLastError(0xdeadbeef);
2938 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2939 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2940 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2941 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2942 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
2943 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2944 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2945 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2946 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2948 old_prot
= 0xdeadbeef;
2949 SetLastError(0xdeadbeef);
2950 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot_set
, &old_prot
);
2953 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2954 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
2956 SetLastError(0xdeadbeef);
2957 ret
= VirtualQuery(base
, &info
, sizeof(info
));
2958 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
2959 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
2960 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
2961 ok(info
.Protect
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_get
);
2962 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
2963 ok(info
.AllocationProtect
== PAGE_NOACCESS
, "%d: %#x != PAGE_NOACCESS\n", i
, info
.AllocationProtect
);
2964 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2965 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
2969 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
2970 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
2973 old_prot
= 0xdeadbeef;
2974 SetLastError(0xdeadbeef);
2975 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2976 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
2978 ok(old_prot
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_get
);
2980 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
2985 for (i
= 0; i
<= 4; i
++)
2989 for (j
= 0; j
<= 4; j
++)
2991 DWORD prot
= exec_prot
| rw_prot
;
2993 SetLastError(0xdeadbeef);
2994 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, prot
);
2995 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
2997 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
2998 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3002 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
3004 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", prot
);
3005 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3009 ok(ptr
!= NULL
, "VirtualAlloc(%02x) error %d\n", prot
, GetLastError());
3010 ok(ptr
== base
, "expected %p, got %p\n", base
, ptr
);
3014 SetLastError(0xdeadbeef);
3015 ret
= VirtualProtect(base
, si
.dwPageSize
, prot
, &old_prot
);
3016 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
3018 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
3019 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3023 if (prot
& (PAGE_WRITECOPY
| PAGE_EXECUTE_WRITECOPY
))
3025 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
3026 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3029 ok(ret
, "VirtualProtect(%02x) error %d\n", prot
, GetLastError());
3035 exec_prot
= 1 << (i
+ 4);
3038 VirtualFree(base
, 0, MEM_RELEASE
);
3041 static BOOL
is_mem_writable(DWORD prot
)
3043 switch (prot
& 0xff)
3045 case PAGE_READWRITE
:
3046 case PAGE_WRITECOPY
:
3047 case PAGE_EXECUTE_READWRITE
:
3048 case PAGE_EXECUTE_WRITECOPY
:
3056 static void test_VirtualAlloc_protection(void)
3058 static const struct test_data
3064 { 0, FALSE
}, /* 0x00 */
3065 { PAGE_NOACCESS
, TRUE
}, /* 0x01 */
3066 { PAGE_READONLY
, TRUE
}, /* 0x02 */
3067 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x03 */
3068 { PAGE_READWRITE
, TRUE
}, /* 0x04 */
3069 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x05 */
3070 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x06 */
3071 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x07 */
3072 { PAGE_WRITECOPY
, FALSE
}, /* 0x08 */
3073 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
}, /* 0x09 */
3074 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
}, /* 0x0a */
3075 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
}, /* 0x0b */
3076 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
}, /* 0x0c */
3077 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
}, /* 0x0d */
3078 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
}, /* 0x0e */
3079 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
}, /* 0x0f */
3081 { PAGE_EXECUTE
, TRUE
}, /* 0x10 */
3082 { PAGE_EXECUTE_READ
, TRUE
}, /* 0x20 */
3083 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x30 */
3084 { PAGE_EXECUTE_READWRITE
, TRUE
}, /* 0x40 */
3085 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0x50 */
3086 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0x60 */
3087 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0x70 */
3088 { PAGE_EXECUTE_WRITECOPY
, FALSE
}, /* 0x80 */
3089 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
}, /* 0x90 */
3090 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xa0 */
3091 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
}, /* 0xb0 */
3092 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
}, /* 0xc0 */
3093 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
}, /* 0xd0 */
3094 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
}, /* 0xe0 */
3095 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
} /* 0xf0 */
3099 MEMORY_BASIC_INFORMATION info
;
3103 trace("system page size %#x\n", si
.dwPageSize
);
3105 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3107 SetLastError(0xdeadbeef);
3108 base
= VirtualAlloc(0, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3112 ok(base
!= NULL
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3114 SetLastError(0xdeadbeef);
3115 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3116 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3117 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3118 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3119 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3120 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3121 ok(info
.AllocationProtect
== td
[i
].prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, td
[i
].prot
);
3122 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3123 ok(info
.Type
== MEM_PRIVATE
, "%d: %#x != MEM_PRIVATE\n", i
, info
.Type
);
3125 if (is_mem_writable(info
.Protect
))
3129 SetLastError(0xdeadbeef);
3130 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3131 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3132 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3135 SetLastError(0xdeadbeef);
3136 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3137 ok(ptr
== base
, "%d: VirtualAlloc failed %d\n", i
, GetLastError());
3139 VirtualFree(base
, 0, MEM_RELEASE
);
3143 ok(!base
, "%d: VirtualAlloc should fail\n", i
);
3144 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3149 static void test_CreateFileMapping_protection(void)
3151 static const struct test_data
3155 DWORD prot_after_write
;
3158 { 0, FALSE
, 0 }, /* 0x00 */
3159 { PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x01 */
3160 { PAGE_READONLY
, TRUE
, PAGE_READONLY
}, /* 0x02 */
3161 { PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x03 */
3162 { PAGE_READWRITE
, TRUE
, PAGE_READWRITE
}, /* 0x04 */
3163 { PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x05 */
3164 { PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x06 */
3165 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x07 */
3166 { PAGE_WRITECOPY
, TRUE
, PAGE_READWRITE
}, /* 0x08 */
3167 { PAGE_WRITECOPY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x09 */
3168 { PAGE_WRITECOPY
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0a */
3169 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0b */
3170 { PAGE_WRITECOPY
| PAGE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0x0c */
3171 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0d */
3172 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, FALSE
, PAGE_NOACCESS
}, /* 0x0e */
3173 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, FALSE
, PAGE_NOACCESS
}, /* 0x0f */
3175 { PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE
}, /* 0x10 */
3176 { PAGE_EXECUTE_READ
, TRUE
, PAGE_EXECUTE_READ
}, /* 0x20 */
3177 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_EXECUTE_READ
}, /* 0x30 */
3178 { PAGE_EXECUTE_READWRITE
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x40 */
3179 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x50 */
3180 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0x60 */
3181 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x70 */
3182 { PAGE_EXECUTE_WRITECOPY
, TRUE
, PAGE_EXECUTE_READWRITE
}, /* 0x80 */
3183 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0x90 */
3184 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xa0 */
3185 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xb0 */
3186 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, FALSE
, PAGE_NOACCESS
}, /* 0xc0 */
3187 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
}, /* 0xd0 */
3188 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, FALSE
, PAGE_NOACCESS
}, /* 0xe0 */
3189 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, FALSE
, PAGE_NOACCESS
} /* 0xf0 */
3192 DWORD ret
, i
, alloc_prot
, prot
, old_prot
;
3193 MEMORY_BASIC_INFORMATION info
;
3195 char temp_path
[MAX_PATH
];
3196 char file_name
[MAX_PATH
];
3198 BOOL page_exec_supported
= TRUE
;
3201 trace("system page size %#x\n", si
.dwPageSize
);
3203 GetTempPathA(MAX_PATH
, temp_path
);
3204 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3206 SetLastError(0xdeadbeef);
3207 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3208 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3209 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3210 SetEndOfFile(hfile
);
3212 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3214 SetLastError(0xdeadbeef);
3215 hmap
= CreateFileMappingW(hfile
, NULL
, td
[i
].prot
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3221 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, td
[i
].prot
, GetLastError());
3222 /* NT4 and win2k don't support EXEC on file mappings */
3223 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3225 page_exec_supported
= FALSE
;
3226 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3229 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3230 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3232 page_exec_supported
= FALSE
;
3233 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3237 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, td
[i
].prot
, GetLastError());
3239 base
= MapViewOfFile(hmap
, FILE_MAP_READ
, 0, 0, 0);
3240 ok(base
!= NULL
, "%d: MapViewOfFile failed %d\n", i
, GetLastError());
3242 SetLastError(0xdeadbeef);
3243 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3244 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3245 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3246 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3247 ok(info
.Protect
== PAGE_READONLY
, "%d: got %#x != expected PAGE_READONLY\n", i
, info
.Protect
);
3248 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3249 ok(info
.AllocationProtect
== PAGE_READONLY
, "%d: %#x != PAGE_READONLY\n", i
, info
.AllocationProtect
);
3250 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3251 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3253 if (is_mem_writable(info
.Protect
))
3257 SetLastError(0xdeadbeef);
3258 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3259 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3260 ok(info
.Protect
== td
[i
].prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot
);
3263 SetLastError(0xdeadbeef);
3264 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, td
[i
].prot
);
3265 ok(!ptr
, "%d: VirtualAlloc(%02x) should fail\n", i
, td
[i
].prot
);
3266 /* FIXME: remove once Wine is fixed */
3267 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3268 ok(GetLastError() == ERROR_ACCESS_DENIED
, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i
, GetLastError());
3270 SetLastError(0xdeadbeef);
3271 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3272 if (td
[i
].prot
== PAGE_READONLY
|| td
[i
].prot
== PAGE_WRITECOPY
)
3273 ok(ret
, "%d: VirtualProtect(%02x) error %d\n", i
, td
[i
].prot
, GetLastError());
3276 ok(!ret
, "%d: VirtualProtect(%02x) should fail\n", i
, td
[i
].prot
);
3277 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3280 UnmapViewOfFile(base
);
3285 ok(!hmap
, "%d: CreateFileMapping should fail\n", i
);
3286 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3290 if (page_exec_supported
) alloc_prot
= PAGE_EXECUTE_READWRITE
;
3291 else alloc_prot
= PAGE_READWRITE
;
3292 SetLastError(0xdeadbeef);
3293 hmap
= CreateFileMappingW(hfile
, NULL
, alloc_prot
, 0, si
.dwPageSize
, NULL
);
3294 ok(hmap
!= 0, "%d: CreateFileMapping error %d\n", i
, GetLastError());
3296 SetLastError(0xdeadbeef);
3297 base
= MapViewOfFile(hmap
, FILE_MAP_READ
| FILE_MAP_WRITE
| (page_exec_supported
? FILE_MAP_EXECUTE
: 0), 0, 0, 0);
3298 ok(base
!= NULL
, "MapViewOfFile failed %d\n", GetLastError());
3300 old_prot
= 0xdeadbeef;
3301 SetLastError(0xdeadbeef);
3302 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3303 ok(ret
, "VirtualProtect error %d\n", GetLastError());
3304 ok(old_prot
== alloc_prot
, "got %#x != expected %#x\n", old_prot
, alloc_prot
);
3306 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
3308 SetLastError(0xdeadbeef);
3309 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3310 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3311 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3312 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3313 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
3314 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3315 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3316 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3317 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3319 old_prot
= 0xdeadbeef;
3320 SetLastError(0xdeadbeef);
3321 ret
= VirtualProtect(base
, si
.dwPageSize
, td
[i
].prot
, &old_prot
);
3322 if (td
[i
].success
|| td
[i
].prot
== PAGE_NOACCESS
|| td
[i
].prot
== PAGE_EXECUTE
)
3326 /* win2k and XP don't support EXEC on file mappings */
3327 if (td
[i
].prot
== PAGE_EXECUTE
)
3329 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3332 /* NT4 and win2k don't support EXEC on file mappings */
3333 if (td
[i
].prot
== PAGE_EXECUTE_READ
|| td
[i
].prot
== PAGE_EXECUTE_READWRITE
)
3335 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i
);
3338 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3339 if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3341 ok(broken(!ret
), "%d: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3346 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3347 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
3350 /* looks strange but Windows doesn't do this for PAGE_WRITECOPY */
3351 if (prot
== PAGE_EXECUTE_WRITECOPY
) prot
= PAGE_EXECUTE_READWRITE
;
3353 SetLastError(0xdeadbeef);
3354 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3355 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3356 ok(info
.BaseAddress
== base
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, base
);
3357 ok(info
.RegionSize
== si
.dwPageSize
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, si
.dwPageSize
);
3358 /* FIXME: remove the condition below once Wine is fixed */
3359 todo_wine_if (td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3360 ok(info
.Protect
== prot
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, prot
);
3361 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
3362 ok(info
.AllocationProtect
== alloc_prot
, "%d: %#x != %#x\n", i
, info
.AllocationProtect
, alloc_prot
);
3363 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
3364 ok(info
.Type
== MEM_MAPPED
, "%d: %#x != MEM_MAPPED\n", i
, info
.Type
);
3366 if (is_mem_writable(info
.Protect
))
3370 SetLastError(0xdeadbeef);
3371 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3372 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
3373 /* FIXME: remove the condition below once Wine is fixed */
3374 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3375 ok(info
.Protect
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_after_write
);
3380 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
3381 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
3385 old_prot
= 0xdeadbeef;
3386 SetLastError(0xdeadbeef);
3387 ret
= VirtualProtect(base
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
3388 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
3389 /* FIXME: remove the condition below once Wine is fixed */
3390 todo_wine_if (td
[i
].prot
== PAGE_WRITECOPY
|| td
[i
].prot
== PAGE_EXECUTE_WRITECOPY
)
3391 ok(old_prot
== td
[i
].prot_after_write
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_after_write
);
3394 UnmapViewOfFile(base
);
3398 DeleteFileA(file_name
);
3401 #define ACCESS_READ 0x01
3402 #define ACCESS_WRITE 0x02
3403 #define ACCESS_EXECUTE 0x04
3404 #define ACCESS_WRITECOPY 0x08
3406 static DWORD
page_prot_to_access(DWORD prot
)
3410 case PAGE_READWRITE
:
3411 return ACCESS_READ
| ACCESS_WRITE
;
3414 case PAGE_EXECUTE_READ
:
3415 return ACCESS_READ
| ACCESS_EXECUTE
;
3417 case PAGE_EXECUTE_READWRITE
:
3418 return ACCESS_READ
| ACCESS_WRITE
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3420 case PAGE_EXECUTE_WRITECOPY
:
3421 return ACCESS_READ
| ACCESS_WRITECOPY
| ACCESS_EXECUTE
;
3426 case PAGE_WRITECOPY
:
3434 static BOOL
is_compatible_protection(DWORD map_prot
, DWORD view_prot
, DWORD prot
)
3436 DWORD map_access
, view_access
, prot_access
;
3438 map_access
= page_prot_to_access(map_prot
);
3439 view_access
= page_prot_to_access(view_prot
);
3440 prot_access
= page_prot_to_access(prot
);
3442 if (view_access
== prot_access
) return TRUE
;
3443 if (!view_access
) return FALSE
;
3445 if ((view_access
& prot_access
) != prot_access
) return FALSE
;
3446 if ((map_access
& prot_access
) == prot_access
) return TRUE
;
3451 static DWORD
map_prot_to_access(DWORD prot
)
3455 case PAGE_READWRITE
:
3456 case PAGE_EXECUTE_READWRITE
:
3457 return SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3459 case PAGE_WRITECOPY
:
3461 case PAGE_EXECUTE_READ
:
3462 case PAGE_EXECUTE_WRITECOPY
:
3463 return SECTION_MAP_READ
| SECTION_MAP_EXECUTE
| SECTION_MAP_EXECUTE_EXPLICIT
| SECTION_QUERY
;
3469 static BOOL
is_compatible_access(DWORD map_prot
, DWORD view_prot
)
3471 DWORD access
= map_prot_to_access(map_prot
);
3472 if (!view_prot
) view_prot
= SECTION_MAP_READ
;
3473 return (view_prot
& access
) == view_prot
;
3476 static void *map_view_of_file(HANDLE handle
, DWORD access
)
3479 LARGE_INTEGER offset
;
3485 if (!pNtMapViewOfSection
) return NULL
;
3488 offset
.u
.LowPart
= 0;
3489 offset
.u
.HighPart
= 0;
3491 exec
= access
& FILE_MAP_EXECUTE
;
3492 access
&= ~FILE_MAP_EXECUTE
;
3494 if (access
== FILE_MAP_COPY
)
3497 protect
= PAGE_EXECUTE_WRITECOPY
;
3499 protect
= PAGE_WRITECOPY
;
3501 else if (access
& FILE_MAP_WRITE
)
3504 protect
= PAGE_EXECUTE_READWRITE
;
3506 protect
= PAGE_READWRITE
;
3508 else if (access
& FILE_MAP_READ
)
3511 protect
= PAGE_EXECUTE_READ
;
3513 protect
= PAGE_READONLY
;
3515 else protect
= PAGE_NOACCESS
;
3518 status
= pNtMapViewOfSection(handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
3519 &count
, 1 /* ViewShare */, 0, protect
);
3522 /* for simplicity */
3523 SetLastError(ERROR_ACCESS_DENIED
);
3529 static void test_mapping(void)
3531 static const DWORD page_prot
[] =
3533 PAGE_NOACCESS
, PAGE_READONLY
, PAGE_READWRITE
, PAGE_WRITECOPY
,
3534 PAGE_EXECUTE_READ
, PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_WRITECOPY
3541 { 0, PAGE_NOACCESS
}, /* 0x00 */
3542 { FILE_MAP_COPY
, PAGE_WRITECOPY
}, /* 0x01 */
3543 { FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x02 */
3544 { FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x03 */
3545 { FILE_MAP_READ
, PAGE_READONLY
}, /* 0x04 */
3546 { FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x05 */
3547 { FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x06 */
3548 { FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x07 */
3549 { SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x08 */
3550 { SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x09 */
3551 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0a */
3552 { SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0b */
3553 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_READONLY
}, /* 0x0c */
3554 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_READONLY
}, /* 0x0d */
3555 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_READWRITE
}, /* 0x0e */
3556 { SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_READWRITE
}, /* 0x0f */
3557 { FILE_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x20 */
3558 { FILE_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_EXECUTE_WRITECOPY
}, /* 0x21 */
3559 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x22 */
3560 { FILE_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x23 */
3561 { FILE_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x24 */
3562 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x25 */
3563 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x26 */
3564 { FILE_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x27 */
3565 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
, PAGE_NOACCESS
}, /* 0x28 */
3566 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_COPY
, PAGE_NOACCESS
}, /* 0x29 */
3567 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2a */
3568 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
}, /* 0x2b */
3569 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
, PAGE_EXECUTE_READ
}, /* 0x2c */
3570 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_COPY
, PAGE_EXECUTE_READ
}, /* 0x2d */
3571 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
, PAGE_EXECUTE_READWRITE
}, /* 0x2e */
3572 { FILE_MAP_EXECUTE
| SECTION_MAP_EXECUTE
| FILE_MAP_READ
| FILE_MAP_WRITE
| FILE_MAP_COPY
, PAGE_EXECUTE_READWRITE
} /* 0x2f */
3574 void *base
, *nt_base
, *ptr
;
3575 DWORD i
, j
, k
, ret
, old_prot
, prev_prot
;
3577 char temp_path
[MAX_PATH
];
3578 char file_name
[MAX_PATH
];
3580 MEMORY_BASIC_INFORMATION info
, nt_info
;
3583 trace("system page size %#x\n", si
.dwPageSize
);
3585 GetTempPathA(MAX_PATH
, temp_path
);
3586 GetTempFileNameA(temp_path
, "map", 0, file_name
);
3588 SetLastError(0xdeadbeef);
3589 hfile
= CreateFileA(file_name
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3590 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile(%s) error %d\n", file_name
, GetLastError());
3591 SetFilePointer(hfile
, si
.dwPageSize
, NULL
, FILE_BEGIN
);
3592 SetEndOfFile(hfile
);
3594 for (i
= 0; i
< sizeof(page_prot
)/sizeof(page_prot
[0]); i
++)
3596 SetLastError(0xdeadbeef);
3597 hmap
= CreateFileMappingW(hfile
, NULL
, page_prot
[i
] | SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3599 if (page_prot
[i
] == PAGE_NOACCESS
)
3603 ok(!hmap
, "CreateFileMapping(PAGE_NOACCESS) should fail\n");
3604 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3606 /* A trick to create a not accessible mapping */
3607 SetLastError(0xdeadbeef);
3608 hmap
= CreateFileMappingW(hfile
, NULL
, PAGE_READWRITE
| SEC_COMMIT
, 0, si
.dwPageSize
, NULL
);
3609 ok(hmap
!= 0, "CreateFileMapping(PAGE_READWRITE) error %d\n", GetLastError());
3610 SetLastError(0xdeadbeef);
3611 ret
= DuplicateHandle(GetCurrentProcess(), hmap
, GetCurrentProcess(), &hmap2
, 0, FALSE
, 0);
3612 ok(ret
, "DuplicateHandle error %d\n", GetLastError());
3619 trace("%d: CreateFileMapping(%04x) failed: %d\n", i
, page_prot
[i
], GetLastError());
3621 /* NT4 and win2k don't support EXEC on file mappings */
3622 if (page_prot
[i
] == PAGE_EXECUTE_READ
|| page_prot
[i
] == PAGE_EXECUTE_READWRITE
)
3624 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i
);
3627 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3628 if (page_prot
[i
] == PAGE_EXECUTE_WRITECOPY
)
3630 ok(broken(!hmap
), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i
);
3635 ok(hmap
!= 0, "%d: CreateFileMapping(%04x) error %d\n", i
, page_prot
[i
], GetLastError());
3637 for (j
= 0; j
< sizeof(view
)/sizeof(view
[0]); j
++)
3639 nt_base
= map_view_of_file(hmap
, view
[j
].access
);
3642 SetLastError(0xdeadbeef);
3643 ret
= VirtualQuery(nt_base
, &nt_info
, sizeof(nt_info
));
3644 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3645 UnmapViewOfFile(nt_base
);
3648 SetLastError(0xdeadbeef);
3649 base
= MapViewOfFile(hmap
, view
[j
].access
, 0, 0, 0);
3651 /* Vista+ supports FILE_MAP_EXECUTE properly, earlier versions don't */
3652 ok(!nt_base
== !base
||
3653 broken((view
[j
].access
& FILE_MAP_EXECUTE
) && !nt_base
!= !base
),
3654 "%d: (%04x/%04x) NT %p kernel %p\n", j
, page_prot
[i
], view
[j
].access
, nt_base
, base
);
3656 if (!is_compatible_access(page_prot
[i
], view
[j
].access
))
3658 ok(!base
, "%d: MapViewOfFile(%04x/%04x) should fail\n", j
, page_prot
[i
], view
[j
].access
);
3659 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %d\n", GetLastError());
3663 /* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */
3664 if (!base
&& (view
[j
].access
& FILE_MAP_EXECUTE
))
3666 ok(broken(!base
), "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3670 ok(base
!= NULL
, "%d: MapViewOfFile(%04x/%04x) failed %d\n", j
, page_prot
[i
], view
[j
].access
, GetLastError());
3672 SetLastError(0xdeadbeef);
3673 ret
= VirtualQuery(base
, &info
, sizeof(info
));
3674 ok(ret
, "%d: VirtualQuery failed %d\n", j
, GetLastError());
3675 ok(info
.BaseAddress
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.BaseAddress
, base
);
3676 ok(info
.RegionSize
== si
.dwPageSize
, "%d: (%04x) got %#lx != expected %#x\n", j
, view
[j
].access
, info
.RegionSize
, si
.dwPageSize
);
3677 ok(info
.Protect
== view
[j
].prot
||
3678 broken(view
[j
].prot
== PAGE_EXECUTE_READ
&& info
.Protect
== PAGE_READONLY
) || /* win2k */
3679 broken(view
[j
].prot
== PAGE_EXECUTE_READWRITE
&& info
.Protect
== PAGE_READWRITE
) || /* win2k */
3680 broken(view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3681 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.Protect
, view
[j
].prot
);
3682 ok(info
.AllocationBase
== base
, "%d: (%04x) got %p, expected %p\n", j
, view
[j
].access
, info
.AllocationBase
, base
);
3683 ok(info
.AllocationProtect
== info
.Protect
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, info
.AllocationProtect
, info
.Protect
);
3684 ok(info
.State
== MEM_COMMIT
, "%d: (%04x) got %#x, expected MEM_COMMIT\n", j
, view
[j
].access
, info
.State
);
3685 ok(info
.Type
== MEM_MAPPED
, "%d: (%04x) got %#x, expected MEM_MAPPED\n", j
, view
[j
].access
, info
.Type
);
3687 if (nt_base
&& base
)
3689 ok(nt_info
.RegionSize
== info
.RegionSize
, "%d: (%04x) got %#lx != expected %#lx\n", j
, view
[j
].access
, nt_info
.RegionSize
, info
.RegionSize
);
3690 ok(nt_info
.Protect
== info
.Protect
/* Vista+ */ ||
3691 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3692 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Protect
, info
.Protect
);
3693 ok(nt_info
.AllocationProtect
== info
.AllocationProtect
/* Vista+ */ ||
3694 broken(nt_info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
&& info
.Protect
== PAGE_NOACCESS
), /* XP */
3695 "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.AllocationProtect
, info
.AllocationProtect
);
3696 ok(nt_info
.State
== info
.State
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.State
, info
.State
);
3697 ok(nt_info
.Type
== info
.Type
, "%d: (%04x) got %#x, expected %#x\n", j
, view
[j
].access
, nt_info
.Type
, info
.Type
);
3700 prev_prot
= info
.Protect
;
3702 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3704 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3705 SetLastError(0xdeadbeef);
3706 old_prot
= 0xdeadbeef;
3707 ret
= VirtualProtect(base
, si
.dwPageSize
, page_prot
[k
], &old_prot
);
3708 if (is_compatible_protection(page_prot
[i
], view
[j
].prot
, page_prot
[k
]))
3710 /* win2k and XP don't support EXEC on file mappings */
3711 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE
)
3713 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3716 /* NT4 and win2k don't support EXEC on file mappings */
3717 if (!ret
&& (page_prot
[k
] == PAGE_EXECUTE_READ
|| page_prot
[k
] == PAGE_EXECUTE_READWRITE
))
3719 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE\n");
3722 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
3723 if (!ret
&& page_prot
[k
] == PAGE_EXECUTE_WRITECOPY
)
3725 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n");
3728 /* win2k and XP don't support PAGE_EXECUTE_WRITECOPY views properly */
3729 if (!ret
&& view
[j
].prot
== PAGE_EXECUTE_WRITECOPY
)
3731 ok(broken(!ret
), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY view properly\n");
3735 ok(ret
, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3736 ok(old_prot
== prev_prot
, "got %#x, expected %#x\n", old_prot
, prev_prot
);
3737 prev_prot
= page_prot
[k
];
3741 /* NT4 doesn't fail on incompatible map and view */
3744 ok(broken(ret
), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3745 skip("Incompatible map and view are not properly handled on this platform\n");
3746 break; /* NT4 won't pass remaining tests */
3749 ok(!ret
, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot
[i
], view
[j
].prot
, page_prot
[k
]);
3750 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3754 for (k
= 0; k
< sizeof(page_prot
)/sizeof(page_prot
[0]); k
++)
3756 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
3757 SetLastError(0xdeadbeef);
3758 ptr
= VirtualAlloc(base
, si
.dwPageSize
, MEM_COMMIT
, page_prot
[k
]);
3759 ok(!ptr
, "VirtualAlloc(%02x) should fail\n", page_prot
[k
]);
3760 /* FIXME: remove once Wine is fixed */
3761 todo_wine_if (page_prot
[k
] == PAGE_WRITECOPY
|| page_prot
[k
] == PAGE_EXECUTE_WRITECOPY
)
3762 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3765 UnmapViewOfFile(base
);
3772 DeleteFileA(file_name
);
3775 static void test_shared_memory(BOOL is_child
)
3780 SetLastError(0xdeadbef);
3781 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c");
3782 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3784 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3786 SetLastError(0xdeadbef);
3787 p
= MapViewOfFile(mapping
, FILE_MAP_READ
|FILE_MAP_WRITE
, 0, 0, 4096);
3788 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3792 ok(*p
== 0x1a2b3c4d, "expected 0x1a2b3c4d in child, got %#x\n", *p
);
3797 char cmdline
[MAX_PATH
];
3798 PROCESS_INFORMATION pi
;
3799 STARTUPINFOA si
= { sizeof(si
) };
3804 winetest_get_mainargs(&argv
);
3805 sprintf(cmdline
, "\"%s\" virtual sharedmem", argv
[0]);
3806 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3807 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3808 winetest_wait_child_process(pi
.hProcess
);
3809 CloseHandle(pi
.hThread
);
3810 CloseHandle(pi
.hProcess
);
3814 CloseHandle(mapping
);
3817 static void test_shared_memory_ro(BOOL is_child
, DWORD child_access
)
3822 SetLastError(0xdeadbef);
3823 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_virtual.c_ro");
3824 ok(mapping
!= 0, "CreateFileMapping error %d\n", GetLastError());
3826 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
3828 SetLastError(0xdeadbef);
3829 p
= MapViewOfFile(mapping
, is_child
? child_access
: FILE_MAP_READ
, 0, 0, 4096);
3830 ok(p
!= NULL
, "MapViewOfFile error %d\n", GetLastError());
3839 char cmdline
[MAX_PATH
];
3840 PROCESS_INFORMATION pi
;
3841 STARTUPINFOA si
= { sizeof(si
) };
3844 winetest_get_mainargs(&argv
);
3845 sprintf(cmdline
, "\"%s\" virtual sharedmemro %x", argv
[0], child_access
);
3846 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3847 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3848 winetest_wait_child_process(pi
.hProcess
);
3849 CloseHandle(pi
.hThread
);
3850 CloseHandle(pi
.hProcess
);
3852 if(child_access
& FILE_MAP_WRITE
)
3853 ok(*p
== 0xdeadbeef, "*p = %x, expected 0xdeadbeef\n", *p
);
3855 ok(!*p
, "*p = %x, expected 0\n", *p
);
3859 CloseHandle(mapping
);
3862 static void test_NtQuerySection(void)
3864 char path
[MAX_PATH
];
3865 HANDLE file
, mapping
;
3870 SECTION_BASIC_INFORMATION basic
;
3871 SECTION_IMAGE_INFORMATION image
;
3874 IMAGE_NT_HEADERS
*nt
;
3876 SIZE_T fsize
, image_size
;
3879 if (!pNtQuerySection
)
3881 win_skip("NtQuerySection is not available\n");
3886 page_mask
= si
.dwPageSize
- 1;
3888 GetSystemDirectoryA(path
, sizeof(path
));
3889 strcat(path
, "\\kernel32.dll");
3891 SetLastError(0xdeadbef);
3892 file
= CreateFileA(path
, GENERIC_READ
|GENERIC_EXECUTE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
3893 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile error %u\n", GetLastError());
3895 fsize
= GetFileSize(file
, NULL
);
3897 SetLastError(0xdeadbef);
3898 mapping
= CreateFileMappingA(file
, NULL
, PAGE_EXECUTE_READ
, 0, 0, NULL
);
3899 /* NT4 and win2k don't support EXEC on file mappings */
3901 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
3902 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
3904 status
= pNtQuerySection(mapping
, SectionBasicInformation
, NULL
, sizeof(info
), &ret
);
3905 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status
);
3907 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, 0, NULL
);
3908 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3910 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, 0, &ret
);
3911 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3913 memset(&info
, 0x55, sizeof(info
));
3915 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3916 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3917 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3918 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3919 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
3920 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3922 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
.basic
), &ret
);
3923 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3925 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
), &ret
);
3926 ok(status
== STATUS_SECTION_NOT_IMAGE
, "expected STATUS_SECTION_NOT_IMAGE, got %#x\n", status
);
3928 SetLastError(0xdeadbef);
3929 p
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
3930 ok(p
!= NULL
, "MapViewOfFile error %u\n", GetLastError());
3932 nt
= image_nt_header(p
);
3933 image_size
= ROUND_SIZE(p
, nt
->OptionalHeader
.SizeOfImage
);
3935 memset(&info
, 0x55, sizeof(info
));
3937 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3938 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3939 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3940 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3941 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
3942 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3945 CloseHandle(mapping
);
3947 SetLastError(0xdeadbef);
3948 mapping
= CreateFileMappingA(file
, NULL
, PAGE_EXECUTE_READ
|SEC_IMAGE
, 0, 0, NULL
);
3949 /* NT4 and win2k don't support EXEC on file mappings */
3951 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
|SEC_IMAGE
, 0, 0, NULL
);
3952 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
3954 memset(&info
, 0x55, sizeof(info
));
3956 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
3957 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3958 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
3959 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
3960 ok(info
.basic
.Attributes
== (SEC_FILE
|SEC_IMAGE
), "expected SEC_FILE|SEC_IMAGE, got %#x\n", info
.basic
.Attributes
);
3961 ok(info
.basic
.Size
.QuadPart
== image_size
, "expected %#lx, got %#x/%08x\n", image_size
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
3963 status
= pNtQuerySection(mapping
, SectionImageInformation
, NULL
, sizeof(info
), &ret
);
3964 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status
);
3966 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, 0, NULL
);
3967 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3969 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, 0, &ret
);
3970 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3972 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
.basic
), &ret
);
3973 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %#x\n", status
);
3975 SetLastError(0xdeadbef);
3976 p
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
3977 ok(p
!= NULL
, "MapViewOfFile error %u\n", GetLastError());
3979 nt
= image_nt_header(p
);
3981 memset(&info
, 0x55, sizeof(info
));
3983 status
= pNtQuerySection(mapping
, SectionImageInformation
, &info
, sizeof(info
), &ret
);
3984 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
3985 ok(ret
== sizeof(info
.image
), "wrong returned size %u\n", ret
);
3986 ok((ULONG_PTR
)info
.image
.TransferAddress
== nt
->OptionalHeader
.ImageBase
+ nt
->OptionalHeader
.AddressOfEntryPoint
,
3987 "expected %#lx, got %p\n", (SIZE_T
)(nt
->OptionalHeader
.ImageBase
+ nt
->OptionalHeader
.AddressOfEntryPoint
), info
.image
.TransferAddress
);
3988 ok(info
.image
.ZeroBits
== 0, "expected 0, got %#x\n", info
.image
.ZeroBits
);
3989 ok(info
.image
.MaximumStackSize
== nt
->OptionalHeader
.SizeOfStackReserve
, "expected %#lx, got %#lx\n", (SIZE_T
)nt
->OptionalHeader
.SizeOfStackReserve
, info
.image
.MaximumStackSize
);
3990 ok(info
.image
.CommittedStackSize
== nt
->OptionalHeader
.SizeOfStackCommit
, "expected %#lx, got %#lx\n", (SIZE_T
)nt
->OptionalHeader
.SizeOfStackCommit
, info
.image
.CommittedStackSize
);
3991 ok(info
.image
.SubSystemType
== nt
->OptionalHeader
.Subsystem
, "expected %#x, got %#x\n", nt
->OptionalHeader
.Subsystem
, info
.image
.SubSystemType
);
3992 ok(info
.image
.SubsystemVersionLow
== nt
->OptionalHeader
.MinorSubsystemVersion
, "expected %#x, got %#x\n", nt
->OptionalHeader
.MinorSubsystemVersion
, info
.image
.SubsystemVersionLow
);
3993 ok(info
.image
.SubsystemVersionHigh
== nt
->OptionalHeader
.MajorSubsystemVersion
, "expected %#x, got %#x\n", nt
->OptionalHeader
.MajorSubsystemVersion
, info
.image
.SubsystemVersionHigh
);
3994 ok(info
.image
.ImageCharacteristics
== nt
->FileHeader
.Characteristics
, "expected %#x, got %#x\n", nt
->FileHeader
.Characteristics
, info
.image
.ImageCharacteristics
);
3995 ok(info
.image
.DllCharacteristics
== nt
->OptionalHeader
.DllCharacteristics
, "expected %#x, got %#x\n", nt
->OptionalHeader
.DllCharacteristics
, info
.image
.DllCharacteristics
);
3996 ok(info
.image
.Machine
== nt
->FileHeader
.Machine
, "expected %#x, got %#x\n", nt
->FileHeader
.Machine
, info
.image
.Machine
);
3998 ok(info
.image
.ImageContainsCode
== TRUE
, "expected 1, got %#x\n", info
.image
.ImageContainsCode
);
4000 memset(&info
, 0x55, sizeof(info
));
4002 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4003 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4004 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4005 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4006 ok(info
.basic
.Attributes
== (SEC_FILE
|SEC_IMAGE
), "expected SEC_FILE|SEC_IMAGE, got %#x\n", info
.basic
.Attributes
);
4007 ok(info
.basic
.Size
.QuadPart
== image_size
, "expected %#lx, got %#x/%08x\n", image_size
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4010 CloseHandle(mapping
);
4012 SetLastError(0xdeadbef);
4013 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
|SEC_COMMIT
|SEC_NOCACHE
, 0, 0, NULL
);
4014 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
4016 memset(&info
, 0x55, sizeof(info
));
4018 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4019 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4020 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4021 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4023 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
4024 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4026 CloseHandle(mapping
);
4028 SetLastError(0xdeadbef);
4029 mapping
= CreateFileMappingA(file
, NULL
, PAGE_READONLY
|SEC_RESERVE
, 0, 0, NULL
);
4030 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
4032 memset(&info
, 0x55, sizeof(info
));
4034 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4035 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4036 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4037 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4038 ok(info
.basic
.Attributes
== SEC_FILE
, "expected SEC_FILE, got %#x\n", info
.basic
.Attributes
);
4039 ok(info
.basic
.Size
.QuadPart
== fsize
, "expected %#lx, got %#x/%08x\n", fsize
, info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4041 CloseHandle(mapping
);
4044 SetLastError(0xdeadbef);
4045 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
|SEC_COMMIT
, 0, 4096, NULL
);
4046 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
4048 memset(&info
, 0x55, sizeof(info
));
4050 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4051 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4052 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4053 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4054 ok(info
.basic
.Attributes
== SEC_COMMIT
, "expected SEC_COMMIT, got %#x\n", info
.basic
.Attributes
);
4055 ok(info
.basic
.Size
.QuadPart
== 4096, "expected 4096, got %#x/%08x\n", info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4057 SetLastError(0xdeadbef);
4058 p
= MapViewOfFile(mapping
, FILE_MAP_READ
|FILE_MAP_WRITE
, 0, 0, 0);
4059 ok(p
!= NULL
, "MapViewOfFile error %u\n", GetLastError());
4061 memset(&info
, 0x55, sizeof(info
));
4063 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4064 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4065 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4066 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4067 ok(info
.basic
.Attributes
== SEC_COMMIT
, "expected SEC_COMMIT, got %#x\n", info
.basic
.Attributes
);
4068 ok(info
.basic
.Size
.QuadPart
== 4096, "expected 4096, got %#x/%08x\n", info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4071 CloseHandle(mapping
);
4073 SetLastError(0xdeadbef);
4074 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READONLY
|SEC_RESERVE
, 0, 4096, NULL
);
4075 ok(mapping
!= 0, "CreateFileMapping error %u\n", GetLastError());
4077 memset(&info
, 0x55, sizeof(info
));
4079 status
= pNtQuerySection(mapping
, SectionBasicInformation
, &info
, sizeof(info
), &ret
);
4080 ok(status
== STATUS_SUCCESS
, "NtQuerySection error %#x\n", status
);
4081 ok(ret
== sizeof(info
.basic
), "wrong returned size %u\n", ret
);
4082 ok(info
.basic
.BaseAddress
== NULL
, "expected NULL, got %p\n", info
.basic
.BaseAddress
);
4083 ok(info
.basic
.Attributes
== SEC_RESERVE
, "expected SEC_RESERVE, got %#x\n", info
.basic
.Attributes
);
4084 ok(info
.basic
.Size
.QuadPart
== 4096, "expected 4096, got %#x/%08x\n", info
.basic
.Size
.HighPart
, info
.basic
.Size
.LowPart
);
4086 CloseHandle(mapping
);
4093 argc
= winetest_get_mainargs( &argv
);
4097 if (!strcmp(argv
[2], "sleep"))
4099 Sleep(5000); /* spawned process runs for at most 5 seconds */
4102 if (!strcmp(argv
[2], "sharedmem"))
4104 test_shared_memory(TRUE
);
4107 if (!strcmp(argv
[2], "sharedmemro"))
4109 test_shared_memory_ro(TRUE
, strtol(argv
[3], NULL
, 16));
4116 mem
= VirtualAlloc(NULL
, 1<<20, MEM_COMMIT
|MEM_RESERVE
,
4117 PAGE_EXECUTE_READWRITE
);
4118 ok(mem
!= NULL
, "VirtualAlloc failed %u\n", GetLastError());
4119 if (mem
== NULL
) break;
4120 ret
= VirtualFree(mem
, 0, MEM_RELEASE
);
4121 ok(ret
, "VirtualFree failed %u\n", GetLastError());
4127 hkernel32
= GetModuleHandleA("kernel32.dll");
4128 hntdll
= GetModuleHandleA("ntdll.dll");
4130 pVirtualAllocEx
= (void *) GetProcAddress(hkernel32
, "VirtualAllocEx");
4131 pVirtualFreeEx
= (void *) GetProcAddress(hkernel32
, "VirtualFreeEx");
4132 pGetWriteWatch
= (void *) GetProcAddress(hkernel32
, "GetWriteWatch");
4133 pResetWriteWatch
= (void *) GetProcAddress(hkernel32
, "ResetWriteWatch");
4134 pGetProcessDEPPolicy
= (void *)GetProcAddress( hkernel32
, "GetProcessDEPPolicy" );
4135 pIsWow64Process
= (void *)GetProcAddress( hkernel32
, "IsWow64Process" );
4136 pNtAreMappedFilesTheSame
= (void *)GetProcAddress( hntdll
, "NtAreMappedFilesTheSame" );
4137 pNtCreateSection
= (void *)GetProcAddress( hntdll
, "NtCreateSection" );
4138 pNtMapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtMapViewOfSection" );
4139 pNtUnmapViewOfSection
= (void *)GetProcAddress( hntdll
, "NtUnmapViewOfSection" );
4140 pNtQuerySection
= (void *)GetProcAddress( hntdll
, "NtQuerySection" );
4141 pRtlAddVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlAddVectoredExceptionHandler" );
4142 pRtlRemoveVectoredExceptionHandler
= (void *)GetProcAddress( hntdll
, "RtlRemoveVectoredExceptionHandler" );
4143 pNtProtectVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtProtectVirtualMemory" );
4144 pNtAllocateVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtAllocateVirtualMemory" );
4145 pNtFreeVirtualMemory
= (void *)GetProcAddress( hntdll
, "NtFreeVirtualMemory" );
4147 test_shared_memory(FALSE
);
4148 test_shared_memory_ro(FALSE
, FILE_MAP_READ
|FILE_MAP_WRITE
);
4149 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
);
4150 test_shared_memory_ro(FALSE
, FILE_MAP_COPY
|FILE_MAP_WRITE
);
4152 test_NtQuerySection();
4153 test_CreateFileMapping_protection();
4154 test_VirtualAlloc_protection();
4155 test_VirtualProtect();
4156 test_VirtualAllocEx();
4157 test_VirtualAlloc();
4158 test_MapViewOfFile();
4159 test_NtMapViewOfSection();
4160 test_NtAreMappedFilesTheSame();
4161 test_CreateFileMapping();
4162 test_IsBadReadPtr();
4163 test_IsBadWritePtr();
4164 test_IsBadCodePtr();
4166 #if defined(__i386__) || defined(__x86_64__)
4167 test_stack_commit();
4171 /* The following tests should be executed as a last step, and in exactly this
4172 * order, since ATL thunk emulation cannot be enabled anymore on Windows. */
4173 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE
);
4174 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
);
4175 test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE
| MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
);