[SPIDER]
[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", 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", 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");
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", 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", 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", 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
681 /* Create a data section with write access */
682 Status = NtCreateSection(&DataSectionHandle,
683 SECTION_ALL_ACCESS, // DesiredAccess
684 NULL, // ObjectAttributes
685 NULL, // MaximumSize
686 PAGE_READWRITE, // SectionPageProtection
687 SEC_COMMIT, // AllocationAttributes
688 FileHandle);
689 ok_ntstatus(Status, STATUS_SUCCESS);
690
691 /* Map the data section as flat mapping */
692 DataBase = NULL;
693 ViewSize = 0;
694 Status = NtMapViewOfSection(DataSectionHandle,
695 NtCurrentProcess(),
696 &DataBase,
697 0,
698 0,
699 NULL,
700 &ViewSize,
701 ViewShare,
702 0,
703 PAGE_READWRITE);
704 ok_ntstatus(Status, STATUS_SUCCESS);
705 //ok(ViewSize == 0x3f95cc48, "ViewSize wrong: 0x%lx\n");
706
707 /* Check the original data */
708 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
709
710 /* Modify the PE header (but do not flush!) */
711 *(ULONG*)DataBase = 0xdeadbabe;
712 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
713
714 /* Modify data in the .data section (but do not flush!) */
715 ok(*(ULONG*)((PUCHAR)DataBase + 0x800) == 0x12345678,
716 "Data in .data section invalid: 0x%lx!\n", *(ULONG*)((PUCHAR)DataBase + 0x800));
717 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x87654321;
718
719 /* Now try to create an image section (should fail) */
720 Status = NtCreateSection(&ImageSectionHandle,
721 SECTION_ALL_ACCESS, // DesiredAccess
722 NULL, // ObjectAttributes
723 NULL, // MaximumSize
724 PAGE_READWRITE, // SectionPageProtection
725 SEC_IMAGE, // AllocationAttributes
726 FileHandle);
727 ok_ntstatus(Status, STATUS_INVALID_IMAGE_NOT_MZ);
728
729 /* Restore the original header */
730 *(ULONG*)DataBase = 0x00905a4d;
731
732 /* Modify data in the .data section (but do not flush!) */
733 ok_hex(*(ULONG*)((PUCHAR)DataBase + 0x800), 0x87654321);
734 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xdeadbabe;
735
736 /* Try to create an image section again */
737 Status = NtCreateSection(&ImageSectionHandle,
738 SECTION_ALL_ACCESS, // DesiredAccess
739 NULL, // ObjectAttributes
740 NULL, // MaximumSize
741 PAGE_READWRITE, // SectionPageProtection
742 SEC_IMAGE, // AllocationAttributes
743 FileHandle);
744 ok_ntstatus(Status, STATUS_SUCCESS);
745
746 /* Map the image section */
747 ImageBase = NULL;
748 ViewSize = 0;
749 Status = NtMapViewOfSection(ImageSectionHandle,
750 NtCurrentProcess(),
751 &ImageBase,
752 0, // ZeroBits
753 0, // CommitSize
754 NULL, // SectionOffset
755 &ViewSize,
756 ViewShare,
757 0, // AllocationType
758 PAGE_READONLY);
759 #ifdef _M_IX86
760 ok_ntstatus(Status, STATUS_IMAGE_NOT_AT_BASE);
761 #else
762 ok_ntstatus(Status, STATUS_IMAGE_MACHINE_TYPE_MISMATCH);
763 #endif
764
765 /* Check the header */
766 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
767 ok(*(ULONG*)ImageBase == 0x00905a4d, "Header not ok\n");
768
769 /* Check the data section. Either of these can be present! */
770 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
771 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
772 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
773
774 /* Now modify the data again */
775 *(ULONG*)DataBase = 0xdeadbabe;
776 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xf00dada;
777
778 /* Check the data */
779 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
780 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
781 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
782 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
783 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
784
785 /* Flush the view */
786 ViewSize = 0x1000;
787 Status = NtFlushVirtualMemory(NtCurrentProcess(),
788 &DataBase,
789 &ViewSize,
790 &IoStatusBlock);
791 ok_ntstatus(Status, STATUS_SUCCESS);
792
793 /* Check the data again */
794 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
795 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
796 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
797 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
798
799 /* Restore the original header */
800 *(ULONG*)DataBase = 0x00905a4d;
801 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
802
803 /* Close the image mapping */
804 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
805 NtClose(ImageSectionHandle);
806
807 /* Create an image section again */
808 Status = NtCreateSection(&ImageSectionHandle,
809 SECTION_ALL_ACCESS, // DesiredAccess
810 NULL, // ObjectAttributes
811 NULL, // MaximumSize
812 PAGE_READWRITE, // SectionPageProtection
813 SEC_IMAGE, // AllocationAttributes
814 FileHandle);
815 ok_ntstatus(Status, STATUS_SUCCESS);
816
817 /* Map the image section again */
818 ImageBase = NULL;
819 ViewSize = 0;
820 Status = NtMapViewOfSection(ImageSectionHandle,
821 NtCurrentProcess(),
822 &ImageBase,
823 0,
824 0,
825 NULL,
826 &ViewSize,
827 ViewShare,
828 0,
829 PAGE_READONLY);
830 #ifdef _M_IX86
831 ok_ntstatus(Status, STATUS_IMAGE_NOT_AT_BASE);
832 #else
833 ok_ntstatus(Status, STATUS_IMAGE_MACHINE_TYPE_MISMATCH);
834 #endif
835
836 // This one doesn't always work, needs investigation
837 /* Check the .data section again */
838 //ok(*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0xf00dada,
839 // "Data should be synced: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
840
841 /* Restore the original data */
842 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x12345678;
843
844 /* Close the data mapping */
845 NtUnmapViewOfSection(NtCurrentProcess(), DataBase);
846
847 NtClose(DataSectionHandle);
848
849 /* Try to allocate memory inside the image mapping */
850 DataBase = (PUCHAR)ImageBase + 0x20000;
851 ViewSize = 0x1000;
852 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &DataBase, 0, &ViewSize, MEM_RESERVE, PAGE_NOACCESS);
853 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
854
855 /* Cleanup */
856 NtClose(FileHandle);
857 NtClose(ImageSectionHandle);
858 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
859 }
860
861 void
862 Test_ImageSection2(void)
863 {
864 UNICODE_STRING FileName;
865 NTSTATUS Status;
866 OBJECT_ATTRIBUTES FileObjectAttributes;
867 IO_STATUS_BLOCK IoStatusBlock;
868 HANDLE FileHandle, ImageSectionHandle;
869 PVOID ImageBase, BaseAddress;
870 SIZE_T ViewSize;
871 LARGE_INTEGER MaximumSize, SectionOffset;
872
873 if (!RtlDosPathNameToNtPathName_U(L"testdata\\nvoglv32.dll",
874 &FileName,
875 NULL,
876 NULL))
877 {
878 ok(0, "RtlDosPathNameToNtPathName_U failed\n");
879 return;
880 }
881
882 InitializeObjectAttributes(&FileObjectAttributes,
883 &FileName,
884 0,
885 NULL,
886 NULL);
887
888 Status = NtOpenFile(&FileHandle,
889 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
890 &FileObjectAttributes,
891 &IoStatusBlock,
892 FILE_SHARE_READ,
893 FILE_SYNCHRONOUS_IO_NONALERT);
894 ok_ntstatus(Status, STATUS_SUCCESS);
895 printf("Opened file with handle %p\n", FileHandle);
896
897 /* Create a data section with write access */
898 MaximumSize.QuadPart = 0x20000;
899 Status = NtCreateSection(&ImageSectionHandle,
900 SECTION_ALL_ACCESS, // DesiredAccess
901 NULL, // ObjectAttributes
902 &MaximumSize, // MaximumSize
903 PAGE_READWRITE, // SectionPageProtection
904 SEC_IMAGE, // AllocationAttributes
905 FileHandle);
906 ok_ntstatus(Status, STATUS_SUCCESS);
907
908 printf("Created image section with handle %p\n", ImageSectionHandle);
909 //system("PAUSE");
910
911 /* Map the image section */
912 ImageBase = NULL;
913 ViewSize = 0x0000;
914 SectionOffset.QuadPart = 0x00000;
915 Status = NtMapViewOfSection(ImageSectionHandle,
916 NtCurrentProcess(),
917 &ImageBase,
918 0,
919 0,
920 &SectionOffset,
921 &ViewSize,
922 ViewShare,
923 0,
924 PAGE_READWRITE);
925 ok_ntstatus(Status, STATUS_SUCCESS);
926
927 printf("Mapped image section at %p, value in text section: %lx\n",
928 ImageBase, *((ULONG*)((PCHAR)ImageBase + 0x1196)));
929 system("PAUSE");
930
931 /* Try to allocate a page after the section */
932 BaseAddress = (PUCHAR)ImageBase + 0x10000;
933 ViewSize = 0x1000;
934 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
935 &BaseAddress,
936 0,
937 &ViewSize,
938 MEM_RESERVE | MEM_COMMIT,
939 PAGE_READWRITE);
940 printf("allocation status: %lx\n", Status);
941 system("PAUSE");
942
943 }
944
945 // doesn't work with WoW64!
946 void
947 Test_BasedSection(void)
948 {
949 NTSTATUS Status;
950 HANDLE SectionHandle1, SectionHandle2;
951 LARGE_INTEGER MaximumSize, SectionOffset;
952 PVOID BaseAddress1, BaseAddress2;
953 SIZE_T ViewSize;
954
955 /* Create a based section with SEC_COMMIT */
956 MaximumSize.QuadPart = 0x1000;
957 Status = NtCreateSection(&SectionHandle1,
958 SECTION_ALL_ACCESS,
959 NULL,
960 &MaximumSize,
961 PAGE_READWRITE,
962 SEC_COMMIT | SEC_BASED,
963 NULL);
964 ok_ntstatus(Status, STATUS_SUCCESS);
965
966 /* Map the 1st section */
967 BaseAddress1 = NULL;
968 SectionOffset.QuadPart = 0;
969 ViewSize = 0;
970 Status = NtMapViewOfSection(SectionHandle1,
971 NtCurrentProcess(),
972 &BaseAddress1,
973 0,
974 0,
975 &SectionOffset,
976 &ViewSize,
977 ViewShare,
978 0,
979 PAGE_READWRITE);
980 #if 0 // WOW64?
981 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
982 #else
983 ok_ntstatus(Status, STATUS_SUCCESS);
984 #endif
985
986 /* Create a 2nd based section with SEC_COMMIT */
987 MaximumSize.QuadPart = 0x1000;
988 Status = NtCreateSection(&SectionHandle2,
989 SECTION_ALL_ACCESS,
990 NULL,
991 &MaximumSize,
992 PAGE_READWRITE,
993 SEC_COMMIT | SEC_BASED,
994 NULL);
995 ok_ntstatus(Status, STATUS_SUCCESS);//
996
997 /* Map the 2nd section */
998 BaseAddress2 = NULL;
999 SectionOffset.QuadPart = 0;
1000 ViewSize = 0;
1001 Status = NtMapViewOfSection(SectionHandle2,
1002 NtCurrentProcess(),
1003 &BaseAddress2,
1004 0,
1005 0,
1006 &SectionOffset,
1007 &ViewSize,
1008 ViewShare,
1009 0,
1010 PAGE_READWRITE);
1011 #if 0 // WOW64?
1012 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
1013 #else
1014 ok_ntstatus(Status, STATUS_SUCCESS);
1015 #endif
1016
1017 ok_ntstatus(Status, STATUS_SUCCESS);
1018 ok((ULONG_PTR)BaseAddress2 < (ULONG_PTR)BaseAddress1,
1019 "Invalid addresses: BaseAddress1=%p, BaseAddress2=%p\n", BaseAddress1, BaseAddress2);
1020 ok(((ULONG_PTR)BaseAddress1 - (ULONG_PTR)BaseAddress2) == 0x10000,
1021 "Invalid addresses: BaseAddress1=%p, BaseAddress2=%p\n", BaseAddress1, BaseAddress2);
1022
1023 }
1024
1025 START_TEST(NtMapViewOfSection)
1026 {
1027 Test_PageFileSection();
1028 Test_ImageSection();
1029 Test_BasedSection();
1030 }
1031