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