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