usp10/tests: A spelling fix in an ok() message.
[wine.git] / dlls / ntdll / tests / virtual.c
blobbb110f15681025a3e44f9a268e67749895bb64ec
1 /*
2 * Unit test suite for the virtual memory APIs.
4 * Copyright 2019 Remi Bernon for CodeWeavers
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
21 #include <stdio.h>
23 #include "ntstatus.h"
24 #define WIN32_NO_STATUS
25 #include "windef.h"
26 #include "winternl.h"
27 #include "wine/test.h"
29 static unsigned int page_size;
31 static NTSTATUS (WINAPI *pRtlCreateUserStack)(SIZE_T, SIZE_T, ULONG, SIZE_T, SIZE_T, INITIAL_TEB *);
32 static NTSTATUS (WINAPI *pRtlFreeUserStack)(void *);
33 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
35 static HANDLE create_target_process(const char *arg)
37 char **argv;
38 char cmdline[MAX_PATH];
39 PROCESS_INFORMATION pi;
40 BOOL ret;
41 STARTUPINFOA si = { 0 };
42 si.cb = sizeof(si);
44 winetest_get_mainargs(&argv);
45 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
46 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
47 ok(ret, "error: %u\n", GetLastError());
48 ret = CloseHandle(pi.hThread);
49 ok(ret, "error %u\n", GetLastError());
50 return pi.hProcess;
53 static UINT_PTR get_zero_bits(UINT_PTR p)
55 UINT_PTR z = 0;
57 #ifdef _WIN64
58 if (p >= 0xffffffff)
59 return (~(UINT_PTR)0) >> get_zero_bits(p >> 32);
60 #endif
62 if (p == 0) return 32;
63 while ((p >> (31 - z)) != 1) z++;
64 return z;
67 static void test_NtAllocateVirtualMemory(void)
69 void *addr1, *addr2;
70 NTSTATUS status;
71 SIZE_T size;
72 ULONG zero_bits;
73 BOOL is_wow64;
75 /* simple allocation should success */
76 size = 0x1000;
77 addr1 = NULL;
78 status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr1, 0, &size,
79 MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
80 ok(status == STATUS_SUCCESS, "NtAllocateVirtualMemory returned %08x\n", status);
82 /* allocation conflicts because of 64k align */
83 size = 0x1000;
84 addr2 = (char *)addr1 + 0x1000;
85 status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, 0, &size,
86 MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
87 ok(status == STATUS_CONFLICTING_ADDRESSES, "NtAllocateVirtualMemory returned %08x\n", status);
89 /* it should conflict, even when zero_bits is explicitly set */
90 size = 0x1000;
91 addr2 = (char *)addr1 + 0x1000;
92 status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, 12, &size,
93 MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
94 ok(status == STATUS_CONFLICTING_ADDRESSES, "NtAllocateVirtualMemory returned %08x\n", status);
96 /* 1 zero bits should zero 63-31 upper bits */
97 size = 0x1000;
98 addr2 = NULL;
99 zero_bits = 1;
100 status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, zero_bits, &size,
101 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
102 ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY ||
103 broken(status == STATUS_INVALID_PARAMETER_3) /* winxp */,
104 "NtAllocateVirtualMemory returned %08x\n", status);
105 if (status == STATUS_SUCCESS)
107 ok(((UINT_PTR)addr2 >> (32 - zero_bits)) == 0,
108 "NtAllocateVirtualMemory returned address: %p\n", addr2);
110 size = 0;
111 status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_RELEASE);
112 ok(status == STATUS_SUCCESS, "NtFreeVirtualMemory return %08x, addr2: %p\n", status, addr2);
115 for (zero_bits = 2; zero_bits <= 20; zero_bits++)
117 size = 0x1000;
118 addr2 = NULL;
119 status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, zero_bits, &size,
120 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
121 ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY ||
122 broken(zero_bits == 20 && status == STATUS_CONFLICTING_ADDRESSES) /* w1064v1809 */,
123 "NtAllocateVirtualMemory with %d zero_bits returned %08x\n", zero_bits, status);
124 if (status == STATUS_SUCCESS)
126 todo_wine_if((UINT_PTR)addr2 >> (32 - zero_bits))
127 ok(((UINT_PTR)addr2 >> (32 - zero_bits)) == 0,
128 "NtAllocateVirtualMemory with %d zero_bits returned address %p\n", zero_bits, addr2);
130 size = 0;
131 status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_RELEASE);
132 ok(status == STATUS_SUCCESS, "NtFreeVirtualMemory return %08x, addr2: %p\n", status, addr2);
136 /* 21 zero bits never succeeds */
137 size = 0x1000;
138 addr2 = NULL;
139 status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, 21, &size,
140 MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
141 todo_wine
142 ok(status == STATUS_NO_MEMORY || status == STATUS_INVALID_PARAMETER,
143 "NtAllocateVirtualMemory returned %08x\n", status);
144 if (status == STATUS_SUCCESS)
146 size = 0;
147 status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_RELEASE);
148 ok(status == STATUS_SUCCESS, "NtFreeVirtualMemory return %08x, addr2: %p\n", status, addr2);
151 /* 22 zero bits is invalid */
152 size = 0x1000;
153 addr2 = NULL;
154 status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, 22, &size,
155 MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
156 ok(status == STATUS_INVALID_PARAMETER_3 || status == STATUS_INVALID_PARAMETER,
157 "NtAllocateVirtualMemory returned %08x\n", status);
159 /* zero bits > 31 should be considered as bitmask on 64bit and WoW64 */
160 size = 0x1000;
161 addr2 = NULL;
162 zero_bits = 0x1fffffff;
163 status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, zero_bits, &size,
164 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
166 if (sizeof(void *) == sizeof(int) && (!pIsWow64Process ||
167 !pIsWow64Process(NtCurrentProcess(), &is_wow64) || !is_wow64))
169 ok(status == STATUS_INVALID_PARAMETER_3, "NtAllocateVirtualMemory returned %08x\n", status);
171 else
173 ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY,
174 "NtAllocateVirtualMemory returned %08x\n", status);
175 if (status == STATUS_SUCCESS)
177 todo_wine_if((UINT_PTR)addr2 & ~zero_bits)
178 ok(((UINT_PTR)addr2 & ~zero_bits) == 0,
179 "NtAllocateVirtualMemory returned address %p\n", addr2);
181 size = 0;
182 status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_RELEASE);
183 ok(status == STATUS_SUCCESS, "NtFreeVirtualMemory return %08x, addr2: %p\n", status, addr2);
187 /* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
188 size = 0x1000;
189 addr2 = (char *)addr1 + 0x1000;
190 status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, 0, &size,
191 MEM_RESERVE | MEM_COMMIT | AT_ROUND_TO_PAGE, PAGE_EXECUTE_READWRITE);
192 ok(status == STATUS_INVALID_PARAMETER_5 || status == STATUS_INVALID_PARAMETER,
193 "NtAllocateVirtualMemory returned %08x\n", status);
195 size = 0;
196 status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE);
197 ok(status == STATUS_SUCCESS, "NtFreeVirtualMemory failed\n");
200 static void test_RtlCreateUserStack(void)
202 IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress );
203 SIZE_T default_commit = nt->OptionalHeader.SizeOfStackCommit;
204 SIZE_T default_reserve = nt->OptionalHeader.SizeOfStackReserve;
205 INITIAL_TEB stack = {0};
206 unsigned int i;
207 NTSTATUS ret;
209 struct
211 SIZE_T commit, reserve, commit_align, reserve_align, expect_commit, expect_reserve;
213 tests[] =
215 { 0, 0, 1, 1, default_commit, default_reserve},
216 { 0x2000, 0, 1, 1, 0x2000, default_reserve},
217 { 0x4000, 0, 1, 1, 0x4000, default_reserve},
218 { 0, 0x200000, 1, 1, default_commit, 0x200000},
219 { 0x4000, 0x200000, 1, 1, 0x4000, 0x200000},
220 {0x100000, 0x100000, 1, 1, 0x100000, 0x100000},
221 { 0x20000, 0x20000, 1, 1, 0x20000, 0x100000},
223 { 0, 0x110000, 1, 1, default_commit, 0x110000},
224 { 0, 0x110000, 1, 0x40000, default_commit, 0x140000},
225 { 0, 0x140000, 1, 0x40000, default_commit, 0x140000},
226 { 0x11000, 0x140000, 1, 0x40000, 0x11000, 0x140000},
227 { 0x11000, 0x140000, 0x4000, 0x40000, 0x14000, 0x140000},
228 { 0, 0, 0x4000, 0x400000,
229 (default_commit + 0x3fff) & ~0x3fff,
230 (default_reserve + 0x3fffff) & ~0x3fffff},
233 if (!pRtlCreateUserStack)
235 win_skip("RtlCreateUserStack() is missing\n");
236 return;
239 for (i = 0; i < ARRAY_SIZE(tests); ++i)
241 memset(&stack, 0xcc, sizeof(stack));
242 ret = pRtlCreateUserStack(tests[i].commit, tests[i].reserve, 0,
243 tests[i].commit_align, tests[i].reserve_align, &stack);
244 ok(!ret, "%u: got status %#x\n", i, ret);
245 ok(!stack.OldStackBase, "%u: got OldStackBase %p\n", i, stack.OldStackBase);
246 ok(!stack.OldStackLimit, "%u: got OldStackLimit %p\n", i, stack.OldStackLimit);
247 ok(!((ULONG_PTR)stack.DeallocationStack & (page_size - 1)),
248 "%u: got unaligned memory %p\n", i, stack.DeallocationStack);
249 ok((ULONG_PTR)stack.StackBase - (ULONG_PTR)stack.DeallocationStack == tests[i].expect_reserve,
250 "%u: got reserve %#lx\n", i, (ULONG_PTR)stack.StackBase - (ULONG_PTR)stack.DeallocationStack);
251 todo_wine ok((ULONG_PTR)stack.StackBase - (ULONG_PTR)stack.StackLimit == tests[i].expect_commit,
252 "%u: got commit %#lx\n", i, (ULONG_PTR)stack.StackBase - (ULONG_PTR)stack.StackLimit);
253 pRtlFreeUserStack(stack.DeallocationStack);
256 ret = pRtlCreateUserStack(0x11000, 0x110000, 0, 1, 0, &stack);
257 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
259 ret = pRtlCreateUserStack(0x11000, 0x110000, 0, 0, 1, &stack);
260 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
263 static void test_NtMapViewOfSection(void)
265 static const char testfile[] = "testfile.xxx";
266 static const char data[] = "test data for NtMapViewOfSection";
267 char buffer[sizeof(data)];
268 HANDLE file, mapping, process;
269 void *ptr, *ptr2;
270 BOOL is_wow64, ret;
271 DWORD status, written;
272 SIZE_T size, result;
273 LARGE_INTEGER offset;
274 ULONG zero_bits;
276 file = CreateFileA(testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
277 ok(file != INVALID_HANDLE_VALUE, "Failed to create test file\n");
278 WriteFile(file, data, sizeof(data), &written, NULL);
279 SetFilePointer(file, 4096, NULL, FILE_BEGIN);
280 SetEndOfFile(file);
282 /* read/write mapping */
284 mapping = CreateFileMappingA(file, NULL, PAGE_READWRITE, 0, 4096, NULL);
285 ok(mapping != 0, "CreateFileMapping failed\n");
287 process = create_target_process("sleep");
288 ok(process != NULL, "Can't start process\n");
290 ptr = NULL;
291 size = 0;
292 offset.QuadPart = 0;
293 status = NtMapViewOfSection(mapping, process, &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE);
294 ok(status == STATUS_SUCCESS, "NtMapViewOfSection returned %08x\n", status);
295 ok(!((ULONG_PTR)ptr & 0xffff), "returned memory %p is not aligned to 64k\n", ptr);
297 ret = ReadProcessMemory(process, ptr, buffer, sizeof(buffer), &result);
298 ok(ret, "ReadProcessMemory failed\n");
299 ok(result == sizeof(buffer), "ReadProcessMemory didn't read all data (%lx)\n", result);
300 ok(!memcmp(buffer, data, sizeof(buffer)), "Wrong data read\n");
302 /* 1 zero bits should zero 63-31 upper bits */
303 ptr2 = NULL;
304 size = 0;
305 zero_bits = 1;
306 offset.QuadPart = 0;
307 status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, 0, PAGE_READWRITE);
308 ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY,
309 "NtMapViewOfSection returned %08x\n", status);
310 if (status == STATUS_SUCCESS)
312 todo_wine_if((UINT_PTR)ptr2 >> (32 - zero_bits))
313 ok(((UINT_PTR)ptr2 >> (32 - zero_bits)) == 0,
314 "NtMapViewOfSection returned address: %p\n", ptr2);
316 status = NtUnmapViewOfSection(process, ptr2);
317 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08x\n", status);
320 for (zero_bits = 2; zero_bits <= 20; zero_bits++)
322 ptr2 = NULL;
323 size = 0;
324 offset.QuadPart = 0;
325 status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, 0, PAGE_READWRITE);
326 ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY,
327 "NtMapViewOfSection with %d zero_bits returned %08x\n", zero_bits, status);
328 if (status == STATUS_SUCCESS)
330 todo_wine_if((UINT_PTR)ptr2 >> (32 - zero_bits))
331 ok(((UINT_PTR)ptr2 >> (32 - zero_bits)) == 0,
332 "NtMapViewOfSection with %d zero_bits returned address %p\n", zero_bits, ptr2);
334 status = NtUnmapViewOfSection(process, ptr2);
335 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08x\n", status);
339 /* 21 zero bits never succeeds */
340 ptr2 = NULL;
341 size = 0;
342 offset.QuadPart = 0;
343 status = NtMapViewOfSection(mapping, process, &ptr2, 21, 0, &offset, &size, 1, 0, PAGE_READWRITE);
344 todo_wine
345 ok(status == STATUS_NO_MEMORY || status == STATUS_INVALID_PARAMETER,
346 "NtMapViewOfSection returned %08x\n", status);
348 /* 22 zero bits is invalid */
349 ptr2 = NULL;
350 size = 0;
351 offset.QuadPart = 0;
352 status = NtMapViewOfSection(mapping, process, &ptr2, 22, 0, &offset, &size, 1, 0, PAGE_READWRITE);
353 ok(status == STATUS_INVALID_PARAMETER_4 || status == STATUS_INVALID_PARAMETER,
354 "NtMapViewOfSection returned %08x\n", status);
356 /* zero bits > 31 should be considered as bitmask on 64bit and WoW64 */
357 ptr2 = NULL;
358 size = 0;
359 zero_bits = 0x1fffffff;
360 offset.QuadPart = 0;
361 status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, 0, PAGE_READWRITE);
363 if (sizeof(void *) == sizeof(int) && (!pIsWow64Process ||
364 !pIsWow64Process(NtCurrentProcess(), &is_wow64) || !is_wow64))
366 ok(status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %08x\n", status);
368 else
370 ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY,
371 "NtMapViewOfSection returned %08x\n", status);
372 if (status == STATUS_SUCCESS)
374 todo_wine_if((UINT_PTR)ptr2 & ~zero_bits)
375 ok(((UINT_PTR)ptr2 & ~zero_bits) == 0,
376 "NtMapViewOfSection returned address %p\n", ptr2);
378 status = NtUnmapViewOfSection(process, ptr2);
379 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08x\n", status);
383 /* mapping at the same page conflicts */
384 ptr2 = ptr;
385 size = 0;
386 offset.QuadPart = 0;
387 status = NtMapViewOfSection(mapping, process, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE);
388 ok(status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %08x\n", status);
390 /* offset has to be aligned */
391 ptr2 = ptr;
392 size = 0;
393 offset.QuadPart = 1;
394 status = NtMapViewOfSection(mapping, process, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE);
395 ok(status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %08x\n", status);
397 /* ptr has to be aligned */
398 ptr2 = (char *)ptr + 42;
399 size = 0;
400 offset.QuadPart = 0;
401 status = NtMapViewOfSection(mapping, process, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE);
402 ok(status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %08x\n", status);
404 /* still not 64k aligned */
405 ptr2 = (char *)ptr + 0x1000;
406 size = 0;
407 offset.QuadPart = 0;
408 status = NtMapViewOfSection(mapping, process, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE);
409 ok(status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %08x\n", status);
411 /* when an address is passed, it has to satisfy the provided number of zero bits */
412 ptr2 = (char *)ptr + 0x1000;
413 size = 0;
414 offset.QuadPart = 0;
415 zero_bits = get_zero_bits(((UINT_PTR)ptr2) >> 1);
416 status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, 0, PAGE_READWRITE);
417 ok(status == STATUS_INVALID_PARAMETER_4 || status == STATUS_INVALID_PARAMETER,
418 "NtMapViewOfSection returned %08x\n", status);
420 ptr2 = (char *)ptr + 0x1000;
421 size = 0;
422 offset.QuadPart = 0;
423 zero_bits = get_zero_bits((UINT_PTR)ptr2);
424 status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, 0, PAGE_READWRITE);
425 ok(status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %08x\n", status);
427 if (sizeof(void *) == sizeof(int) && (!pIsWow64Process ||
428 !pIsWow64Process(NtCurrentProcess(), &is_wow64) || !is_wow64))
430 /* new memory region conflicts with previous mapping */
431 ptr2 = ptr;
432 size = 0;
433 offset.QuadPart = 0;
434 status = NtMapViewOfSection(mapping, process, &ptr2, 0, 0, &offset,
435 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE);
436 ok(status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %08x\n", status);
438 ptr2 = (char *)ptr + 42;
439 size = 0;
440 offset.QuadPart = 0;
441 status = NtMapViewOfSection(mapping, process, &ptr2, 0, 0, &offset,
442 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE);
443 ok(status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %08x\n", status);
445 /* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
446 ptr2 = (char *)ptr + 0x1000;
447 size = 0;
448 offset.QuadPart = 0;
449 status = NtMapViewOfSection(mapping, process, &ptr2, 0, 0, &offset,
450 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE);
451 ok(status == STATUS_SUCCESS, "NtMapViewOfSection returned %08x\n", status);
452 ok((char *)ptr2 == (char *)ptr + 0x1000,
453 "expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2);
454 status = NtUnmapViewOfSection(process, ptr2);
455 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08x\n", status);
457 /* the address is rounded down if not on a page boundary */
458 ptr2 = (char *)ptr + 0x1001;
459 size = 0;
460 offset.QuadPart = 0;
461 status = NtMapViewOfSection(mapping, process, &ptr2, 0, 0, &offset,
462 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE);
463 ok(status == STATUS_SUCCESS, "NtMapViewOfSection returned %08x\n", status);
464 ok((char *)ptr2 == (char *)ptr + 0x1000,
465 "expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2);
466 status = NtUnmapViewOfSection(process, ptr2);
467 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08x\n", status);
469 ptr2 = (char *)ptr + 0x2000;
470 size = 0;
471 offset.QuadPart = 0;
472 status = NtMapViewOfSection(mapping, process, &ptr2, 0, 0, &offset,
473 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE);
474 ok(status == STATUS_SUCCESS, "NtMapViewOfSection returned %08x\n", status);
475 ok((char *)ptr2 == (char *)ptr + 0x2000,
476 "expected address %p, got %p\n", (char *)ptr + 0x2000, ptr2);
477 status = NtUnmapViewOfSection(process, ptr2);
478 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08x\n", status);
480 else
482 ptr2 = (char *)ptr + 0x1000;
483 size = 0;
484 offset.QuadPart = 0;
485 status = NtMapViewOfSection(mapping, process, &ptr2, 0, 0, &offset,
486 &size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE);
487 todo_wine
488 ok(status == STATUS_INVALID_PARAMETER_9 || status == STATUS_INVALID_PARAMETER,
489 "NtMapViewOfSection returned %08x\n", status);
492 status = NtUnmapViewOfSection(process, ptr);
493 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08x\n", status);
495 NtClose(mapping);
497 CloseHandle(file);
498 DeleteFileA(testfile);
500 TerminateProcess(process, 0);
501 CloseHandle(process);
504 START_TEST(virtual)
506 SYSTEM_BASIC_INFORMATION sbi;
507 HMODULE mod;
509 int argc;
510 char **argv;
511 argc = winetest_get_mainargs(&argv);
513 if (argc >= 3)
515 if (!strcmp(argv[2], "sleep"))
517 Sleep(5000); /* spawned process runs for at most 5 seconds */
518 return;
520 return;
523 mod = GetModuleHandleA("kernel32.dll");
524 pIsWow64Process = (void *)GetProcAddress(mod, "IsWow64Process");
526 mod = GetModuleHandleA("ntdll.dll");
527 pRtlCreateUserStack = (void *)GetProcAddress(mod, "RtlCreateUserStack");
528 pRtlFreeUserStack = (void *)GetProcAddress(mod, "RtlFreeUserStack");
530 NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL);
531 trace("system page size %#x\n", sbi.PageSize);
532 page_size = sbi.PageSize;
534 test_NtAllocateVirtualMemory();
535 test_RtlCreateUserStack();
536 test_NtMapViewOfSection();