[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 NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
261 NtClose(SectionHandle);
262
263 /* Create a page file backed section, but only reserved */
264 MaximumSize.QuadPart = 0x20000;
265 Status = NtCreateSection(&SectionHandle,
266 SECTION_ALL_ACCESS,
267 NULL,
268 &MaximumSize,
269 PAGE_READWRITE,
270 SEC_RESERVE,
271 NULL);
272 ok_ntstatus(Status, STATUS_SUCCESS);
273
274 /* Try to map 1 page, passing MEM_RESERVE */
275 BaseAddress = NULL;
276 SectionOffset.QuadPart = 0;
277 ViewSize = PAGE_SIZE;
278 Status = NtMapViewOfSection(SectionHandle,
279 NtCurrentProcess(),
280 &BaseAddress,
281 0,
282 PAGE_SIZE,
283 &SectionOffset,
284 &ViewSize,
285 ViewShare,
286 MEM_RESERVE,
287 PAGE_READWRITE);
288 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_9);
289
290 /* Try to map 1 page using MEM_COMMIT */
291 BaseAddress = NULL;
292 SectionOffset.QuadPart = 0;
293 ViewSize = PAGE_SIZE;
294 Status = NtMapViewOfSection(SectionHandle,
295 NtCurrentProcess(),
296 &BaseAddress,
297 0,
298 PAGE_SIZE,
299 &SectionOffset,
300 &ViewSize,
301 ViewShare,
302 MEM_COMMIT,
303 PAGE_READWRITE);
304 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_9);
305
306 /* Map 2 pages, but commit 1 */
307 BaseAddress = NULL;
308 SectionOffset.QuadPart = 0;
309 ViewSize = 2 * PAGE_SIZE;
310 Status = NtMapViewOfSection(SectionHandle,
311 NtCurrentProcess(),
312 &BaseAddress,
313 0,
314 PAGE_SIZE,
315 &SectionOffset,
316 &ViewSize,
317 ViewShare,
318 0,
319 PAGE_READWRITE);
320 ok_ntstatus(Status, STATUS_SUCCESS);
321
322 /* We must be able to access the 1st page */
323 Status = STATUS_SUCCESS;
324 _SEH2_TRY
325 {
326 *(PUCHAR)BaseAddress = 1;
327 }
328 _SEH2_EXCEPT(1)
329 {
330 Status = _SEH2_GetExceptionCode();
331 }
332 _SEH2_END;
333 ok_ntstatus(Status, STATUS_SUCCESS);
334
335 /* We must not be able to access the 2nd page */
336 Status = STATUS_SUCCESS;
337 _SEH2_TRY
338 {
339 *((PUCHAR)BaseAddress + PAGE_SIZE) = 1;
340 }
341 _SEH2_EXCEPT(1)
342 {
343 Status = _SEH2_GetExceptionCode();
344 }
345 _SEH2_END;
346 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
347
348 /* Map the 2 pages again into a different memory location */
349 BaseAddress2 = NULL;
350 Status = NtMapViewOfSection(SectionHandle,
351 NtCurrentProcess(),
352 &BaseAddress2,
353 0,
354 0,
355 &SectionOffset,
356 &ViewSize,
357 ViewShare,
358 0,
359 PAGE_READWRITE);
360 ok_ntstatus(Status, STATUS_SUCCESS);
361
362 /* Commit a the 2nd page in the 2nd memory location */
363 BaseAddress2 = (PUCHAR)BaseAddress2 + PAGE_SIZE;
364 ViewSize = PAGE_SIZE;
365 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
366 &BaseAddress2,
367 0,
368 &ViewSize,
369 MEM_COMMIT,
370 PAGE_READONLY);
371 ok_ntstatus(Status, STATUS_SUCCESS);
372
373 /* Try to commit again (the already committed page) */
374 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
375 &BaseAddress2,
376 0,
377 &ViewSize,
378 MEM_COMMIT,
379 PAGE_READONLY);
380 ok_ntstatus(Status, STATUS_SUCCESS);
381
382 /* We must be able to access the memory in the 2nd page of the 1st memory location */
383 Status = STATUS_SUCCESS;
384 _SEH2_TRY
385 {
386 *((PUCHAR)BaseAddress + PAGE_SIZE) = 2;
387 }
388 _SEH2_EXCEPT(1)
389 {
390 Status = _SEH2_GetExceptionCode();
391 }
392 _SEH2_END;
393 ok_ntstatus(Status, STATUS_SUCCESS);
394
395 ok(*(PULONG)BaseAddress2 == 2, "Value in memory was wrong\n");
396
397 /* Close the mapping */
398 NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
399 NtUnmapViewOfSection(NtCurrentProcess(), (PUCHAR)BaseAddress2 - PAGE_SIZE);
400 NtClose(SectionHandle);
401
402 /* Try to create a 512 GB page file backed section with committed pages */
403 MaximumSize.QuadPart = 0x8000000000;
404 Status = NtCreateSection(&SectionHandle,
405 SECTION_ALL_ACCESS,
406 NULL,
407 &MaximumSize,
408 PAGE_READWRITE,
409 SEC_COMMIT,
410 NULL);
411 ok_ntstatus(Status, STATUS_COMMITMENT_LIMIT);
412
413 /* Try to create a huge page file backed section with PAGE_NOACCESS protection */
414 MaximumSize.QuadPart = 0x8000000000;
415 Status = NtCreateSection(&SectionHandle,
416 SECTION_ALL_ACCESS,
417 NULL,
418 &MaximumSize,
419 PAGE_NOACCESS,
420 SEC_COMMIT,
421 NULL);
422 ok_ntstatus(Status, STATUS_INVALID_PAGE_PROTECTION);
423
424 /* Try to create a very huge page file backed section, but only reserved */
425 MaximumSize.QuadPart = 0x80000000000;
426 Status = NtCreateSection(&SectionHandle,
427 SECTION_ALL_ACCESS,
428 NULL,
429 &MaximumSize,
430 PAGE_READWRITE,
431 SEC_RESERVE,
432 NULL);
433 #ifdef _WIN64
434 ok_ntstatus(Status, STATUS_INSUFFICIENT_RESOURCES);
435 #else
436 /* WoW64 returns STATUS_INSUFFICIENT_RESOURCES */
437 ok((Status == STATUS_INSUFFICIENT_RESOURCES) || (Status == STATUS_SECTION_TOO_BIG),
438 "got wrong Status: 0x%lx\n", Status);
439 #endif
440
441 /* Try to create a even huger page file backed section, but only reserved */
442 MaximumSize.QuadPart = 0x800000000000;
443 Status = NtCreateSection(&SectionHandle,
444 SECTION_ALL_ACCESS,
445 NULL,
446 &MaximumSize,
447 PAGE_READWRITE,
448 SEC_RESERVE,
449 NULL);
450 ok_ntstatus(Status, STATUS_SECTION_TOO_BIG);
451
452 /* Create a 8 GB page file backed section, but only reserved */
453 MaximumSize.QuadPart = 0x200000000;
454 Status = NtCreateSection(&SectionHandle,
455 SECTION_ALL_ACCESS,
456 NULL,
457 &MaximumSize,
458 PAGE_READWRITE,
459 SEC_RESERVE,
460 NULL);
461 ok_ntstatus(Status, STATUS_SUCCESS);
462
463 /* Pass a too large region size */
464 BaseAddress = NULL;
465 SectionOffset.QuadPart = 0;
466 ViewSize = MAXULONG_PTR;
467 Status = NtMapViewOfSection(SectionHandle,
468 NtCurrentProcess(),
469 &BaseAddress,
470 0,
471 0,
472 &SectionOffset,
473 &ViewSize,
474 ViewShare,
475 0,
476 PAGE_READWRITE);
477 #ifdef _WIN64
478 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_3);
479 #else
480 /* WoW64 returns STATUS_INVALID_PARAMETER_4 */
481 ok((Status == STATUS_INVALID_PARAMETER_4) || (Status == STATUS_INVALID_PARAMETER_3),
482 "got wrong Status: 0x%lx\n", Status);
483 #endif
484
485 /* Pass 0 region size */
486 BaseAddress = NULL;
487 SectionOffset.QuadPart = 0;
488 ViewSize = 0;
489 Status = NtMapViewOfSection(SectionHandle,
490 NtCurrentProcess(),
491 &BaseAddress,
492 0,
493 0,
494 &SectionOffset,
495 &ViewSize,
496 ViewShare,
497 0,
498 PAGE_READWRITE);
499 #ifdef _WIN64
500 ok_ntstatus(Status, STATUS_SUCCESS);
501 ok(ViewSize == 0x200000000, "wrong ViewSize: 0x%Ix\n", ViewSize);
502 #else
503 /* WoW64 returns STATUS_NO_MEMORY */
504 ok((Status == STATUS_NO_MEMORY) || (Status == STATUS_INVALID_VIEW_SIZE),
505 "got wrong Status: 0x%lx\n", Status);
506 ok(ViewSize == 0, "wrong ViewSize: 0x%Ix\n", ViewSize);
507 #endif
508
509 /* Map with PAGE_NOACCESS */
510 BaseAddress = NULL;
511 SectionOffset.QuadPart = 0;
512 ViewSize = 0x20000000;
513 Status = NtMapViewOfSection(SectionHandle,
514 NtCurrentProcess(),
515 &BaseAddress,
516 0,
517 0,
518 &SectionOffset,
519 &ViewSize,
520 ViewShare,
521 0,
522 PAGE_NOACCESS);
523 ok_ntstatus(Status, STATUS_SUCCESS);
524
525 /* Try to change protection to read/write */
526 ViewSize = 0x1000;
527 OldProtect = -1;
528 BaseAddress2 = BaseAddress;
529 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READWRITE, &OldProtect);
530 ok_ntstatus(Status, STATUS_SECTION_PROTECTION);
531 // Windows 2003 returns bogus
532 //ok(OldProtect == PAGE_READWRITE, "Wrong protection returned: %u\n", OldProtect);
533
534 /* Test read access */
535 Status = STATUS_SUCCESS;
536 _SEH2_TRY
537 {
538 (void)(*(volatile char*)BaseAddress2);
539 }
540 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
541 {
542 Status = _SEH2_GetExceptionCode();
543 }
544 _SEH2_END;
545 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
546
547 /* Try to change protection to read/write */
548 ViewSize = 0x1000;
549 OldProtect = -1;
550 BaseAddress2 = BaseAddress;
551 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READWRITE, &OldProtect);
552 ok_ntstatus(Status, STATUS_SECTION_PROTECTION);
553 #ifdef _WIN64
554 ok(OldProtect == 0, "Wrong protection returned: 0x%lx\n", OldProtect);
555 #else
556 // Windows 2003 returns bogus
557 #endif
558
559 /* Try to change protection to readonly */
560 ViewSize = 0x1000;
561 OldProtect = -1;
562 BaseAddress2 = BaseAddress;
563 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READONLY, &OldProtect);
564 ok_ntstatus(Status, STATUS_SECTION_PROTECTION);
565 #ifdef _WIN64
566 //ok(OldProtect == 0, "Wrong protection returned: 0x%lx\n", OldProtect);
567 #else
568 // Windows 2003 returns bogus
569 #endif
570
571 /* Commit a page */
572 ViewSize = 0x1000;
573 BaseAddress2 = BaseAddress;
574 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READONLY);
575 ok_ntstatus(Status, STATUS_SUCCESS);
576 ok(BaseAddress2 == BaseAddress, "Invalid base address: %p\n", BaseAddress2);
577
578 /* Commit the page again */
579 ViewSize = 0x1000;
580 BaseAddress2 = BaseAddress;
581 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READONLY);
582 ok_ntstatus(Status, STATUS_SUCCESS);
583 ok(BaseAddress2 == BaseAddress, "Invalid base address: %p\n", BaseAddress2);
584
585 /* Test read access */
586 Status = STATUS_SUCCESS;
587 _SEH2_TRY
588 {
589 (void)(*(volatile char*)BaseAddress2);
590 }
591 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
592 {
593 Status = _SEH2_GetExceptionCode();
594 }
595 _SEH2_END;
596 ok_ntstatus(Status, STATUS_SUCCESS);
597
598 /* Test write access */
599 Status = STATUS_SUCCESS;
600 _SEH2_TRY
601 {
602 *(char*)BaseAddress2 = 1;
603 }
604 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
605 {
606 Status = _SEH2_GetExceptionCode();
607 }
608 _SEH2_END;
609 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
610
611 /* Update protection to PAGE_READWRITE */
612 ViewSize = 0x1000;
613 BaseAddress2 = BaseAddress;
614 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READWRITE);
615 ok_ntstatus(Status, STATUS_SUCCESS);
616
617 /* Test write access */
618 Status = STATUS_SUCCESS;
619 _SEH2_TRY
620 {
621 *(char*)BaseAddress2 = 1;
622 }
623 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
624 {
625 Status = _SEH2_GetExceptionCode();
626 }
627 _SEH2_END;
628 ok_ntstatus(Status, STATUS_SUCCESS);
629
630 /* Update protection to PAGE_EXECUTE_READWRITE (1 page) */
631 ViewSize = 0x1000;
632 BaseAddress2 = BaseAddress;
633 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
634 ok_ntstatus(Status, STATUS_SUCCESS);
635
636 }
637
638 void
639 Test_ImageSection(void)
640 {
641 UNICODE_STRING FileName;
642 NTSTATUS Status;
643 OBJECT_ATTRIBUTES FileObjectAttributes;
644 IO_STATUS_BLOCK IoStatusBlock;
645 WCHAR TestDllPath[MAX_PATH];
646 HANDLE FileHandle, DataSectionHandle, ImageSectionHandle;
647 PVOID DataBase, ImageBase;
648 SIZE_T ViewSize;
649
650 GetModuleFileNameW(NULL, TestDllPath, RTL_NUMBER_OF(TestDllPath));
651 wcsrchr(TestDllPath, L'\\')[1] = UNICODE_NULL;
652 StringCbCatW(TestDllPath, sizeof(TestDllPath), L"testdata\\test.dll");
653 if (!RtlDosPathNameToNtPathName_U(TestDllPath,
654 &FileName,
655 NULL,
656 NULL))
657 {
658 ok(0, "RtlDosPathNameToNtPathName_U failed\n");
659 return;
660 }
661
662 InitializeObjectAttributes(&FileObjectAttributes,
663 &FileName,
664 0,
665 NULL,
666 NULL);
667
668 Status = NtOpenFile(&FileHandle,
669 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
670 &FileObjectAttributes,
671 &IoStatusBlock,
672 FILE_SHARE_READ,
673 FILE_SYNCHRONOUS_IO_NONALERT);
674 ok_ntstatus(Status, STATUS_SUCCESS);
675 if (!NT_SUCCESS(Status))
676 {
677 skip("Failed to open file\n");
678 return;
679 }
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 if (!NT_SUCCESS(Status))
691 {
692 skip("Failed to create data section\n");
693 NtClose(FileHandle);
694 return;
695 }
696
697 /* Map the data section as flat mapping */
698 DataBase = NULL;
699 ViewSize = 0;
700 Status = NtMapViewOfSection(DataSectionHandle,
701 NtCurrentProcess(),
702 &DataBase,
703 0,
704 0,
705 NULL,
706 &ViewSize,
707 ViewShare,
708 0,
709 PAGE_READWRITE);
710 ok_ntstatus(Status, STATUS_SUCCESS);
711 //ok(ViewSize == 0x3f95cc48, "ViewSize wrong: 0x%lx\n");
712 if (!NT_SUCCESS(Status))
713 {
714 skip("Failed to map view of data section\n");
715 NtClose(DataSectionHandle);
716 NtClose(FileHandle);
717 return;
718 }
719
720 /* Check the original data */
721 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
722
723 /* Modify the PE header (but do not flush!) */
724 *(ULONG*)DataBase = 0xdeadbabe;
725 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
726
727 /* Modify data in the .data section (but do not flush!) */
728 ok(*(ULONG*)((PUCHAR)DataBase + 0x800) == 0x12345678,
729 "Data in .data section invalid: 0x%lx!\n", *(ULONG*)((PUCHAR)DataBase + 0x800));
730 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x87654321;
731
732 /* Now try to create an image section (should fail) */
733 Status = NtCreateSection(&ImageSectionHandle,
734 SECTION_ALL_ACCESS, // DesiredAccess
735 NULL, // ObjectAttributes
736 NULL, // MaximumSize
737 PAGE_READWRITE, // SectionPageProtection
738 SEC_IMAGE, // AllocationAttributes
739 FileHandle);
740 ok_ntstatus(Status, STATUS_INVALID_IMAGE_NOT_MZ);
741 if (NT_SUCCESS(Status)) NtClose(ImageSectionHandle);
742
743 /* Restore the original header */
744 *(ULONG*)DataBase = 0x00905a4d;
745
746 /* Modify data in the .data section (but do not flush!) */
747 ok_hex(*(ULONG*)((PUCHAR)DataBase + 0x800), 0x87654321);
748 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xdeadbabe;
749
750 /* Try to create an image section again */
751 Status = NtCreateSection(&ImageSectionHandle,
752 SECTION_ALL_ACCESS, // DesiredAccess
753 NULL, // ObjectAttributes
754 NULL, // MaximumSize
755 PAGE_READWRITE, // SectionPageProtection
756 SEC_IMAGE, // AllocationAttributes
757 FileHandle);
758 ok_ntstatus(Status, STATUS_SUCCESS);
759 if (!NT_SUCCESS(Status))
760 {
761 skip("Failed to create image section\n");
762 NtClose(DataSectionHandle);
763 NtClose(FileHandle);
764 return;
765 }
766
767 /* Map the image section */
768 ImageBase = NULL;
769 ViewSize = 0;
770 Status = NtMapViewOfSection(ImageSectionHandle,
771 NtCurrentProcess(),
772 &ImageBase,
773 0, // ZeroBits
774 0, // CommitSize
775 NULL, // SectionOffset
776 &ViewSize,
777 ViewShare,
778 0, // AllocationType
779 PAGE_READONLY);
780 #ifdef _M_IX86
781 ok_ntstatus(Status, STATUS_IMAGE_NOT_AT_BASE);
782 #else
783 ok_ntstatus(Status, STATUS_IMAGE_MACHINE_TYPE_MISMATCH);
784 #endif
785 if (!NT_SUCCESS(Status))
786 {
787 skip("Failed to map view of image section\n");
788 NtClose(ImageSectionHandle);
789 NtClose(DataSectionHandle);
790 NtClose(FileHandle);
791 return;
792 }
793
794 /* Check the header */
795 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
796 ok(*(ULONG*)ImageBase == 0x00905a4d, "Header not ok\n");
797
798 /* Check the data section. Either of these can be present! */
799 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
800 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
801 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
802
803 /* Now modify the data again */
804 *(ULONG*)DataBase = 0xdeadbabe;
805 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xf00dada;
806
807 /* Check the data */
808 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
809 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
810 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
811 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
812 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
813
814 /* Flush the view */
815 ViewSize = 0x1000;
816 Status = NtFlushVirtualMemory(NtCurrentProcess(),
817 &DataBase,
818 &ViewSize,
819 &IoStatusBlock);
820 ok_ntstatus(Status, STATUS_SUCCESS);
821
822 /* Check the data again */
823 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
824 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
825 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
826 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
827
828 /* Restore the original header */
829 *(ULONG*)DataBase = 0x00905a4d;
830 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
831
832 /* Close the image mapping */
833 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
834 NtClose(ImageSectionHandle);
835
836 /* Create an image section again */
837 Status = NtCreateSection(&ImageSectionHandle,
838 SECTION_ALL_ACCESS, // DesiredAccess
839 NULL, // ObjectAttributes
840 NULL, // MaximumSize
841 PAGE_READWRITE, // SectionPageProtection
842 SEC_IMAGE, // AllocationAttributes
843 FileHandle);
844 ok_ntstatus(Status, STATUS_SUCCESS);
845 if (!NT_SUCCESS(Status))
846 {
847 skip("Failed to create image section\n");
848 NtClose(DataSectionHandle);
849 NtClose(FileHandle);
850 return;
851 }
852
853 /* Map the image section again */
854 ImageBase = NULL;
855 ViewSize = 0;
856 Status = NtMapViewOfSection(ImageSectionHandle,
857 NtCurrentProcess(),
858 &ImageBase,
859 0,
860 0,
861 NULL,
862 &ViewSize,
863 ViewShare,
864 0,
865 PAGE_READONLY);
866 #ifdef _M_IX86
867 ok_ntstatus(Status, STATUS_IMAGE_NOT_AT_BASE);
868 #else
869 ok_ntstatus(Status, STATUS_IMAGE_MACHINE_TYPE_MISMATCH);
870 #endif
871 if (!NT_SUCCESS(Status))
872 {
873 skip("Failed to map view of image section\n");
874 NtClose(ImageSectionHandle);
875 NtClose(DataSectionHandle);
876 NtClose(FileHandle);
877 return;
878 }
879
880 // This one doesn't always work, needs investigation
881 /* Check the .data section again */
882 //ok(*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0xf00dada,
883 // "Data should be synced: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
884
885 /* Restore the original data */
886 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x12345678;
887
888 /* Close the data mapping */
889 NtUnmapViewOfSection(NtCurrentProcess(), DataBase);
890
891 NtClose(DataSectionHandle);
892
893 /* Try to allocate memory inside the image mapping */
894 DataBase = (PUCHAR)ImageBase + 0x20000;
895 ViewSize = 0x1000;
896 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &DataBase, 0, &ViewSize, MEM_RESERVE, PAGE_NOACCESS);
897 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
898
899 /* Cleanup */
900 NtClose(FileHandle);
901 NtClose(ImageSectionHandle);
902 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
903 }
904
905 void
906 Test_ImageSection2(void)
907 {
908 UNICODE_STRING FileName;
909 NTSTATUS Status;
910 OBJECT_ATTRIBUTES FileObjectAttributes;
911 IO_STATUS_BLOCK IoStatusBlock;
912 HANDLE FileHandle, ImageSectionHandle;
913 PVOID ImageBase, BaseAddress;
914 SIZE_T ViewSize;
915 LARGE_INTEGER MaximumSize, SectionOffset;
916
917 if (!RtlDosPathNameToNtPathName_U(L"testdata\\nvoglv32.dll",
918 &FileName,
919 NULL,
920 NULL))
921 {
922 ok(0, "RtlDosPathNameToNtPathName_U failed\n");
923 return;
924 }
925
926 InitializeObjectAttributes(&FileObjectAttributes,
927 &FileName,
928 0,
929 NULL,
930 NULL);
931
932 Status = NtOpenFile(&FileHandle,
933 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
934 &FileObjectAttributes,
935 &IoStatusBlock,
936 FILE_SHARE_READ,
937 FILE_SYNCHRONOUS_IO_NONALERT);
938 ok_ntstatus(Status, STATUS_SUCCESS);
939 printf("Opened file with handle %p\n", FileHandle);
940
941 /* Create a data section with write access */
942 MaximumSize.QuadPart = 0x20000;
943 Status = NtCreateSection(&ImageSectionHandle,
944 SECTION_ALL_ACCESS, // DesiredAccess
945 NULL, // ObjectAttributes
946 &MaximumSize, // MaximumSize
947 PAGE_READWRITE, // SectionPageProtection
948 SEC_IMAGE, // AllocationAttributes
949 FileHandle);
950 ok_ntstatus(Status, STATUS_SUCCESS);
951
952 printf("Created image section with handle %p\n", ImageSectionHandle);
953 //system("PAUSE");
954
955 /* Map the image section */
956 ImageBase = NULL;
957 ViewSize = 0x0000;
958 SectionOffset.QuadPart = 0x00000;
959 Status = NtMapViewOfSection(ImageSectionHandle,
960 NtCurrentProcess(),
961 &ImageBase,
962 0,
963 0,
964 &SectionOffset,
965 &ViewSize,
966 ViewShare,
967 0,
968 PAGE_READWRITE);
969 ok_ntstatus(Status, STATUS_SUCCESS);
970
971 printf("Mapped image section at %p, value in text section: %lx\n",
972 ImageBase, *((ULONG*)((PCHAR)ImageBase + 0x1196)));
973 system("PAUSE");
974
975 /* Try to allocate a page after the section */
976 BaseAddress = (PUCHAR)ImageBase + 0x10000;
977 ViewSize = 0x1000;
978 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
979 &BaseAddress,
980 0,
981 &ViewSize,
982 MEM_RESERVE | MEM_COMMIT,
983 PAGE_READWRITE);
984 printf("allocation status: %lx\n", Status);
985 system("PAUSE");
986
987 }
988
989 // doesn't work with WoW64!
990 void
991 Test_BasedSection(void)
992 {
993 NTSTATUS Status;
994 HANDLE SectionHandle1, SectionHandle2;
995 LARGE_INTEGER MaximumSize, SectionOffset;
996 PVOID BaseAddress1, BaseAddress2;
997 SIZE_T ViewSize;
998
999 /* Create a based section with SEC_COMMIT */
1000 MaximumSize.QuadPart = 0x1000;
1001 Status = NtCreateSection(&SectionHandle1,
1002 SECTION_ALL_ACCESS,
1003 NULL,
1004 &MaximumSize,
1005 PAGE_READWRITE,
1006 SEC_COMMIT | SEC_BASED,
1007 NULL);
1008 ok_ntstatus(Status, STATUS_SUCCESS);
1009
1010 /* Map the 1st section */
1011 BaseAddress1 = NULL;
1012 SectionOffset.QuadPart = 0;
1013 ViewSize = 0;
1014 Status = NtMapViewOfSection(SectionHandle1,
1015 NtCurrentProcess(),
1016 &BaseAddress1,
1017 0,
1018 0,
1019 &SectionOffset,
1020 &ViewSize,
1021 ViewShare,
1022 0,
1023 PAGE_READWRITE);
1024 #if 0 // WOW64?
1025 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
1026 #else
1027 ok_ntstatus(Status, STATUS_SUCCESS);
1028 #endif
1029
1030 /* Create a 2nd based section with SEC_COMMIT */
1031 MaximumSize.QuadPart = 0x1000;
1032 Status = NtCreateSection(&SectionHandle2,
1033 SECTION_ALL_ACCESS,
1034 NULL,
1035 &MaximumSize,
1036 PAGE_READWRITE,
1037 SEC_COMMIT | SEC_BASED,
1038 NULL);
1039 ok_ntstatus(Status, STATUS_SUCCESS);//
1040
1041 /* Map the 2nd section */
1042 BaseAddress2 = NULL;
1043 SectionOffset.QuadPart = 0;
1044 ViewSize = 0;
1045 Status = NtMapViewOfSection(SectionHandle2,
1046 NtCurrentProcess(),
1047 &BaseAddress2,
1048 0,
1049 0,
1050 &SectionOffset,
1051 &ViewSize,
1052 ViewShare,
1053 0,
1054 PAGE_READWRITE);
1055 #if 0 // WOW64?
1056 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
1057 #else
1058 ok_ntstatus(Status, STATUS_SUCCESS);
1059 #endif
1060
1061 ok_ntstatus(Status, STATUS_SUCCESS);
1062 ok((ULONG_PTR)BaseAddress2 < (ULONG_PTR)BaseAddress1,
1063 "Invalid addresses: BaseAddress1=%p, BaseAddress2=%p\n", BaseAddress1, BaseAddress2);
1064 ok(((ULONG_PTR)BaseAddress1 - (ULONG_PTR)BaseAddress2) == 0x10000,
1065 "Invalid addresses: BaseAddress1=%p, BaseAddress2=%p\n", BaseAddress1, BaseAddress2);
1066
1067 }
1068
1069 START_TEST(NtMapViewOfSection)
1070 {
1071 Test_PageFileSection();
1072 Test_ImageSection();
1073 Test_BasedSection();
1074 }