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     ULONG 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 }
1639