[KMTESTS:MM]
[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 * Thomas Faber
7 */
8
9 #include <apitest.h>
10 #include <strsafe.h>
11 #define WIN32_NO_STATUS
12 #include <ndk/ntndk.h>
13
14 void
15 Test_PageFileSection(void)
16 {
17 NTSTATUS Status;
18 HANDLE SectionHandle;
19 LARGE_INTEGER MaximumSize, SectionOffset;
20 PVOID BaseAddress, BaseAddress2;
21 SIZE_T ViewSize;
22 ULONG OldProtect;
23
24 /* Create a page file backed section with SEC_COMMIT */
25 MaximumSize.QuadPart = 0x20000;
26 Status = NtCreateSection(&SectionHandle,
27 SECTION_ALL_ACCESS,
28 NULL,
29 &MaximumSize,
30 PAGE_READWRITE,
31 SEC_COMMIT,
32 NULL);
33 ok_ntstatus(Status, STATUS_SUCCESS);
34 if (!NT_SUCCESS(Status))
35 return;
36
37 /* Try to map a page at an address that is not 64k aligned */
38 BaseAddress = (PVOID)0x30001000;
39 SectionOffset.QuadPart = 0;
40 ViewSize = 0x1000;
41 Status = NtMapViewOfSection(SectionHandle,
42 NtCurrentProcess(),
43 &BaseAddress,
44 0,
45 0,
46 &SectionOffset,
47 &ViewSize,
48 ViewShare,
49 0,
50 PAGE_READWRITE);
51 ok_ntstatus(Status, STATUS_MAPPED_ALIGNMENT);
52
53 /* Try to map a page with execute rights */
54 BaseAddress = (PVOID)0x30000000;
55 SectionOffset.QuadPart = 0;
56 ViewSize = 0x1000;
57 Status = NtMapViewOfSection(SectionHandle,
58 NtCurrentProcess(),
59 &BaseAddress,
60 0,
61 0,
62 &SectionOffset,
63 &ViewSize,
64 ViewShare,
65 0,
66 PAGE_EXECUTE_READWRITE);
67 ok_ntstatus(Status, STATUS_SECTION_PROTECTION);
68
69 /* Try to map 2 pages with MEM_COMMIT */
70 BaseAddress = (PVOID)0x30000000;
71 SectionOffset.QuadPart = 0;
72 ViewSize = 0x2000;
73 Status = NtMapViewOfSection(SectionHandle,
74 NtCurrentProcess(),
75 &BaseAddress,
76 0,
77 PAGE_SIZE,
78 &SectionOffset,
79 &ViewSize,
80 ViewShare,
81 MEM_COMMIT,
82 PAGE_READWRITE);
83 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_9);
84
85 /* Try to map 1 page, with free base address and zero bits compatible with 64k granularity */
86 BaseAddress = NULL;
87 SectionOffset.QuadPart = 0;
88 ViewSize = 0x1000;
89 Status = NtMapViewOfSection(SectionHandle,
90 NtCurrentProcess(),
91 &BaseAddress,
92 10,
93 0,
94 &SectionOffset,
95 &ViewSize,
96 ViewShare,
97 0,
98 PAGE_READWRITE);
99 ok_ntstatus(Status, STATUS_SUCCESS);
100 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
101 ok_ntstatus(Status, STATUS_SUCCESS);
102
103 {
104 ULONG_PTR gran = 64 * 1024;
105 ULONG_PTR ZeroBits = 11;
106
107 ok_hex(gran, 0x10000);
108 gran <<= ZeroBits;
109 ok_hex(gran, 0x8000000);
110 gran >>= ZeroBits;
111 ok_hex(gran, 0x10000);
112
113 ok_hex((gran << ZeroBits) >> ZeroBits, gran);
114
115 }
116
117 /* Try to map 1 page, with free base address and zero bits incompatible with 64k granularity */
118 BaseAddress = NULL;
119 SectionOffset.QuadPart = 0;
120 ViewSize = 0x1000;
121 Status = NtMapViewOfSection(SectionHandle,
122 NtCurrentProcess(),
123 &BaseAddress,
124 11,
125 0,
126 &SectionOffset,
127 &ViewSize,
128 ViewShare,
129 0,
130 PAGE_READWRITE);
131 ok_ntstatus(Status, STATUS_NO_MEMORY);
132
133 /* Try to map 1 page, with base address and zero bits being compatible */
134 BaseAddress = (PVOID)0x30000000;
135 SectionOffset.QuadPart = 0;
136 ViewSize = 0x1000;
137 Status = NtMapViewOfSection(SectionHandle,
138 NtCurrentProcess(),
139 &BaseAddress,
140 2,
141 0,
142 &SectionOffset,
143 &ViewSize,
144 ViewShare,
145 0,
146 PAGE_READWRITE);
147 ok_ntstatus(Status, STATUS_SUCCESS);
148 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
149 ok_ntstatus(Status, STATUS_SUCCESS);
150
151 /* Try to map 1 page, with base address and zero bits being incompatible */
152 BaseAddress = (PVOID)0x30000000;
153 SectionOffset.QuadPart = 0;
154 ViewSize = 0x1000;
155 Status = NtMapViewOfSection(SectionHandle,
156 NtCurrentProcess(),
157 &BaseAddress,
158 3,
159 0,
160 &SectionOffset,
161 &ViewSize,
162 ViewShare,
163 0,
164 PAGE_READWRITE);
165 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_4);
166
167 /* Map 2 pages, without MEM_COMMIT */
168 BaseAddress = (PVOID)0x30000000;
169 SectionOffset.QuadPart = 0;
170 ViewSize = 0x2000;
171 Status = NtMapViewOfSection(SectionHandle,
172 NtCurrentProcess(),
173 &BaseAddress,
174 0,
175 0,
176 &SectionOffset,
177 &ViewSize,
178 ViewShare,
179 0,
180 PAGE_READWRITE);
181 ok_ntstatus(Status, STATUS_SUCCESS);
182
183 /* We must be able to access the memory */
184 _SEH2_TRY
185 {
186 *(PULONG)BaseAddress = 1;
187 }
188 _SEH2_EXCEPT(1)
189 {
190 ok(FALSE, "Got an exception\n");
191 }
192 _SEH2_END;
193
194 /* Commit a page in the section */
195 BaseAddress = (PVOID)0x30000000;
196 ViewSize = 0x1000;
197 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
198 &BaseAddress,
199 0,
200 &ViewSize,
201 MEM_COMMIT,
202 PAGE_READWRITE);
203 ok_ntstatus(Status, STATUS_SUCCESS);
204
205 /* Try to decommit a page in the section */
206 Status = NtFreeVirtualMemory(NtCurrentProcess(),
207 &BaseAddress,
208 &ViewSize,
209 MEM_DECOMMIT);
210 ok_ntstatus(Status, STATUS_UNABLE_TO_DELETE_SECTION);
211
212 /* Try to commit a range larger than the section */
213 BaseAddress = (PVOID)0x30000000;
214 ViewSize = 0x3000;
215 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
216 &BaseAddress,
217 0,
218 &ViewSize,
219 MEM_COMMIT,
220 PAGE_READWRITE);
221 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
222
223 /* Try to commit a page after the section */
224 BaseAddress = (PVOID)0x30002000;
225 ViewSize = 0x1000;
226 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
227 &BaseAddress,
228 0,
229 &ViewSize,
230 MEM_COMMIT,
231 PAGE_READWRITE);
232 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
233
234 /* Try to allocate a page after the section */
235 BaseAddress = (PVOID)0x30002000;
236 ViewSize = 0x1000;
237 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
238 &BaseAddress,
239 0,
240 &ViewSize,
241 MEM_RESERVE | MEM_COMMIT,
242 PAGE_READWRITE);
243 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
244
245 /* Need to go to next 64k boundary */
246 BaseAddress = (PVOID)0x30010000;
247 ViewSize = 0x1000;
248 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
249 &BaseAddress,
250 0,
251 &ViewSize,
252 MEM_RESERVE | MEM_COMMIT,
253 PAGE_READWRITE);
254 ok_ntstatus(Status, STATUS_SUCCESS);
255 if (!NT_SUCCESS(Status))
256 return;
257
258 /* Free the allocation */
259 BaseAddress = (PVOID)0x30010000;
260 ViewSize = 0x1000;
261 Status = NtFreeVirtualMemory(NtCurrentProcess(),
262 &BaseAddress,
263 &ViewSize,
264 MEM_RELEASE);
265 ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed with Status %lx\n", Status);
266
267 /* Try to release the section mapping with NtFreeVirtualMemory */
268 BaseAddress = (PVOID)0x30000000;
269 ViewSize = 0x1000;
270 Status = NtFreeVirtualMemory(NtCurrentProcess(),
271 &BaseAddress,
272 &ViewSize,
273 MEM_RELEASE);
274 ok_ntstatus(Status, STATUS_UNABLE_TO_DELETE_SECTION);
275
276 /* Commit a page in the section */
277 BaseAddress = (PVOID)0x30001000;
278 ViewSize = 0x1000;
279 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
280 &BaseAddress,
281 0,
282 &ViewSize,
283 MEM_COMMIT,
284 PAGE_READWRITE);
285 ok_ntstatus(Status, STATUS_SUCCESS);
286
287 /* Try to decommit the page */
288 BaseAddress = (PVOID)0x30001000;
289 ViewSize = 0x1000;
290 Status = NtFreeVirtualMemory(NtCurrentProcess(),
291 &BaseAddress,
292 &ViewSize,
293 MEM_DECOMMIT);
294 ok_ntstatus(Status, STATUS_UNABLE_TO_DELETE_SECTION);
295
296 BaseAddress = UlongToPtr(0x40000000);
297 SectionOffset.QuadPart = 0;
298 ViewSize = 0x1000;
299 Status = NtMapViewOfSection(SectionHandle,
300 NtCurrentProcess(),
301 &BaseAddress,
302 0,
303 0,
304 &SectionOffset,
305 &ViewSize,
306 ViewShare,
307 0,
308 PAGE_READWRITE);
309 ok_ntstatus(Status, STATUS_SUCCESS);
310 if (!NT_SUCCESS(Status))
311 return;
312
313 ok(BaseAddress == UlongToPtr(0x40000000), "Invalid BaseAddress: %p\n", BaseAddress);
314
315 BaseAddress = (PVOID)0x40080000;
316 SectionOffset.QuadPart = 0x10000;
317 ViewSize = 0x1000;
318 Status = NtMapViewOfSection(SectionHandle,
319 NtCurrentProcess(),
320 &BaseAddress,
321 0,
322 0,
323 &SectionOffset,
324 &ViewSize,
325 ViewShare,
326 0,
327 PAGE_READWRITE);
328 ok_ntstatus(Status, STATUS_SUCCESS);
329
330 ok(BaseAddress == (PVOID)0x40080000, "Invalid BaseAddress: %p\n", BaseAddress);
331
332 /* Commit a page in the section */
333 BaseAddress = (PVOID)0x40000000;
334 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
335 &BaseAddress,
336 0,
337 &ViewSize,
338 MEM_COMMIT,
339 PAGE_READWRITE);
340 ok_ntstatus(Status, STATUS_SUCCESS);
341
342 /* Close the mapping */
343 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
344 ok_ntstatus(Status, STATUS_SUCCESS);
345 BaseAddress = (PVOID)0x30000000;
346 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
347 ok_ntstatus(Status, STATUS_SUCCESS);
348 Status = NtClose(SectionHandle);
349 ok_ntstatus(Status, STATUS_SUCCESS);
350
351 /* Create a page file backed section, but only reserved */
352 MaximumSize.QuadPart = 0x20000;
353 Status = NtCreateSection(&SectionHandle,
354 SECTION_ALL_ACCESS,
355 NULL,
356 &MaximumSize,
357 PAGE_READWRITE,
358 SEC_RESERVE,
359 NULL);
360 ok_ntstatus(Status, STATUS_SUCCESS);
361
362 /* Try to map 1 page, passing MEM_RESERVE */
363 BaseAddress = NULL;
364 SectionOffset.QuadPart = 0;
365 ViewSize = PAGE_SIZE;
366 Status = NtMapViewOfSection(SectionHandle,
367 NtCurrentProcess(),
368 &BaseAddress,
369 0,
370 PAGE_SIZE,
371 &SectionOffset,
372 &ViewSize,
373 ViewShare,
374 MEM_RESERVE,
375 PAGE_READWRITE);
376 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_9);
377
378 /* Try to map 1 page using MEM_COMMIT */
379 BaseAddress = NULL;
380 SectionOffset.QuadPart = 0;
381 ViewSize = PAGE_SIZE;
382 Status = NtMapViewOfSection(SectionHandle,
383 NtCurrentProcess(),
384 &BaseAddress,
385 0,
386 PAGE_SIZE,
387 &SectionOffset,
388 &ViewSize,
389 ViewShare,
390 MEM_COMMIT,
391 PAGE_READWRITE);
392 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_9);
393
394 /* Map 2 pages, but commit 1 */
395 BaseAddress = NULL;
396 SectionOffset.QuadPart = 0;
397 ViewSize = 2 * PAGE_SIZE;
398 Status = NtMapViewOfSection(SectionHandle,
399 NtCurrentProcess(),
400 &BaseAddress,
401 0,
402 PAGE_SIZE,
403 &SectionOffset,
404 &ViewSize,
405 ViewShare,
406 0,
407 PAGE_READWRITE);
408 ok_ntstatus(Status, STATUS_SUCCESS);
409
410 /* We must be able to access the 1st page */
411 Status = STATUS_SUCCESS;
412 _SEH2_TRY
413 {
414 *(PUCHAR)BaseAddress = 1;
415 }
416 _SEH2_EXCEPT(1)
417 {
418 Status = _SEH2_GetExceptionCode();
419 }
420 _SEH2_END;
421 ok_ntstatus(Status, STATUS_SUCCESS);
422
423 /* We must not be able to access the 2nd page */
424 Status = STATUS_SUCCESS;
425 _SEH2_TRY
426 {
427 *((PUCHAR)BaseAddress + PAGE_SIZE) = 1;
428 }
429 _SEH2_EXCEPT(1)
430 {
431 Status = _SEH2_GetExceptionCode();
432 }
433 _SEH2_END;
434 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
435
436 /* Map the 2 pages again into a different memory location */
437 BaseAddress2 = NULL;
438 Status = NtMapViewOfSection(SectionHandle,
439 NtCurrentProcess(),
440 &BaseAddress2,
441 0,
442 0,
443 &SectionOffset,
444 &ViewSize,
445 ViewShare,
446 0,
447 PAGE_READWRITE);
448 ok_ntstatus(Status, STATUS_SUCCESS);
449
450 /* Commit a the 2nd page in the 2nd memory location */
451 BaseAddress2 = (PUCHAR)BaseAddress2 + PAGE_SIZE;
452 ViewSize = PAGE_SIZE;
453 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
454 &BaseAddress2,
455 0,
456 &ViewSize,
457 MEM_COMMIT,
458 PAGE_READONLY);
459 ok_ntstatus(Status, STATUS_SUCCESS);
460
461 /* Try to commit again (the already committed page) */
462 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
463 &BaseAddress2,
464 0,
465 &ViewSize,
466 MEM_COMMIT,
467 PAGE_READONLY);
468 ok_ntstatus(Status, STATUS_SUCCESS);
469
470 /* We must be able to access the memory in the 2nd page of the 1st memory location */
471 Status = STATUS_SUCCESS;
472 _SEH2_TRY
473 {
474 *((PUCHAR)BaseAddress + PAGE_SIZE) = 2;
475 }
476 _SEH2_EXCEPT(1)
477 {
478 Status = _SEH2_GetExceptionCode();
479 }
480 _SEH2_END;
481 ok_ntstatus(Status, STATUS_SUCCESS);
482
483 ok(*(PULONG)BaseAddress2 == 2, "Value in memory was wrong\n");
484
485 /* Close the mapping */
486 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
487 ok_ntstatus(Status, STATUS_SUCCESS);
488 Status = NtUnmapViewOfSection(NtCurrentProcess(), (PUCHAR)BaseAddress2 - PAGE_SIZE);
489 ok_ntstatus(Status, STATUS_SUCCESS);
490 Status = NtClose(SectionHandle);
491 ok_ntstatus(Status, STATUS_SUCCESS);
492
493 /* Try to create a 512 GB page file backed section with committed pages */
494 MaximumSize.QuadPart = 0x8000000000;
495 Status = NtCreateSection(&SectionHandle,
496 SECTION_ALL_ACCESS,
497 NULL,
498 &MaximumSize,
499 PAGE_READWRITE,
500 SEC_COMMIT,
501 NULL);
502 ok_ntstatus(Status, STATUS_COMMITMENT_LIMIT);
503
504 /* Try to create a huge page file backed section with PAGE_NOACCESS protection */
505 MaximumSize.QuadPart = 0x8000000000;
506 Status = NtCreateSection(&SectionHandle,
507 SECTION_ALL_ACCESS,
508 NULL,
509 &MaximumSize,
510 PAGE_NOACCESS,
511 SEC_COMMIT,
512 NULL);
513 ok_ntstatus(Status, STATUS_INVALID_PAGE_PROTECTION);
514
515 /* Try to create a very huge page file backed section, but only reserved */
516 MaximumSize.QuadPart = 0x80000000000;
517 Status = NtCreateSection(&SectionHandle,
518 SECTION_ALL_ACCESS,
519 NULL,
520 &MaximumSize,
521 PAGE_READWRITE,
522 SEC_RESERVE,
523 NULL);
524 #ifdef _WIN64
525 ok_ntstatus(Status, STATUS_INSUFFICIENT_RESOURCES);
526 #else
527 /* WoW64 returns STATUS_INSUFFICIENT_RESOURCES */
528 ok((Status == STATUS_INSUFFICIENT_RESOURCES) || (Status == STATUS_SECTION_TOO_BIG),
529 "got wrong Status: 0x%lx\n", Status);
530 #endif
531
532 /* Try to create a even huger page file backed section, but only reserved */
533 MaximumSize.QuadPart = 0x800000000000;
534 Status = NtCreateSection(&SectionHandle,
535 SECTION_ALL_ACCESS,
536 NULL,
537 &MaximumSize,
538 PAGE_READWRITE,
539 SEC_RESERVE,
540 NULL);
541 ok_ntstatus(Status, STATUS_SECTION_TOO_BIG);
542
543 /* Create a 8 GB page file backed section, but only reserved */
544 MaximumSize.QuadPart = 0x200000000;
545 Status = NtCreateSection(&SectionHandle,
546 SECTION_ALL_ACCESS,
547 NULL,
548 &MaximumSize,
549 PAGE_READWRITE,
550 SEC_RESERVE,
551 NULL);
552 ok_ntstatus(Status, STATUS_SUCCESS);
553
554 /* Pass a too large region size */
555 BaseAddress = NULL;
556 SectionOffset.QuadPart = 0;
557 ViewSize = MAXULONG_PTR;
558 Status = NtMapViewOfSection(SectionHandle,
559 NtCurrentProcess(),
560 &BaseAddress,
561 0,
562 0,
563 &SectionOffset,
564 &ViewSize,
565 ViewShare,
566 0,
567 PAGE_READWRITE);
568 #ifdef _WIN64
569 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_3);
570 #else
571 /* WoW64 returns STATUS_INVALID_PARAMETER_4 */
572 ok((Status == STATUS_INVALID_PARAMETER_4) || (Status == STATUS_INVALID_PARAMETER_3),
573 "got wrong Status: 0x%lx\n", Status);
574 #endif
575
576 /* Pass 0 region size */
577 BaseAddress = NULL;
578 SectionOffset.QuadPart = 0;
579 ViewSize = 0;
580 Status = NtMapViewOfSection(SectionHandle,
581 NtCurrentProcess(),
582 &BaseAddress,
583 0,
584 0,
585 &SectionOffset,
586 &ViewSize,
587 ViewShare,
588 0,
589 PAGE_READWRITE);
590 #ifdef _WIN64
591 ok_ntstatus(Status, STATUS_SUCCESS);
592 ok(ViewSize == 0x200000000, "wrong ViewSize: 0x%Ix\n", ViewSize);
593 #else
594 /* WoW64 returns STATUS_NO_MEMORY */
595 ok((Status == STATUS_NO_MEMORY) || (Status == STATUS_INVALID_VIEW_SIZE),
596 "got wrong Status: 0x%lx\n", Status);
597 ok(ViewSize == 0, "wrong ViewSize: 0x%Ix\n", ViewSize);
598 #endif
599
600 /* Map with PAGE_NOACCESS */
601 BaseAddress = NULL;
602 SectionOffset.QuadPart = 0;
603 ViewSize = 0x20000000;
604 Status = NtMapViewOfSection(SectionHandle,
605 NtCurrentProcess(),
606 &BaseAddress,
607 0,
608 0,
609 &SectionOffset,
610 &ViewSize,
611 ViewShare,
612 0,
613 PAGE_NOACCESS);
614 ok_ntstatus(Status, STATUS_SUCCESS);
615
616 /* Try to change protection to read/write */
617 ViewSize = 0x1000;
618 OldProtect = -1;
619 BaseAddress2 = BaseAddress;
620 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READWRITE, &OldProtect);
621 ok_ntstatus(Status, STATUS_SECTION_PROTECTION);
622 // Windows 2003 returns bogus
623 //ok(OldProtect == PAGE_READWRITE, "Wrong protection returned: %u\n", OldProtect);
624
625 /* Test read access */
626 Status = STATUS_SUCCESS;
627 _SEH2_TRY
628 {
629 (void)(*(volatile char*)BaseAddress2);
630 }
631 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
632 {
633 Status = _SEH2_GetExceptionCode();
634 }
635 _SEH2_END;
636 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
637
638 /* Try to change protection to read/write */
639 ViewSize = 0x1000;
640 OldProtect = -1;
641 BaseAddress2 = BaseAddress;
642 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READWRITE, &OldProtect);
643 ok_ntstatus(Status, STATUS_SECTION_PROTECTION);
644 #ifdef _WIN64
645 ok(OldProtect == 0, "Wrong protection returned: 0x%lx\n", OldProtect);
646 #else
647 // Windows 2003 returns bogus
648 #endif
649
650 /* Try to change protection to readonly */
651 ViewSize = 0x1000;
652 OldProtect = -1;
653 BaseAddress2 = BaseAddress;
654 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READONLY, &OldProtect);
655 ok_ntstatus(Status, STATUS_SECTION_PROTECTION);
656 #ifdef _WIN64
657 //ok(OldProtect == 0, "Wrong protection returned: 0x%lx\n", OldProtect);
658 #else
659 // Windows 2003 returns bogus
660 #endif
661
662 /* Commit a page */
663 ViewSize = 0x1000;
664 BaseAddress2 = BaseAddress;
665 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READONLY);
666 ok_ntstatus(Status, STATUS_SUCCESS);
667 ok(BaseAddress2 == BaseAddress, "Invalid base address: %p\n", BaseAddress2);
668
669 /* Commit the page again */
670 ViewSize = 0x1000;
671 BaseAddress2 = BaseAddress;
672 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READONLY);
673 ok_ntstatus(Status, STATUS_SUCCESS);
674 ok(BaseAddress2 == BaseAddress, "Invalid base address: %p\n", BaseAddress2);
675
676 /* Test read access */
677 Status = STATUS_SUCCESS;
678 _SEH2_TRY
679 {
680 (void)(*(volatile char*)BaseAddress2);
681 }
682 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
683 {
684 Status = _SEH2_GetExceptionCode();
685 }
686 _SEH2_END;
687 ok_ntstatus(Status, STATUS_SUCCESS);
688
689 /* Test write access */
690 Status = STATUS_SUCCESS;
691 _SEH2_TRY
692 {
693 *(char*)BaseAddress2 = 1;
694 }
695 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
696 {
697 Status = _SEH2_GetExceptionCode();
698 }
699 _SEH2_END;
700 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
701
702 /* Update protection to PAGE_READWRITE */
703 ViewSize = 0x1000;
704 BaseAddress2 = BaseAddress;
705 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READWRITE);
706 ok_ntstatus(Status, STATUS_SUCCESS);
707
708 /* Test write access */
709 Status = STATUS_SUCCESS;
710 _SEH2_TRY
711 {
712 *(char*)BaseAddress2 = 1;
713 }
714 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
715 {
716 Status = _SEH2_GetExceptionCode();
717 }
718 _SEH2_END;
719 ok_ntstatus(Status, STATUS_SUCCESS);
720
721 /* Update protection to PAGE_EXECUTE_READWRITE (1 page) */
722 ViewSize = 0x1000;
723 BaseAddress2 = BaseAddress;
724 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
725 ok_ntstatus(Status, STATUS_SUCCESS);
726
727 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
728 ok_ntstatus(Status, STATUS_SUCCESS);
729 Status = NtClose(SectionHandle);
730 ok_ntstatus(Status, STATUS_SUCCESS);
731 }
732
733 void
734 Test_ImageSection(void)
735 {
736 UNICODE_STRING FileName;
737 NTSTATUS Status;
738 OBJECT_ATTRIBUTES FileObjectAttributes;
739 IO_STATUS_BLOCK IoStatusBlock;
740 WCHAR TestDllPath[MAX_PATH];
741 HANDLE FileHandle, DataSectionHandle, ImageSectionHandle;
742 PVOID DataBase, ImageBase;
743 SIZE_T ViewSize;
744
745 GetModuleFileNameW(NULL, TestDllPath, RTL_NUMBER_OF(TestDllPath));
746 wcsrchr(TestDllPath, L'\\')[1] = UNICODE_NULL;
747 StringCbCatW(TestDllPath, sizeof(TestDllPath), L"testdata\\test.dll");
748 if (!RtlDosPathNameToNtPathName_U(TestDllPath,
749 &FileName,
750 NULL,
751 NULL))
752 {
753 ok(0, "RtlDosPathNameToNtPathName_U failed\n");
754 return;
755 }
756
757 InitializeObjectAttributes(&FileObjectAttributes,
758 &FileName,
759 0,
760 NULL,
761 NULL);
762
763 Status = NtOpenFile(&FileHandle,
764 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
765 &FileObjectAttributes,
766 &IoStatusBlock,
767 FILE_SHARE_READ,
768 FILE_SYNCHRONOUS_IO_NONALERT);
769 ok_ntstatus(Status, STATUS_SUCCESS);
770 if (!NT_SUCCESS(Status))
771 {
772 skip("Failed to open file\n");
773 return;
774 }
775
776 /* Create a data section with write access */
777 Status = NtCreateSection(&DataSectionHandle,
778 SECTION_ALL_ACCESS, // DesiredAccess
779 NULL, // ObjectAttributes
780 NULL, // MaximumSize
781 PAGE_READWRITE, // SectionPageProtection
782 SEC_COMMIT, // AllocationAttributes
783 FileHandle);
784 ok_ntstatus(Status, STATUS_SUCCESS);
785 if (!NT_SUCCESS(Status))
786 {
787 skip("Failed to create data section\n");
788 NtClose(FileHandle);
789 return;
790 }
791
792 /* Map the data section as flat mapping */
793 DataBase = NULL;
794 ViewSize = 0;
795 Status = NtMapViewOfSection(DataSectionHandle,
796 NtCurrentProcess(),
797 &DataBase,
798 0,
799 0,
800 NULL,
801 &ViewSize,
802 ViewShare,
803 0,
804 PAGE_READWRITE);
805 ok_ntstatus(Status, STATUS_SUCCESS);
806 //ok(ViewSize == 0x3f95cc48, "ViewSize wrong: 0x%lx\n");
807 if (!NT_SUCCESS(Status))
808 {
809 skip("Failed to map view of data section\n");
810 NtClose(DataSectionHandle);
811 NtClose(FileHandle);
812 return;
813 }
814
815 /* Check the original data */
816 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
817
818 /* Modify the PE header (but do not flush!) */
819 *(ULONG*)DataBase = 0xdeadbabe;
820 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
821
822 /* Modify data in the .data section (but do not flush!) */
823 ok(*(ULONG*)((PUCHAR)DataBase + 0x800) == 0x12345678,
824 "Data in .data section invalid: 0x%lx!\n", *(ULONG*)((PUCHAR)DataBase + 0x800));
825 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x87654321;
826
827 /* Now try to create an image section (should fail) */
828 Status = NtCreateSection(&ImageSectionHandle,
829 SECTION_ALL_ACCESS, // DesiredAccess
830 NULL, // ObjectAttributes
831 NULL, // MaximumSize
832 PAGE_READWRITE, // SectionPageProtection
833 SEC_IMAGE, // AllocationAttributes
834 FileHandle);
835 ok_ntstatus(Status, STATUS_INVALID_IMAGE_NOT_MZ);
836 if (NT_SUCCESS(Status)) NtClose(ImageSectionHandle);
837
838 /* Restore the original header */
839 *(ULONG*)DataBase = 0x00905a4d;
840
841 /* Modify data in the .data section (but do not flush!) */
842 ok_hex(*(ULONG*)((PUCHAR)DataBase + 0x800), 0x87654321);
843 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xdeadbabe;
844
845 /* Try to create an image section again */
846 Status = NtCreateSection(&ImageSectionHandle,
847 SECTION_ALL_ACCESS, // DesiredAccess
848 NULL, // ObjectAttributes
849 NULL, // MaximumSize
850 PAGE_READWRITE, // SectionPageProtection
851 SEC_IMAGE, // AllocationAttributes
852 FileHandle);
853 ok_ntstatus(Status, STATUS_SUCCESS);
854 if (!NT_SUCCESS(Status))
855 {
856 skip("Failed to create image section\n");
857 NtClose(DataSectionHandle);
858 NtClose(FileHandle);
859 return;
860 }
861
862 /* Map the image section */
863 ImageBase = NULL;
864 ViewSize = 0;
865 Status = NtMapViewOfSection(ImageSectionHandle,
866 NtCurrentProcess(),
867 &ImageBase,
868 0, // ZeroBits
869 0, // CommitSize
870 NULL, // SectionOffset
871 &ViewSize,
872 ViewShare,
873 0, // AllocationType
874 PAGE_READONLY);
875 #ifdef _M_IX86
876 ok_ntstatus(Status, STATUS_SUCCESS);
877 #else
878 ok_ntstatus(Status, STATUS_IMAGE_MACHINE_TYPE_MISMATCH);
879 #endif
880 if (!NT_SUCCESS(Status))
881 {
882 skip("Failed to map view of image section\n");
883 NtClose(ImageSectionHandle);
884 NtClose(DataSectionHandle);
885 NtClose(FileHandle);
886 return;
887 }
888
889 /* Check the header */
890 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
891 ok(*(ULONG*)ImageBase == 0x00905a4d, "Header not ok\n");
892
893 /* Check the data section. Either of these can be present! */
894 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
895 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
896 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
897
898 /* Now modify the data again */
899 *(ULONG*)DataBase = 0xdeadbabe;
900 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xf00dada;
901
902 /* Check the data */
903 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
904 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
905 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
906 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
907 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
908
909 /* Flush the view */
910 ViewSize = 0x1000;
911 Status = NtFlushVirtualMemory(NtCurrentProcess(),
912 &DataBase,
913 &ViewSize,
914 &IoStatusBlock);
915 ok_ntstatus(Status, STATUS_SUCCESS);
916
917 /* Check the data again */
918 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
919 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
920 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
921 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
922
923 /* Restore the original header */
924 *(ULONG*)DataBase = 0x00905a4d;
925 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
926
927 /* Close the image mapping */
928 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
929 NtClose(ImageSectionHandle);
930
931 /* Create an image section again */
932 Status = NtCreateSection(&ImageSectionHandle,
933 SECTION_ALL_ACCESS, // DesiredAccess
934 NULL, // ObjectAttributes
935 NULL, // MaximumSize
936 PAGE_READWRITE, // SectionPageProtection
937 SEC_IMAGE, // AllocationAttributes
938 FileHandle);
939 ok_ntstatus(Status, STATUS_SUCCESS);
940 if (!NT_SUCCESS(Status))
941 {
942 skip("Failed to create image section\n");
943 NtClose(DataSectionHandle);
944 NtClose(FileHandle);
945 return;
946 }
947
948 /* Map the image section again */
949 ImageBase = NULL;
950 ViewSize = 0;
951 Status = NtMapViewOfSection(ImageSectionHandle,
952 NtCurrentProcess(),
953 &ImageBase,
954 0,
955 0,
956 NULL,
957 &ViewSize,
958 ViewShare,
959 0,
960 PAGE_READONLY);
961 #ifdef _M_IX86
962 ok_ntstatus(Status, STATUS_SUCCESS);
963 #else
964 ok_ntstatus(Status, STATUS_IMAGE_MACHINE_TYPE_MISMATCH);
965 #endif
966 if (!NT_SUCCESS(Status))
967 {
968 skip("Failed to map view of image section\n");
969 NtClose(ImageSectionHandle);
970 NtClose(DataSectionHandle);
971 NtClose(FileHandle);
972 return;
973 }
974
975 // This one doesn't always work, needs investigation
976 /* Check the .data section again */
977 //ok(*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0xf00dada,
978 // "Data should be synced: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
979
980 /* Restore the original data */
981 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x12345678;
982
983 /* Close the data mapping */
984 NtUnmapViewOfSection(NtCurrentProcess(), DataBase);
985
986 NtClose(DataSectionHandle);
987
988 /* Try to allocate memory inside the image mapping */
989 DataBase = (PUCHAR)ImageBase + 0x20000;
990 ViewSize = 0x1000;
991 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &DataBase, 0, &ViewSize, MEM_RESERVE, PAGE_NOACCESS);
992 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
993
994 /* Cleanup */
995 NtClose(FileHandle);
996 NtClose(ImageSectionHandle);
997 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
998 }
999
1000 void
1001 Test_ImageSection2(void)
1002 {
1003 UNICODE_STRING FileName;
1004 NTSTATUS Status;
1005 OBJECT_ATTRIBUTES FileObjectAttributes;
1006 IO_STATUS_BLOCK IoStatusBlock;
1007 HANDLE FileHandle, ImageSectionHandle;
1008 PVOID ImageBase, BaseAddress;
1009 SIZE_T ViewSize;
1010 LARGE_INTEGER MaximumSize, SectionOffset;
1011
1012 if (!RtlDosPathNameToNtPathName_U(L"testdata\\nvoglv32.dll",
1013 &FileName,
1014 NULL,
1015 NULL))
1016 {
1017 ok(0, "RtlDosPathNameToNtPathName_U failed\n");
1018 return;
1019 }
1020
1021 InitializeObjectAttributes(&FileObjectAttributes,
1022 &FileName,
1023 0,
1024 NULL,
1025 NULL);
1026
1027 Status = NtOpenFile(&FileHandle,
1028 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
1029 &FileObjectAttributes,
1030 &IoStatusBlock,
1031 FILE_SHARE_READ,
1032 FILE_SYNCHRONOUS_IO_NONALERT);
1033 ok_ntstatus(Status, STATUS_SUCCESS);
1034 printf("Opened file with handle %p\n", FileHandle);
1035
1036 /* Create a data section with write access */
1037 MaximumSize.QuadPart = 0x20000;
1038 Status = NtCreateSection(&ImageSectionHandle,
1039 SECTION_ALL_ACCESS, // DesiredAccess
1040 NULL, // ObjectAttributes
1041 &MaximumSize, // MaximumSize
1042 PAGE_READWRITE, // SectionPageProtection
1043 SEC_IMAGE, // AllocationAttributes
1044 FileHandle);
1045 ok_ntstatus(Status, STATUS_SUCCESS);
1046
1047 printf("Created image section with handle %p\n", ImageSectionHandle);
1048 //system("PAUSE");
1049
1050 /* Map the image section */
1051 ImageBase = NULL;
1052 ViewSize = 0x0000;
1053 SectionOffset.QuadPart = 0x00000;
1054 Status = NtMapViewOfSection(ImageSectionHandle,
1055 NtCurrentProcess(),
1056 &ImageBase,
1057 0,
1058 0,
1059 &SectionOffset,
1060 &ViewSize,
1061 ViewShare,
1062 0,
1063 PAGE_READWRITE);
1064 ok_ntstatus(Status, STATUS_SUCCESS);
1065
1066 printf("Mapped image section at %p, value in text section: %lx\n",
1067 ImageBase, *((ULONG*)((PCHAR)ImageBase + 0x1196)));
1068 system("PAUSE");
1069
1070 /* Try to allocate a page after the section */
1071 BaseAddress = (PUCHAR)ImageBase + 0x10000;
1072 ViewSize = 0x1000;
1073 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
1074 &BaseAddress,
1075 0,
1076 &ViewSize,
1077 MEM_RESERVE | MEM_COMMIT,
1078 PAGE_READWRITE);
1079 printf("allocation status: %lx\n", Status);
1080 system("PAUSE");
1081
1082 }
1083
1084 // doesn't work with WoW64!
1085 void
1086 Test_BasedSection(void)
1087 {
1088 NTSTATUS Status;
1089 HANDLE SectionHandle1, SectionHandle2;
1090 LARGE_INTEGER MaximumSize, SectionOffset;
1091 PVOID BaseAddress1, BaseAddress2;
1092 SIZE_T ViewSize;
1093
1094 /* Create a based section with SEC_COMMIT */
1095 MaximumSize.QuadPart = 0x1000;
1096 Status = NtCreateSection(&SectionHandle1,
1097 SECTION_ALL_ACCESS,
1098 NULL,
1099 &MaximumSize,
1100 PAGE_READWRITE,
1101 SEC_COMMIT | SEC_BASED,
1102 NULL);
1103 ok_ntstatus(Status, STATUS_SUCCESS);
1104
1105 /* Map the 1st section */
1106 BaseAddress1 = NULL;
1107 SectionOffset.QuadPart = 0;
1108 ViewSize = 0;
1109 Status = NtMapViewOfSection(SectionHandle1,
1110 NtCurrentProcess(),
1111 &BaseAddress1,
1112 0,
1113 0,
1114 &SectionOffset,
1115 &ViewSize,
1116 ViewShare,
1117 0,
1118 PAGE_READWRITE);
1119 #if 0 // WOW64?
1120 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
1121 #else
1122 ok_ntstatus(Status, STATUS_SUCCESS);
1123 #endif
1124
1125 /* Create a 2nd based section with SEC_COMMIT */
1126 MaximumSize.QuadPart = 0x1000;
1127 Status = NtCreateSection(&SectionHandle2,
1128 SECTION_ALL_ACCESS,
1129 NULL,
1130 &MaximumSize,
1131 PAGE_READWRITE,
1132 SEC_COMMIT | SEC_BASED,
1133 NULL);
1134 ok_ntstatus(Status, STATUS_SUCCESS);//
1135
1136 /* Map the 2nd section */
1137 BaseAddress2 = NULL;
1138 SectionOffset.QuadPart = 0;
1139 ViewSize = 0;
1140 Status = NtMapViewOfSection(SectionHandle2,
1141 NtCurrentProcess(),
1142 &BaseAddress2,
1143 0,
1144 0,
1145 &SectionOffset,
1146 &ViewSize,
1147 ViewShare,
1148 0,
1149 PAGE_READWRITE);
1150 #if 0 // WOW64?
1151 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES);
1152 #else
1153 ok_ntstatus(Status, STATUS_SUCCESS);
1154 ok((ULONG_PTR)BaseAddress2 < (ULONG_PTR)BaseAddress1,
1155 "Invalid addresses: BaseAddress1=%p, BaseAddress2=%p\n", BaseAddress1, BaseAddress2);
1156 ok(((ULONG_PTR)BaseAddress1 - (ULONG_PTR)BaseAddress2) == 0x10000,
1157 "Invalid addresses: BaseAddress1=%p, BaseAddress2=%p\n", BaseAddress1, BaseAddress2);
1158 #endif
1159 }
1160
1161 #define BYTES4(x) x, x, x, x
1162 #define BYTES8(x) BYTES4(x), BYTES4(x)
1163 #define BYTES16(x) BYTES8(x), BYTES8(x)
1164 #define BYTES32(x) BYTES16(x), BYTES16(x)
1165 #define BYTES64(x) BYTES32(x), BYTES32(x)
1166 #define BYTES128(x) BYTES64(x), BYTES64(x)
1167 #define BYTES256(x) BYTES128(x), BYTES128(x)
1168 #define BYTES512(x) BYTES256(x), BYTES256(x)
1169 #define BYTES1024(x) BYTES512(x), BYTES512(x)
1170
1171 static struct _MY_IMAGE_FILE
1172 {
1173 IMAGE_DOS_HEADER doshdr;
1174 WORD stub[32];
1175 IMAGE_NT_HEADERS32 nthdrs;
1176 IMAGE_SECTION_HEADER text_header;
1177 IMAGE_SECTION_HEADER rossym_header;
1178 IMAGE_SECTION_HEADER rsrc_header;
1179 BYTE pad[16];
1180 BYTE text_data[0x400];
1181 BYTE rossym_data[0x400];
1182 BYTE rsrc_data[0x400];
1183 } ImageFile =
1184 {
1185 /* IMAGE_DOS_HEADER */
1186 {
1187 IMAGE_DOS_SIGNATURE, 144, 3, 0, 4, 0, 0xFFFF, 0, 0xB8, 0, 0, 0, 0x40,
1188 0, { 0 }, 0, 0, { 0 }, 0x80
1189 },
1190 /* binary to print "This program cannot be run in DOS mode." */
1191 {
1192 0x1F0E, 0x0EBA, 0xB400, 0xCD09, 0xB821, 0x4C01, 0x21CD, 0x6854, 0x7369,
1193 0x7020, 0x6F72, 0x7267, 0x6D61, 0x6320, 0x6E61, 0x6F6E, 0x2074, 0x6562,
1194 0x7220, 0x6E75, 0x6920, 0x206E, 0x4F44, 0x2053, 0x6F6D, 0x6564, 0x0D2E,
1195 0x0A0D, 0x0024, 0x0000, 0x0000, 0x0000
1196 },
1197 /* IMAGE_NT_HEADERS32 */
1198 {
1199 IMAGE_NT_SIGNATURE, /* Signature */
1200 /* IMAGE_FILE_HEADER */
1201 {
1202 IMAGE_FILE_MACHINE_I386, /* Machine */
1203 3, /* NumberOfSections */
1204 0x47EFDF09, /* TimeDateStamp */
1205 0, /* PointerToSymbolTable */
1206 0, /* NumberOfSymbols */
1207 0xE0, /* SizeOfOptionalHeader */
1208 IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED |
1209 IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE |
1210 IMAGE_FILE_DLL, /* Characteristics */
1211 },
1212 /* IMAGE_OPTIONAL_HEADER32 */
1213 {
1214 IMAGE_NT_OPTIONAL_HDR32_MAGIC, /* Magic */
1215 8, /* MajorLinkerVersion */
1216 0, /* MinorLinkerVersion */
1217 0x400, /* SizeOfCode */
1218 0x000, /* SizeOfInitializedData */
1219 0, /* SizeOfUninitializedData */
1220 0x2000, /* AddressOfEntryPoint */
1221 0x2000, /* BaseOfCode */
1222 0x0000, /* BaseOfData */
1223 0x400000, /* ImageBase */
1224 0x2000, /* SectionAlignment */
1225 0x200, /* FileAlignment */
1226 4, /* MajorOperatingSystemVersion */
1227 0, /* MinorOperatingSystemVersion */
1228 0, /* MajorImageVersion */
1229 0, /* MinorImageVersion */
1230 4, /* MajorSubsystemVersion */
1231 0, /* MinorSubsystemVersion */
1232 0, /* Win32VersionValue */
1233 0x8000, /* SizeOfImage */
1234 0x200, /* SizeOfHeaders */
1235 0x0, /* CheckSum */
1236 IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */
1237 IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
1238 IMAGE_DLLCHARACTERISTICS_NO_SEH |
1239 IMAGE_DLLCHARACTERISTICS_NX_COMPAT, /* DllCharacteristics */
1240 0x100000, /* SizeOfStackReserve */
1241 0x1000, /* SizeOfStackCommit */
1242 0x100000, /* SizeOfHeapReserve */
1243 0x1000, /* SizeOfHeapCommit */
1244 0, /* LoaderFlags */
1245 0x10, /* NumberOfRvaAndSizes */
1246 /* IMAGE_DATA_DIRECTORY */
1247 {
1248 { 0 }, /* Export Table */
1249 { 0 }, /* Import Table */
1250 { 0 }, /* Resource Table */
1251 { 0 }, /* Exception Table */
1252 { 0 }, /* Certificate Table */
1253 { 0 }, /* Base Relocation Table */
1254 { 0 }, /* Debug */
1255 { 0 }, /* Copyright */
1256 { 0 }, /* Global Ptr */
1257 { 0 }, /* TLS Table */
1258 { 0 }, /* Load Config Table */
1259 { 0 }, /* Bound Import */
1260 { 0 }, /* IAT */
1261 { 0 }, /* Delay Import Descriptor */
1262 { 0 }, /* CLI Header */
1263 { 0 } /* Reserved */
1264 }
1265 }
1266 },
1267 /* IMAGE_SECTION_HEADER */
1268 {
1269 ".text", /* Name */
1270 { 0x394 }, /* Misc.VirtualSize */
1271 0x2000, /* VirtualAddress */
1272 0x400, /* SizeOfRawData */
1273 0x200, /* PointerToRawData */
1274 0, /* PointerToRelocations */
1275 0, /* PointerToLinenumbers */
1276 0, /* NumberOfRelocations */
1277 0, /* NumberOfLinenumbers */
1278 IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE |
1279 IMAGE_SCN_CNT_CODE, /* Characteristics */
1280 },
1281 /* IMAGE_SECTION_HEADER */
1282 {
1283 ".rossym", /* Name */
1284 { 0x100 }, /* Misc.VirtualSize */
1285 0x4000, /* VirtualAddress */
1286 0x400, /* SizeOfRawData */
1287 0x600, /* PointerToRawData */
1288 0, /* PointerToRelocations */
1289 0, /* PointerToLinenumbers */
1290 0, /* NumberOfRelocations */
1291 0, /* NumberOfLinenumbers */
1292 IMAGE_SCN_MEM_READ | IMAGE_SCN_TYPE_NOLOAD, /* Characteristics */
1293 },
1294 /* IMAGE_SECTION_HEADER */
1295 {
1296 ".rsrc", /* Name */
1297 { 0x100 }, /* Misc.VirtualSize */
1298 0x6000, /* VirtualAddress */
1299 0x400, /* SizeOfRawData */
1300 0xA00, /* PointerToRawData */
1301 0, /* PointerToRelocations */
1302 0, /* PointerToLinenumbers */
1303 0, /* NumberOfRelocations */
1304 0, /* NumberOfLinenumbers */
1305 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */
1306 },
1307 /* fill */
1308 { 0 },
1309 /* text */
1310 { 0xc3, 0 },
1311 /* rossym */
1312 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1313 BYTES8(0xaa),
1314 BYTES16(0xbb),
1315 BYTES32(0xcc),
1316 BYTES64(0xdd),
1317 BYTES64(0xee),
1318 BYTES64(0xff),
1319 },
1320 /* rsrc */
1321 { 0 },
1322 };
1323
1324 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, text_data) == 0x200);
1325 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, rossym_data) == 0x600);
1326 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, rsrc_data) == 0xa00);
1327
1328 static
1329 void
1330 Test_NoLoadSection(BOOL Relocate)
1331 {
1332 NTSTATUS Status;
1333 WCHAR TempPath[MAX_PATH];
1334 WCHAR FileName[MAX_PATH];
1335 HANDLE Handle;
1336 HANDLE SectionHandle;
1337 LARGE_INTEGER SectionOffset;
1338 PVOID BaseAddress;
1339 SIZE_T ViewSize;
1340 ULONG Written;
1341 ULONG Length;
1342 BOOL Success;
1343
1344 Length = GetTempPathW(MAX_PATH, TempPath);
1345 ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError());
1346 Length = GetTempFileNameW(TempPath, L"nta", 0, FileName);
1347 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError());
1348 Handle = CreateFileW(FileName,
1349 FILE_ALL_ACCESS,
1350 0,
1351 NULL,
1352 CREATE_ALWAYS,
1353 0,
1354 NULL);
1355 if (Handle == INVALID_HANDLE_VALUE)
1356 {
1357 skip("Failed to create temp file %ls, error %lu\n", FileName, GetLastError());
1358 return;
1359 }
1360 if (Relocate)
1361 {
1362 ok((ULONG_PTR)GetModuleHandle(NULL) <= 0x80000000, "Module at %p\n", GetModuleHandle(NULL));
1363 ImageFile.nthdrs.OptionalHeader.ImageBase = (ULONG)(ULONG_PTR)GetModuleHandle(NULL);
1364 }
1365 else
1366 {
1367 ImageFile.nthdrs.OptionalHeader.ImageBase = 0xe400000;
1368 }
1369
1370 Success = WriteFile(Handle,
1371 &ImageFile,
1372 sizeof(ImageFile),
1373 &Written,
1374 NULL);
1375 ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError());
1376 ok(Written == sizeof(ImageFile), "WriteFile wrote %lu bytes\n", Written);
1377
1378 Status = NtCreateSection(&SectionHandle,
1379 SECTION_ALL_ACCESS,
1380 NULL,
1381 NULL,
1382 PAGE_EXECUTE_READWRITE,
1383 SEC_IMAGE,
1384 Handle);
1385 ok_ntstatus(Status, STATUS_SUCCESS);
1386
1387 if (NT_SUCCESS(Status))
1388 {
1389 /* Map the section with */
1390 BaseAddress = NULL;
1391 SectionOffset.QuadPart = 0;
1392 ViewSize = 0;
1393 Status = NtMapViewOfSection(SectionHandle,
1394 NtCurrentProcess(),
1395 &BaseAddress,
1396 0,
1397 0,
1398 &SectionOffset,
1399 &ViewSize,
1400 ViewShare,
1401 0,
1402 PAGE_READWRITE);
1403 if (Relocate)
1404 ok_ntstatus(Status, STATUS_IMAGE_NOT_AT_BASE);
1405 else
1406 ok_ntstatus(Status, STATUS_SUCCESS);
1407 if (NT_SUCCESS(Status))
1408 {
1409 PUCHAR Bytes = BaseAddress;
1410 #define TEST_BYTE(n, v) StartSeh() ok_hex(Bytes[n], v); EndSeh(STATUS_SUCCESS);
1411 TEST_BYTE(0x2000, 0xc3);
1412 TEST_BYTE(0x2001, 0x00);
1413 TEST_BYTE(0x4000, 0x01);
1414 TEST_BYTE(0x4001, 0x23);
1415 TEST_BYTE(0x4007, 0xef);
1416 TEST_BYTE(0x4008, 0xaa);
1417 TEST_BYTE(0x4010, 0xbb);
1418 TEST_BYTE(0x4020, 0xcc);
1419 TEST_BYTE(0x4040, 0xdd);
1420 TEST_BYTE(0x4080, 0xee);
1421 TEST_BYTE(0x40c0, 0xff);
1422 TEST_BYTE(0x40ff, 0xff);
1423 TEST_BYTE(0x4100, 0x00);
1424 TEST_BYTE(0x41ff, 0x00);
1425 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
1426 ok_ntstatus(Status, STATUS_SUCCESS);
1427 }
1428 Status = NtClose(SectionHandle);
1429 ok_ntstatus(Status, STATUS_SUCCESS);
1430 }
1431
1432 CloseHandle(Handle);
1433 DeleteFileW(FileName);
1434 }
1435
1436 static void
1437 Test_EmptyFile(VOID)
1438 {
1439 NTSTATUS Status;
1440 WCHAR TempPath[MAX_PATH];
1441 WCHAR FileName[MAX_PATH];
1442 HANDLE Handle;
1443 HANDLE SectionHandle;
1444 ULONG Length;
1445
1446 Length = GetTempPathW(MAX_PATH, TempPath);
1447 ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError());
1448 Length = GetTempFileNameW(TempPath, L"nta", 0, FileName);
1449 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError());
1450 Handle = CreateFileW(FileName,
1451 FILE_ALL_ACCESS,
1452 0,
1453 NULL,
1454 CREATE_ALWAYS,
1455 0,
1456 NULL);
1457 if (Handle == INVALID_HANDLE_VALUE)
1458 {
1459 skip("Failed to create temp file %ls, error %lu\n", FileName, GetLastError());
1460 return;
1461 }
1462
1463 Status = NtCreateSection(&SectionHandle,
1464 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1465 0, 0, PAGE_READONLY, SEC_COMMIT, Handle);
1466 ok_ntstatus(Status, STATUS_MAPPED_FILE_SIZE_ZERO);
1467
1468 if (NT_SUCCESS(Status))
1469 NtClose(SectionHandle);
1470
1471 Status = NtCreateSection(&SectionHandle,
1472 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1473 0, 0, PAGE_READONLY, SEC_IMAGE, Handle);
1474 ok_ntstatus(Status, STATUS_INVALID_FILE_FOR_SECTION);
1475
1476 if (NT_SUCCESS(Status))
1477 NtClose(SectionHandle);
1478
1479 CloseHandle(Handle);
1480 DeleteFileW(FileName);
1481 }
1482
1483 // CORE-11206
1484 static void
1485 Test_Truncate(VOID)
1486 {
1487 WCHAR TempPath[MAX_PATH];
1488 WCHAR FileName[MAX_PATH];
1489 NTSTATUS Status;
1490 SIZE_T ViewSize = 0;
1491 HANDLE Handle;
1492 HANDLE SectionHandle;
1493
1494 ULONG Length;
1495 BOOL Success;
1496 DWORD Written, Error;
1497 VOID* BaseAddress;
1498
1499 Length = GetTempPathW(MAX_PATH, TempPath);
1500 ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError());
1501 Length = GetTempFileNameW(TempPath, L"nta", 0, FileName);
1502 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError());
1503 Handle = CreateFileW(FileName, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, 0, NULL);
1504
1505 Success = WriteFile(Handle, "TESTDATA", 8, &Written, NULL);
1506 ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError());
1507 ok(Written == 8, "WriteFile wrote %lu bytes\n", Written);
1508
1509 Written = SetFilePointer(Handle, 6, NULL, FILE_BEGIN);
1510 ok(Written == 6, "SetFilePointer returned %lu bytes\n", Written);
1511 Success = SetEndOfFile(Handle);
1512 ok(Success == TRUE, "SetEndOfFile failed with %lu\n", GetLastError());
1513
1514 Status = NtCreateSection(&SectionHandle,
1515 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1516 0, 0, PAGE_READONLY, SEC_COMMIT, Handle);
1517 ok_ntstatus(Status, STATUS_SUCCESS);
1518 BaseAddress = NULL;
1519 ViewSize = 0;
1520 Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0,
1521 0, 0, &ViewSize, ViewShare, 0, PAGE_READONLY);
1522 ok_ntstatus(Status, STATUS_SUCCESS);
1523
1524 if (BaseAddress)
1525 {
1526 // First we test data that was truncated even before the file mapping was opened
1527 Length = strlen((char*)BaseAddress);
1528 ok(Length == 6, "Old data was not properly erased! (Length=%lu)\n", Length);
1529 }
1530
1531 // Now we truncate the file on disk some more
1532 Written = SetFilePointer(Handle, 4, NULL, FILE_BEGIN);
1533 ok(Written == 4, "SetFilePointer returned %lu bytes\n", Written);
1534 Success = SetEndOfFile(Handle);
1535 Error = GetLastError();
1536 ok(Success == FALSE, "SetEndOfFile succeeded\n");
1537 ok(Error == ERROR_USER_MAPPED_FILE, "SetEndOfFile did not set error to ERROR_USER_MAPPED_FILE (%lu)\n", Error);
1538
1539 if (BaseAddress)
1540 {
1541 Length = strlen((char*)BaseAddress);
1542 ok(Length == 6, "Length should not have changed! (Length=%lu)\n", Length);
1543 }
1544
1545 // Unmap and set the end shorter.
1546 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
1547 ok_ntstatus(Status, STATUS_SUCCESS);
1548 Success = CloseHandle(SectionHandle);
1549 ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError());
1550
1551 Written = SetFilePointer(Handle, 4, NULL, FILE_BEGIN);
1552 ok(Written == 4, "SetFilePointer returned %lu bytes\n", Written);
1553 Success = SetEndOfFile(Handle);
1554 ok(Success == TRUE, "SetEndOfFile failed with %lu\n", GetLastError());
1555
1556 Status = NtCreateSection(&SectionHandle,
1557 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1558 0, 0, PAGE_READONLY, SEC_COMMIT, Handle);
1559 ok_ntstatus(Status, STATUS_SUCCESS);
1560 BaseAddress = NULL;
1561 ViewSize = 0;
1562 Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0,
1563 0, 0, &ViewSize, ViewShare, 0, PAGE_READONLY);
1564 ok_ntstatus(Status, STATUS_SUCCESS);
1565
1566 // CLEANUP
1567 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
1568 ok_ntstatus(Status, STATUS_SUCCESS);
1569 Success = CloseHandle(SectionHandle);
1570 ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError());
1571 Success = CloseHandle(Handle);
1572 ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError());
1573
1574 Success = DeleteFileW(FileName);
1575 ok(Success == TRUE, "DeleteFileW failed with %lu\n", GetLastError());
1576 }
1577
1578 START_TEST(NtMapViewOfSection)
1579 {
1580 Test_PageFileSection();
1581 Test_ImageSection();
1582 Test_BasedSection();
1583 Test_NoLoadSection(FALSE);
1584 Test_NoLoadSection(TRUE);
1585 Test_EmptyFile();
1586 Test_Truncate();
1587 }