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