[NTDLL_APITEST]
[reactos.git] / rostests / apitests / ntdll / NtMapViewOfSection.c
1 /*
2 * PROJECT: ReactOS API Tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for NtMapViewOfSection
5 * PROGRAMMERS: Timo Kreuzer
6 */
7
8 #include <apitest.h>
9 #include <strsafe.h>
10 #define WIN32_NO_STATUS
11 #include <ndk/ntndk.h>
12
13 void
14 Test_PageFileSection(void)
15 {
16 NTSTATUS Status;
17 HANDLE SectionHandle;
18 LARGE_INTEGER MaximumSize, SectionOffset;
19 PVOID BaseAddress, BaseAddress2;
20 SIZE_T ViewSize;
21 ULONG OldProtect;
22
23 /* Create a page file backed section with SEC_COMMIT */
24 MaximumSize.QuadPart = 0x20000;
25 Status = NtCreateSection(&SectionHandle,
26 SECTION_ALL_ACCESS,
27 NULL,
28 &MaximumSize,
29 PAGE_READWRITE,
30 SEC_COMMIT,
31 NULL);
32 ok_ntstatus(Status, STATUS_SUCCESS);
33 if (!NT_SUCCESS(Status))
34 return;
35
36 /* Try to map a page at an address that is not 64k aligned */
37 BaseAddress = (PVOID)0x30001000;
38 SectionOffset.QuadPart = 0;
39 ViewSize = 0x1000;
40 Status = NtMapViewOfSection(SectionHandle,
41 NtCurrentProcess(),
42 &BaseAddress,
43 0,
44 0,
45 &SectionOffset,
46 &ViewSize,
47 ViewShare,
48 0,
49 PAGE_READWRITE);
50 ok_ntstatus(Status, STATUS_MAPPED_ALIGNMENT);
51
52 /* Try to map a page with execute rights */
53 BaseAddress = (PVOID)0x30000000;
54 SectionOffset.QuadPart = 0;
55 ViewSize = 0x1000;
56 Status = NtMapViewOfSection(SectionHandle,
57 NtCurrentProcess(),
58 &BaseAddress,
59 0,
60 0,
61 &SectionOffset,
62 &ViewSize,
63 ViewShare,
64 0,
65 PAGE_EXECUTE_READWRITE);
66 ok_ntstatus(Status, STATUS_SECTION_PROTECTION);
67
68 /* Try to map 2 pages with MEM_COMMIT */
69 BaseAddress = (PVOID)0x30000000;
70 SectionOffset.QuadPart = 0;
71 ViewSize = 0x2000;
72 Status = NtMapViewOfSection(SectionHandle,
73 NtCurrentProcess(),
74 &BaseAddress,
75 0,
76 PAGE_SIZE,
77 &SectionOffset,
78 &ViewSize,
79 ViewShare,
80 MEM_COMMIT,
81 PAGE_READWRITE);
82 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_9);
83
84 /* Map 2 pages, without MEM_COMMIT */
85 BaseAddress = (PVOID)0x30000000;
86 SectionOffset.QuadPart = 0;
87 ViewSize = 0x2000;
88 Status = NtMapViewOfSection(SectionHandle,
89 NtCurrentProcess(),
90 &BaseAddress,
91 0,
92 0,
93 &SectionOffset,
94 &ViewSize,
95 ViewShare,
96 0,
97 PAGE_READWRITE);
98 ok_ntstatus(Status, STATUS_SUCCESS);
99
100 /* We must be able to access the memory */
101 _SEH2_TRY
102 {
103 *(PULONG)BaseAddress = 1;
104 }
105 _SEH2_EXCEPT(1)
106 {
107 ok(FALSE, "Got an exception\n");
108 }
109 _SEH2_END;
110
111 /* Commit a page in the section */
112 BaseAddress = (PVOID)0x30000000;
113 ViewSize = 0x1000;
114 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
115 &BaseAddress,
116 0,
117 &ViewSize,
118 MEM_COMMIT,
119 PAGE_READWRITE);
120 ok_ntstatus(Status, STATUS_SUCCESS);
121
122 /* Try to decommit a page in the section */
123 Status = NtFreeVirtualMemory(NtCurrentProcess(),
124 &BaseAddress,
125 &ViewSize,
126 MEM_DECOMMIT);
127 ok_ntstatus(Status, STATUS_UNABLE_TO_DELETE_SECTION);
128
129 /* Try to commit a range larger than the section */
130 BaseAddress = (PVOID)0x30000000;
131 ViewSize = 0x3000;
132 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
133 &BaseAddress,
134 0,
135 &ViewSize,
136 MEM_COMMIT,
137 PAGE_READWRITE);
138 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
139
140 /* Try to commit a page after the section */
141 BaseAddress = (PVOID)0x30002000;
142 ViewSize = 0x1000;
143 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
144 &BaseAddress,
145 0,
146 &ViewSize,
147 MEM_COMMIT,
148 PAGE_READWRITE);
149 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
150
151 /* Try to allocate a page after the section */
152 BaseAddress = (PVOID)0x30002000;
153 ViewSize = 0x1000;
154 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
155 &BaseAddress,
156 0,
157 &ViewSize,
158 MEM_RESERVE | MEM_COMMIT,
159 PAGE_READWRITE);
160 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
161
162 /* Need to go to next 64k boundary */
163 BaseAddress = (PVOID)0x30010000;
164 ViewSize = 0x1000;
165 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
166 &BaseAddress,
167 0,
168 &ViewSize,
169 MEM_RESERVE | MEM_COMMIT,
170 PAGE_READWRITE);
171 ok_ntstatus(Status, STATUS_SUCCESS);
172 if (!NT_SUCCESS(Status))
173 return;
174
175 /* Free the allocation */
176 BaseAddress = (PVOID)0x30010000;
177 ViewSize = 0x1000;
178 Status = NtFreeVirtualMemory(NtCurrentProcess(),
179 &BaseAddress,
180 &ViewSize,
181 MEM_RELEASE);
182 ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed with Status %lx\n", Status);
183
184 /* Try to release the section mapping with NtFreeVirtualMemory */
185 BaseAddress = (PVOID)0x30000000;
186 ViewSize = 0x1000;
187 Status = NtFreeVirtualMemory(NtCurrentProcess(),
188 &BaseAddress,
189 &ViewSize,
190 MEM_RELEASE);
191 ok_ntstatus(Status, STATUS_UNABLE_TO_DELETE_SECTION);
192
193 /* Commit a page in the section */
194 BaseAddress = (PVOID)0x30001000;
195 ViewSize = 0x1000;
196 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
197 &BaseAddress,
198 0,
199 &ViewSize,
200 MEM_COMMIT,
201 PAGE_READWRITE);
202 ok_ntstatus(Status, STATUS_SUCCESS);
203
204 /* Try to decommit the page */
205 BaseAddress = (PVOID)0x30001000;
206 ViewSize = 0x1000;
207 Status = NtFreeVirtualMemory(NtCurrentProcess(),
208 &BaseAddress,
209 &ViewSize,
210 MEM_DECOMMIT);
211 ok_ntstatus(Status, STATUS_UNABLE_TO_DELETE_SECTION);
212
213 BaseAddress = UlongToPtr(0x40000000);
214 SectionOffset.QuadPart = 0;
215 ViewSize = 0x1000;
216 Status = NtMapViewOfSection(SectionHandle,
217 NtCurrentProcess(),
218 &BaseAddress,
219 0,
220 0,
221 &SectionOffset,
222 &ViewSize,
223 ViewShare,
224 0,
225 PAGE_READWRITE);
226 ok_ntstatus(Status, STATUS_SUCCESS);
227 if (!NT_SUCCESS(Status))
228 return;
229
230 ok(BaseAddress == UlongToPtr(0x40000000), "Invalid BaseAddress: %p\n", BaseAddress);
231
232 BaseAddress = (PVOID)0x40080000;
233 SectionOffset.QuadPart = 0x10000;
234 ViewSize = 0x1000;
235 Status = NtMapViewOfSection(SectionHandle,
236 NtCurrentProcess(),
237 &BaseAddress,
238 0,
239 0,
240 &SectionOffset,
241 &ViewSize,
242 ViewShare,
243 0,
244 PAGE_READWRITE);
245 ok_ntstatus(Status, STATUS_SUCCESS);
246
247 ok(BaseAddress == (PVOID)0x40080000, "Invalid BaseAddress: %p\n", BaseAddress);
248
249 /* Commit a page in the section */
250 BaseAddress = (PVOID)0x40000000;
251 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
252 &BaseAddress,
253 0,
254 &ViewSize,
255 MEM_COMMIT,
256 PAGE_READWRITE);
257 ok_ntstatus(Status, STATUS_SUCCESS);
258
259 /* Close the mapping */
260 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
261 ok_ntstatus(Status, STATUS_SUCCESS);
262 BaseAddress = (PVOID)0x30000000;
263 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
264 ok_ntstatus(Status, STATUS_SUCCESS);
265 Status = NtClose(SectionHandle);
266 ok_ntstatus(Status, STATUS_SUCCESS);
267
268 /* Create a page file backed section, but only reserved */
269 MaximumSize.QuadPart = 0x20000;
270 Status = NtCreateSection(&SectionHandle,
271 SECTION_ALL_ACCESS,
272 NULL,
273 &MaximumSize,
274 PAGE_READWRITE,
275 SEC_RESERVE,
276 NULL);
277 ok_ntstatus(Status, STATUS_SUCCESS);
278
279 /* Try to map 1 page, passing MEM_RESERVE */
280 BaseAddress = NULL;
281 SectionOffset.QuadPart = 0;
282 ViewSize = PAGE_SIZE;
283 Status = NtMapViewOfSection(SectionHandle,
284 NtCurrentProcess(),
285 &BaseAddress,
286 0,
287 PAGE_SIZE,
288 &SectionOffset,
289 &ViewSize,
290 ViewShare,
291 MEM_RESERVE,
292 PAGE_READWRITE);
293 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_9);
294
295 /* Try to map 1 page using MEM_COMMIT */
296 BaseAddress = NULL;
297 SectionOffset.QuadPart = 0;
298 ViewSize = PAGE_SIZE;
299 Status = NtMapViewOfSection(SectionHandle,
300 NtCurrentProcess(),
301 &BaseAddress,
302 0,
303 PAGE_SIZE,
304 &SectionOffset,
305 &ViewSize,
306 ViewShare,
307 MEM_COMMIT,
308 PAGE_READWRITE);
309 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_9);
310
311 /* Map 2 pages, but commit 1 */
312 BaseAddress = NULL;
313 SectionOffset.QuadPart = 0;
314 ViewSize = 2 * PAGE_SIZE;
315 Status = NtMapViewOfSection(SectionHandle,
316 NtCurrentProcess(),
317 &BaseAddress,
318 0,
319 PAGE_SIZE,
320 &SectionOffset,
321 &ViewSize,
322 ViewShare,
323 0,
324 PAGE_READWRITE);
325 ok_ntstatus(Status, STATUS_SUCCESS);
326
327 /* We must be able to access the 1st page */
328 Status = STATUS_SUCCESS;
329 _SEH2_TRY
330 {
331 *(PUCHAR)BaseAddress = 1;
332 }
333 _SEH2_EXCEPT(1)
334 {
335 Status = _SEH2_GetExceptionCode();
336 }
337 _SEH2_END;
338 ok_ntstatus(Status, STATUS_SUCCESS);
339
340 /* We must not be able to access the 2nd page */
341 Status = STATUS_SUCCESS;
342 _SEH2_TRY
343 {
344 *((PUCHAR)BaseAddress + PAGE_SIZE) = 1;
345 }
346 _SEH2_EXCEPT(1)
347 {
348 Status = _SEH2_GetExceptionCode();
349 }
350 _SEH2_END;
351 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
352
353 /* Map the 2 pages again into a different memory location */
354 BaseAddress2 = NULL;
355 Status = NtMapViewOfSection(SectionHandle,
356 NtCurrentProcess(),
357 &BaseAddress2,
358 0,
359 0,
360 &SectionOffset,
361 &ViewSize,
362 ViewShare,
363 0,
364 PAGE_READWRITE);
365 ok_ntstatus(Status, STATUS_SUCCESS);
366
367 /* Commit a the 2nd page in the 2nd memory location */
368 BaseAddress2 = (PUCHAR)BaseAddress2 + PAGE_SIZE;
369 ViewSize = PAGE_SIZE;
370 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
371 &BaseAddress2,
372 0,
373 &ViewSize,
374 MEM_COMMIT,
375 PAGE_READONLY);
376 ok_ntstatus(Status, STATUS_SUCCESS);
377
378 /* Try to commit again (the already committed page) */
379 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
380 &BaseAddress2,
381 0,
382 &ViewSize,
383 MEM_COMMIT,
384 PAGE_READONLY);
385 ok_ntstatus(Status, STATUS_SUCCESS);
386
387 /* We must be able to access the memory in the 2nd page of the 1st memory location */
388 Status = STATUS_SUCCESS;
389 _SEH2_TRY
390 {
391 *((PUCHAR)BaseAddress + PAGE_SIZE) = 2;
392 }
393 _SEH2_EXCEPT(1)
394 {
395 Status = _SEH2_GetExceptionCode();
396 }
397 _SEH2_END;
398 ok_ntstatus(Status, STATUS_SUCCESS);
399
400 ok(*(PULONG)BaseAddress2 == 2, "Value in memory was wrong\n");
401
402 /* Close the mapping */
403 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
404 ok_ntstatus(Status, STATUS_SUCCESS);
405 Status = NtUnmapViewOfSection(NtCurrentProcess(), (PUCHAR)BaseAddress2 - PAGE_SIZE);
406 ok_ntstatus(Status, STATUS_SUCCESS);
407 Status = NtClose(SectionHandle);
408 ok_ntstatus(Status, STATUS_SUCCESS);
409
410 /* Try to create a 512 GB page file backed section with committed pages */
411 MaximumSize.QuadPart = 0x8000000000;
412 Status = NtCreateSection(&SectionHandle,
413 SECTION_ALL_ACCESS,
414 NULL,
415 &MaximumSize,
416 PAGE_READWRITE,
417 SEC_COMMIT,
418 NULL);
419 ok_ntstatus(Status, STATUS_COMMITMENT_LIMIT);
420
421 /* Try to create a huge page file backed section with PAGE_NOACCESS protection */
422 MaximumSize.QuadPart = 0x8000000000;
423 Status = NtCreateSection(&SectionHandle,
424 SECTION_ALL_ACCESS,
425 NULL,
426 &MaximumSize,
427 PAGE_NOACCESS,
428 SEC_COMMIT,
429 NULL);
430 ok_ntstatus(Status, STATUS_INVALID_PAGE_PROTECTION);
431
432 /* Try to create a very huge page file backed section, but only reserved */
433 MaximumSize.QuadPart = 0x80000000000;
434 Status = NtCreateSection(&SectionHandle,
435 SECTION_ALL_ACCESS,
436 NULL,
437 &MaximumSize,
438 PAGE_READWRITE,
439 SEC_RESERVE,
440 NULL);
441 #ifdef _WIN64
442 ok_ntstatus(Status, STATUS_INSUFFICIENT_RESOURCES);
443 #else
444 /* WoW64 returns STATUS_INSUFFICIENT_RESOURCES */
445 ok((Status == STATUS_INSUFFICIENT_RESOURCES) || (Status == STATUS_SECTION_TOO_BIG),
446 "got wrong Status: 0x%lx\n", Status);
447 #endif
448
449 /* Try to create a even huger page file backed section, but only reserved */
450 MaximumSize.QuadPart = 0x800000000000;
451 Status = NtCreateSection(&SectionHandle,
452 SECTION_ALL_ACCESS,
453 NULL,
454 &MaximumSize,
455 PAGE_READWRITE,
456 SEC_RESERVE,
457 NULL);
458 ok_ntstatus(Status, STATUS_SECTION_TOO_BIG);
459
460 /* Create a 8 GB page file backed section, but only reserved */
461 MaximumSize.QuadPart = 0x200000000;
462 Status = NtCreateSection(&SectionHandle,
463 SECTION_ALL_ACCESS,
464 NULL,
465 &MaximumSize,
466 PAGE_READWRITE,
467 SEC_RESERVE,
468 NULL);
469 ok_ntstatus(Status, STATUS_SUCCESS);
470
471 /* Pass a too large region size */
472 BaseAddress = NULL;
473 SectionOffset.QuadPart = 0;
474 ViewSize = MAXULONG_PTR;
475 Status = NtMapViewOfSection(SectionHandle,
476 NtCurrentProcess(),
477 &BaseAddress,
478 0,
479 0,
480 &SectionOffset,
481 &ViewSize,
482 ViewShare,
483 0,
484 PAGE_READWRITE);
485 #ifdef _WIN64
486 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_3);
487 #else
488 /* WoW64 returns STATUS_INVALID_PARAMETER_4 */
489 ok((Status == STATUS_INVALID_PARAMETER_4) || (Status == STATUS_INVALID_PARAMETER_3),
490 "got wrong Status: 0x%lx\n", Status);
491 #endif
492
493 /* Pass 0 region size */
494 BaseAddress = NULL;
495 SectionOffset.QuadPart = 0;
496 ViewSize = 0;
497 Status = NtMapViewOfSection(SectionHandle,
498 NtCurrentProcess(),
499 &BaseAddress,
500 0,
501 0,
502 &SectionOffset,
503 &ViewSize,
504 ViewShare,
505 0,
506 PAGE_READWRITE);
507 #ifdef _WIN64
508 ok_ntstatus(Status, STATUS_SUCCESS);
509 ok(ViewSize == 0x200000000, "wrong ViewSize: 0x%Ix\n", ViewSize);
510 #else
511 /* WoW64 returns STATUS_NO_MEMORY */
512 ok((Status == STATUS_NO_MEMORY) || (Status == STATUS_INVALID_VIEW_SIZE),
513 "got wrong Status: 0x%lx\n", Status);
514 ok(ViewSize == 0, "wrong ViewSize: 0x%Ix\n", ViewSize);
515 #endif
516
517 /* Map with PAGE_NOACCESS */
518 BaseAddress = NULL;
519 SectionOffset.QuadPart = 0;
520 ViewSize = 0x20000000;
521 Status = NtMapViewOfSection(SectionHandle,
522 NtCurrentProcess(),
523 &BaseAddress,
524 0,
525 0,
526 &SectionOffset,
527 &ViewSize,
528 ViewShare,
529 0,
530 PAGE_NOACCESS);
531 ok_ntstatus(Status, STATUS_SUCCESS);
532
533 /* Try to change protection to read/write */
534 ViewSize = 0x1000;
535 OldProtect = -1;
536 BaseAddress2 = BaseAddress;
537 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READWRITE, &OldProtect);
538 ok_ntstatus(Status, STATUS_SECTION_PROTECTION);
539 // Windows 2003 returns bogus
540 //ok(OldProtect == PAGE_READWRITE, "Wrong protection returned: %u\n", OldProtect);
541
542 /* Test read access */
543 Status = STATUS_SUCCESS;
544 _SEH2_TRY
545 {
546 (void)(*(volatile char*)BaseAddress2);
547 }
548 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
549 {
550 Status = _SEH2_GetExceptionCode();
551 }
552 _SEH2_END;
553 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
554
555 /* Try to change protection to read/write */
556 ViewSize = 0x1000;
557 OldProtect = -1;
558 BaseAddress2 = BaseAddress;
559 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READWRITE, &OldProtect);
560 ok_ntstatus(Status, STATUS_SECTION_PROTECTION);
561 #ifdef _WIN64
562 ok(OldProtect == 0, "Wrong protection returned: 0x%lx\n", OldProtect);
563 #else
564 // Windows 2003 returns bogus
565 #endif
566
567 /* Try to change protection to readonly */
568 ViewSize = 0x1000;
569 OldProtect = -1;
570 BaseAddress2 = BaseAddress;
571 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READONLY, &OldProtect);
572 ok_ntstatus(Status, STATUS_SECTION_PROTECTION);
573 #ifdef _WIN64
574 //ok(OldProtect == 0, "Wrong protection returned: 0x%lx\n", OldProtect);
575 #else
576 // Windows 2003 returns bogus
577 #endif
578
579 /* Commit a page */
580 ViewSize = 0x1000;
581 BaseAddress2 = BaseAddress;
582 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READONLY);
583 ok_ntstatus(Status, STATUS_SUCCESS);
584 ok(BaseAddress2 == BaseAddress, "Invalid base address: %p\n", BaseAddress2);
585
586 /* Commit the page again */
587 ViewSize = 0x1000;
588 BaseAddress2 = BaseAddress;
589 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READONLY);
590 ok_ntstatus(Status, STATUS_SUCCESS);
591 ok(BaseAddress2 == BaseAddress, "Invalid base address: %p\n", BaseAddress2);
592
593 /* Test read access */
594 Status = STATUS_SUCCESS;
595 _SEH2_TRY
596 {
597 (void)(*(volatile char*)BaseAddress2);
598 }
599 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
600 {
601 Status = _SEH2_GetExceptionCode();
602 }
603 _SEH2_END;
604 ok_ntstatus(Status, STATUS_SUCCESS);
605
606 /* Test write access */
607 Status = STATUS_SUCCESS;
608 _SEH2_TRY
609 {
610 *(char*)BaseAddress2 = 1;
611 }
612 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
613 {
614 Status = _SEH2_GetExceptionCode();
615 }
616 _SEH2_END;
617 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
618
619 /* Update protection to PAGE_READWRITE */
620 ViewSize = 0x1000;
621 BaseAddress2 = BaseAddress;
622 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READWRITE);
623 ok_ntstatus(Status, STATUS_SUCCESS);
624
625 /* Test write access */
626 Status = STATUS_SUCCESS;
627 _SEH2_TRY
628 {
629 *(char*)BaseAddress2 = 1;
630 }
631 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
632 {
633 Status = _SEH2_GetExceptionCode();
634 }
635 _SEH2_END;
636 ok_ntstatus(Status, STATUS_SUCCESS);
637
638 /* Update protection to PAGE_EXECUTE_READWRITE (1 page) */
639 ViewSize = 0x1000;
640 BaseAddress2 = BaseAddress;
641 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
642 ok_ntstatus(Status, STATUS_SUCCESS);
643
644 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
645 ok_ntstatus(Status, STATUS_SUCCESS);
646 Status = NtClose(SectionHandle);
647 ok_ntstatus(Status, STATUS_SUCCESS);
648 }
649
650 void
651 Test_ImageSection(void)
652 {
653 UNICODE_STRING FileName;
654 NTSTATUS Status;
655 OBJECT_ATTRIBUTES FileObjectAttributes;
656 IO_STATUS_BLOCK IoStatusBlock;
657 WCHAR TestDllPath[MAX_PATH];
658 HANDLE FileHandle, DataSectionHandle, ImageSectionHandle;
659 PVOID DataBase, ImageBase;
660 SIZE_T ViewSize;
661
662 GetModuleFileNameW(NULL, TestDllPath, RTL_NUMBER_OF(TestDllPath));
663 wcsrchr(TestDllPath, L'\\')[1] = UNICODE_NULL;
664 StringCbCatW(TestDllPath, sizeof(TestDllPath), L"testdata\\test.dll");
665 if (!RtlDosPathNameToNtPathName_U(TestDllPath,
666 &FileName,
667 NULL,
668 NULL))
669 {
670 ok(0, "RtlDosPathNameToNtPathName_U failed\n");
671 return;
672 }
673
674 InitializeObjectAttributes(&FileObjectAttributes,
675 &FileName,
676 0,
677 NULL,
678 NULL);
679
680 Status = NtOpenFile(&FileHandle,
681 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
682 &FileObjectAttributes,
683 &IoStatusBlock,
684 FILE_SHARE_READ,
685 FILE_SYNCHRONOUS_IO_NONALERT);
686 ok_ntstatus(Status, STATUS_SUCCESS);
687 if (!NT_SUCCESS(Status))
688 {
689 skip("Failed to open file\n");
690 return;
691 }
692
693 /* Create a data section with write access */
694 Status = NtCreateSection(&DataSectionHandle,
695 SECTION_ALL_ACCESS, // DesiredAccess
696 NULL, // ObjectAttributes
697 NULL, // MaximumSize
698 PAGE_READWRITE, // SectionPageProtection
699 SEC_COMMIT, // AllocationAttributes
700 FileHandle);
701 ok_ntstatus(Status, STATUS_SUCCESS);
702 if (!NT_SUCCESS(Status))
703 {
704 skip("Failed to create data section\n");
705 NtClose(FileHandle);
706 return;
707 }
708
709 /* Map the data section as flat mapping */
710 DataBase = NULL;
711 ViewSize = 0;
712 Status = NtMapViewOfSection(DataSectionHandle,
713 NtCurrentProcess(),
714 &DataBase,
715 0,
716 0,
717 NULL,
718 &ViewSize,
719 ViewShare,
720 0,
721 PAGE_READWRITE);
722 ok_ntstatus(Status, STATUS_SUCCESS);
723 //ok(ViewSize == 0x3f95cc48, "ViewSize wrong: 0x%lx\n");
724 if (!NT_SUCCESS(Status))
725 {
726 skip("Failed to map view of data section\n");
727 NtClose(DataSectionHandle);
728 NtClose(FileHandle);
729 return;
730 }
731
732 /* Check the original data */
733 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
734
735 /* Modify the PE header (but do not flush!) */
736 *(ULONG*)DataBase = 0xdeadbabe;
737 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
738
739 /* Modify data in the .data section (but do not flush!) */
740 ok(*(ULONG*)((PUCHAR)DataBase + 0x800) == 0x12345678,
741 "Data in .data section invalid: 0x%lx!\n", *(ULONG*)((PUCHAR)DataBase + 0x800));
742 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x87654321;
743
744 /* Now try to create an image section (should fail) */
745 Status = NtCreateSection(&ImageSectionHandle,
746 SECTION_ALL_ACCESS, // DesiredAccess
747 NULL, // ObjectAttributes
748 NULL, // MaximumSize
749 PAGE_READWRITE, // SectionPageProtection
750 SEC_IMAGE, // AllocationAttributes
751 FileHandle);
752 ok_ntstatus(Status, STATUS_INVALID_IMAGE_NOT_MZ);
753 if (NT_SUCCESS(Status)) NtClose(ImageSectionHandle);
754
755 /* Restore the original header */
756 *(ULONG*)DataBase = 0x00905a4d;
757
758 /* Modify data in the .data section (but do not flush!) */
759 ok_hex(*(ULONG*)((PUCHAR)DataBase + 0x800), 0x87654321);
760 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xdeadbabe;
761
762 /* Try to create an image section again */
763 Status = NtCreateSection(&ImageSectionHandle,
764 SECTION_ALL_ACCESS, // DesiredAccess
765 NULL, // ObjectAttributes
766 NULL, // MaximumSize
767 PAGE_READWRITE, // SectionPageProtection
768 SEC_IMAGE, // AllocationAttributes
769 FileHandle);
770 ok_ntstatus(Status, STATUS_SUCCESS);
771 if (!NT_SUCCESS(Status))
772 {
773 skip("Failed to create image section\n");
774 NtClose(DataSectionHandle);
775 NtClose(FileHandle);
776 return;
777 }
778
779 /* Map the image section */
780 ImageBase = NULL;
781 ViewSize = 0;
782 Status = NtMapViewOfSection(ImageSectionHandle,
783 NtCurrentProcess(),
784 &ImageBase,
785 0, // ZeroBits
786 0, // CommitSize
787 NULL, // SectionOffset
788 &ViewSize,
789 ViewShare,
790 0, // AllocationType
791 PAGE_READONLY);
792 #ifdef _M_IX86
793 ok_ntstatus(Status, STATUS_SUCCESS);
794 #else
795 ok_ntstatus(Status, STATUS_IMAGE_MACHINE_TYPE_MISMATCH);
796 #endif
797 if (!NT_SUCCESS(Status))
798 {
799 skip("Failed to map view of image section\n");
800 NtClose(ImageSectionHandle);
801 NtClose(DataSectionHandle);
802 NtClose(FileHandle);
803 return;
804 }
805
806 /* Check the header */
807 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
808 ok(*(ULONG*)ImageBase == 0x00905a4d, "Header not ok\n");
809
810 /* Check the data section. Either of these can be present! */
811 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
812 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
813 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
814
815 /* Now modify the data again */
816 *(ULONG*)DataBase = 0xdeadbabe;
817 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xf00dada;
818
819 /* Check the data */
820 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
821 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
822 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
823 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
824 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
825
826 /* Flush the view */
827 ViewSize = 0x1000;
828 Status = NtFlushVirtualMemory(NtCurrentProcess(),
829 &DataBase,
830 &ViewSize,
831 &IoStatusBlock);
832 ok_ntstatus(Status, STATUS_SUCCESS);
833
834 /* Check the data again */
835 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
836 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
837 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
838 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
839
840 /* Restore the original header */
841 *(ULONG*)DataBase = 0x00905a4d;
842 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
843
844 /* Close the image mapping */
845 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
846 NtClose(ImageSectionHandle);
847
848 /* Create an image section again */
849 Status = NtCreateSection(&ImageSectionHandle,
850 SECTION_ALL_ACCESS, // DesiredAccess
851 NULL, // ObjectAttributes
852 NULL, // MaximumSize
853 PAGE_READWRITE, // SectionPageProtection
854 SEC_IMAGE, // AllocationAttributes
855 FileHandle);
856 ok_ntstatus(Status, STATUS_SUCCESS);
857 if (!NT_SUCCESS(Status))
858 {
859 skip("Failed to create image section\n");
860 NtClose(DataSectionHandle);
861 NtClose(FileHandle);
862 return;
863 }
864
865 /* Map the image section again */
866 ImageBase = NULL;
867 ViewSize = 0;
868 Status = NtMapViewOfSection(ImageSectionHandle,
869 NtCurrentProcess(),
870 &ImageBase,
871 0,
872 0,
873 NULL,
874 &ViewSize,
875 ViewShare,
876 0,
877 PAGE_READONLY);
878 #ifdef _M_IX86
879 ok_ntstatus(Status, STATUS_SUCCESS);
880 #else
881 ok_ntstatus(Status, STATUS_IMAGE_MACHINE_TYPE_MISMATCH);
882 #endif
883 if (!NT_SUCCESS(Status))
884 {
885 skip("Failed to map view of image section\n");
886 NtClose(ImageSectionHandle);
887 NtClose(DataSectionHandle);
888 NtClose(FileHandle);
889 return;
890 }
891
892 // This one doesn't always work, needs investigation
893 /* Check the .data section again */
894 //ok(*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0xf00dada,
895 // "Data should be synced: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
896
897 /* Restore the original data */
898 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x12345678;
899
900 /* Close the data mapping */
901 NtUnmapViewOfSection(NtCurrentProcess(), DataBase);
902
903 NtClose(DataSectionHandle);
904
905 /* Try to allocate memory inside the image mapping */
906 DataBase = (PUCHAR)ImageBase + 0x20000;
907 ViewSize = 0x1000;
908 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &DataBase, 0, &ViewSize, MEM_RESERVE, PAGE_NOACCESS);
909 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
910
911 /* Cleanup */
912 NtClose(FileHandle);
913 NtClose(ImageSectionHandle);
914 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
915 }
916
917 void
918 Test_ImageSection2(void)
919 {
920 UNICODE_STRING FileName;
921 NTSTATUS Status;
922 OBJECT_ATTRIBUTES FileObjectAttributes;
923 IO_STATUS_BLOCK IoStatusBlock;
924 HANDLE FileHandle, ImageSectionHandle;
925 PVOID ImageBase, BaseAddress;
926 SIZE_T ViewSize;
927 LARGE_INTEGER MaximumSize, SectionOffset;
928
929 if (!RtlDosPathNameToNtPathName_U(L"testdata\\nvoglv32.dll",
930 &FileName,
931 NULL,
932 NULL))
933 {
934 ok(0, "RtlDosPathNameToNtPathName_U failed\n");
935 return;
936 }
937
938 InitializeObjectAttributes(&FileObjectAttributes,
939 &FileName,
940 0,
941 NULL,
942 NULL);
943
944 Status = NtOpenFile(&FileHandle,
945 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
946 &FileObjectAttributes,
947 &IoStatusBlock,
948 FILE_SHARE_READ,
949 FILE_SYNCHRONOUS_IO_NONALERT);
950 ok_ntstatus(Status, STATUS_SUCCESS);
951 printf("Opened file with handle %p\n", FileHandle);
952
953 /* Create a data section with write access */
954 MaximumSize.QuadPart = 0x20000;
955 Status = NtCreateSection(&ImageSectionHandle,
956 SECTION_ALL_ACCESS, // DesiredAccess
957 NULL, // ObjectAttributes
958 &MaximumSize, // MaximumSize
959 PAGE_READWRITE, // SectionPageProtection
960 SEC_IMAGE, // AllocationAttributes
961 FileHandle);
962 ok_ntstatus(Status, STATUS_SUCCESS);
963
964 printf("Created image section with handle %p\n", ImageSectionHandle);
965 //system("PAUSE");
966
967 /* Map the image section */
968 ImageBase = NULL;
969 ViewSize = 0x0000;
970 SectionOffset.QuadPart = 0x00000;
971 Status = NtMapViewOfSection(ImageSectionHandle,
972 NtCurrentProcess(),
973 &ImageBase,
974 0,
975 0,
976 &SectionOffset,
977 &ViewSize,
978 ViewShare,
979 0,
980 PAGE_READWRITE);
981 ok_ntstatus(Status, STATUS_SUCCESS);
982
983 printf("Mapped image section at %p, value in text section: %lx\n",
984 ImageBase, *((ULONG*)((PCHAR)ImageBase + 0x1196)));
985 system("PAUSE");
986
987 /* Try to allocate a page after the section */
988 BaseAddress = (PUCHAR)ImageBase + 0x10000;
989 ViewSize = 0x1000;
990 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
991 &BaseAddress,
992 0,
993 &ViewSize,
994 MEM_RESERVE | MEM_COMMIT,
995 PAGE_READWRITE);
996 printf("allocation status: %lx\n", Status);
997 system("PAUSE");
998
999 }
1000
1001 // doesn't work with WoW64!
1002 void
1003 Test_BasedSection(void)
1004 {
1005 NTSTATUS Status;
1006 HANDLE SectionHandle1, SectionHandle2;
1007 LARGE_INTEGER MaximumSize, SectionOffset;
1008 PVOID BaseAddress1, BaseAddress2;
1009 SIZE_T ViewSize;
1010
1011 /* Create a based section with SEC_COMMIT */
1012 MaximumSize.QuadPart = 0x1000;
1013 Status = NtCreateSection(&SectionHandle1,
1014 SECTION_ALL_ACCESS,
1015 NULL,
1016 &MaximumSize,
1017 PAGE_READWRITE,
1018 SEC_COMMIT | SEC_BASED,
1019 NULL);
1020 ok_ntstatus(Status, STATUS_SUCCESS);
1021
1022 /* Map the 1st section */
1023 BaseAddress1 = NULL;
1024 SectionOffset.QuadPart = 0;
1025 ViewSize = 0;
1026 Status = NtMapViewOfSection(SectionHandle1,
1027 NtCurrentProcess(),
1028 &BaseAddress1,
1029 0,
1030 0,
1031 &SectionOffset,
1032 &ViewSize,
1033 ViewShare,
1034 0,
1035 PAGE_READWRITE);
1036 #if 0 // WOW64?
1037 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
1038 #else
1039 ok_ntstatus(Status, STATUS_SUCCESS);
1040 #endif
1041
1042 /* Create a 2nd based section with SEC_COMMIT */
1043 MaximumSize.QuadPart = 0x1000;
1044 Status = NtCreateSection(&SectionHandle2,
1045 SECTION_ALL_ACCESS,
1046 NULL,
1047 &MaximumSize,
1048 PAGE_READWRITE,
1049 SEC_COMMIT | SEC_BASED,
1050 NULL);
1051 ok_ntstatus(Status, STATUS_SUCCESS);//
1052
1053 /* Map the 2nd section */
1054 BaseAddress2 = NULL;
1055 SectionOffset.QuadPart = 0;
1056 ViewSize = 0;
1057 Status = NtMapViewOfSection(SectionHandle2,
1058 NtCurrentProcess(),
1059 &BaseAddress2,
1060 0,
1061 0,
1062 &SectionOffset,
1063 &ViewSize,
1064 ViewShare,
1065 0,
1066 PAGE_READWRITE);
1067 #if 0 // WOW64?
1068 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
1069 #else
1070 ok_ntstatus(Status, STATUS_SUCCESS);
1071 ok((ULONG_PTR)BaseAddress2 < (ULONG_PTR)BaseAddress1,
1072 "Invalid addresses: BaseAddress1=%p, BaseAddress2=%p\n", BaseAddress1, BaseAddress2);
1073 ok(((ULONG_PTR)BaseAddress1 - (ULONG_PTR)BaseAddress2) == 0x10000,
1074 "Invalid addresses: BaseAddress1=%p, BaseAddress2=%p\n", BaseAddress1, BaseAddress2);
1075 #endif
1076
1077 }
1078
1079 START_TEST(NtMapViewOfSection)
1080 {
1081 Test_PageFileSection();
1082 Test_ImageSection();
1083 Test_BasedSection();
1084 }