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     BYTE pad[16];
1177     BYTE text_data[0x400];
1178     BYTE rossym_data[0x400];
1179     BYTE rsrc_data[0x400];
1180 } ImageFile =
1181 {
1182     /* IMAGE_DOS_HEADER */
1183     {
1184         IMAGE_DOS_SIGNATURE, 144, 3, 0, 4, 0, 0xFFFF, 0, 0xB8, 0, 0, 0, 0x40,
1185         0, { 0 }, 0, 0, { 0 }, 0x80
1186     },
1187     /* binary to print "This program cannot be run in DOS mode." */
1188     {
1189         0x1F0E, 0x0EBA, 0xB400, 0xCD09, 0xB821, 0x4C01, 0x21CD, 0x6854, 0x7369,
1190         0x7020, 0x6F72, 0x7267, 0x6D61, 0x6320, 0x6E61, 0x6F6E, 0x2074, 0x6562,
1191         0x7220, 0x6E75, 0x6920, 0x206E, 0x4F44, 0x2053, 0x6F6D, 0x6564, 0x0D2E,
1192         0x0A0D, 0x0024, 0x0000, 0x0000, 0x0000
1193     },
1194     /* IMAGE_NT_HEADERS32 */
1195     {
1196         IMAGE_NT_SIGNATURE, /* Signature */
1197         /* IMAGE_FILE_HEADER */
1198         {
1199             IMAGE_FILE_MACHINE_I386, /* Machine */
1200             3, /* NumberOfSections */
1201             0x47EFDF09, /* TimeDateStamp */
1202             0, /* PointerToSymbolTable */
1203             0, /* NumberOfSymbols */
1204             0xE0, /* SizeOfOptionalHeader */
1205             IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED |
1206             IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE |
1207             IMAGE_FILE_DLL, /* Characteristics */
1208         },
1209         /* IMAGE_OPTIONAL_HEADER32 */
1210         {
1211             IMAGE_NT_OPTIONAL_HDR32_MAGIC, /* Magic */
1212             8, /* MajorLinkerVersion */
1213             0, /* MinorLinkerVersion */
1214             0x400, /* SizeOfCode */
1215             0x000, /* SizeOfInitializedData */
1216             0, /* SizeOfUninitializedData */
1217             0x2000, /* AddressOfEntryPoint */
1218             0x2000, /* BaseOfCode */
1219             0x0000, /* BaseOfData */
1220             0x400000, /* ImageBase */
1221             0x2000, /* SectionAlignment */
1222             0x200, /* FileAlignment */
1223             4, /* MajorOperatingSystemVersion */
1224             0, /* MinorOperatingSystemVersion */
1225             0, /* MajorImageVersion */
1226             0, /* MinorImageVersion */
1227             4, /* MajorSubsystemVersion */
1228             0, /* MinorSubsystemVersion */
1229             0, /* Win32VersionValue */
1230             0x8000, /* SizeOfImage */
1231             0x200, /* SizeOfHeaders */
1232             0x0, /* CheckSum */
1233             IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */
1234             IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
1235             IMAGE_DLLCHARACTERISTICS_NO_SEH |
1236             IMAGE_DLLCHARACTERISTICS_NX_COMPAT, /* DllCharacteristics */
1237             0x100000, /* SizeOfStackReserve */
1238             0x1000, /* SizeOfStackCommit */
1239             0x100000, /* SizeOfHeapReserve */
1240             0x1000, /* SizeOfHeapCommit */
1241             0, /* LoaderFlags */
1242             0x10, /* NumberOfRvaAndSizes */
1243             /* IMAGE_DATA_DIRECTORY */
1244             {
1245                 { 0 }, /* Export Table */
1246                 { 0 }, /* Import Table */
1247                 { 0 }, /* Resource Table */
1248                 { 0 }, /* Exception Table */
1249                 { 0 }, /* Certificate Table */
1250                 { 0 }, /* Base Relocation Table */
1251                 { 0 }, /* Debug */
1252                 { 0 }, /* Copyright */
1253                 { 0 }, /* Global Ptr */
1254                 { 0 }, /* TLS Table */
1255                 { 0 }, /* Load Config Table */
1256                 { 0 }, /* Bound Import */
1257                 { 0 }, /* IAT */
1258                 { 0 }, /* Delay Import Descriptor */
1259                 { 0 }, /* CLI Header */
1260                 { 0 } /* Reserved */
1261             }
1262         }
1263     },
1264     /* IMAGE_SECTION_HEADER */
1265     {
1266         ".text", /* Name */
1267         { 0x394 }, /* Misc.VirtualSize */
1268         0x2000, /* VirtualAddress */
1269         0x400, /* SizeOfRawData */
1270         0x200, /* PointerToRawData */
1271         0, /* PointerToRelocations */
1272         0, /* PointerToLinenumbers */
1273         0, /* NumberOfRelocations */
1274         0, /* NumberOfLinenumbers */
1275         IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE |
1276         IMAGE_SCN_CNT_CODE, /* Characteristics */
1277     },
1278     /* IMAGE_SECTION_HEADER */
1279     {
1280         ".rossym", /* Name */
1281         { 0x100 }, /* Misc.VirtualSize */
1282         0x4000, /* VirtualAddress */
1283         0x400, /* SizeOfRawData */
1284         0x600, /* PointerToRawData */
1285         0, /* PointerToRelocations */
1286         0, /* PointerToLinenumbers */
1287         0, /* NumberOfRelocations */
1288         0, /* NumberOfLinenumbers */
1289         IMAGE_SCN_MEM_READ | IMAGE_SCN_TYPE_NOLOAD, /* Characteristics */
1290     },
1291     /* IMAGE_SECTION_HEADER */
1292     {
1293         ".rsrc", /* Name */
1294         { 0x100 }, /* Misc.VirtualSize */
1295         0x6000, /* VirtualAddress */
1296         0x400, /* SizeOfRawData */
1297         0xA00, /* PointerToRawData */
1298         0, /* PointerToRelocations */
1299         0, /* PointerToLinenumbers */
1300         0, /* NumberOfRelocations */
1301         0, /* NumberOfLinenumbers */
1302         IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */
1303     },
1304     /* fill */
1305     { 0 },
1306     /* text */
1307     { 0xc3, 0 },
1308     /* rossym */
1309     { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1310       BYTES8(0xaa),
1311       BYTES16(0xbb),
1312       BYTES32(0xcc),
1313       BYTES64(0xdd),
1314       BYTES64(0xee),
1315       BYTES64(0xff),
1316     },
1317     /* rsrc */
1318     { 0 },
1319 };
1320 
1321 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, text_data) == 0x200);
1322 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, rossym_data) == 0x600);
1323 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, rsrc_data) == 0xa00);
1324 
1325 static
1326 void
1327 Test_NoLoadSection(BOOL Relocate)
1328 {
1329     NTSTATUS Status;
1330     WCHAR TempPath[MAX_PATH];
1331     WCHAR FileName[MAX_PATH];
1332     HANDLE Handle;
1333     HANDLE SectionHandle;
1334     LARGE_INTEGER SectionOffset;
1335     PVOID BaseAddress;
1336     SIZE_T ViewSize;
1337     ULONG Written;
1338     ULONG Length;
1339     BOOL Success;
1340 
1341     Length = GetTempPathW(MAX_PATH, TempPath);
1342     ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError());
1343     Length = GetTempFileNameW(TempPath, L"nta", 0, FileName);
1344     ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError());
1345     Handle = CreateFileW(FileName,
1346                          FILE_ALL_ACCESS,
1347                          0,
1348                          NULL,
1349                          CREATE_ALWAYS,
1350                          0,
1351                          NULL);
1352     if (Handle == INVALID_HANDLE_VALUE)
1353     {
1354         skip("Failed to create temp file %ls, error %lu\n", FileName, GetLastError());
1355         return;
1356     }
1357     if (Relocate)
1358     {
1359         ok((ULONG_PTR)GetModuleHandle(NULL) <= 0x80000000, "Module at %p\n", GetModuleHandle(NULL));
1360         ImageFile.nthdrs.OptionalHeader.ImageBase = (ULONG)(ULONG_PTR)GetModuleHandle(NULL);
1361     }
1362     else
1363     {
1364         ImageFile.nthdrs.OptionalHeader.ImageBase = 0xe400000;
1365     }
1366 
1367     Success = WriteFile(Handle,
1368                         &ImageFile,
1369                         sizeof(ImageFile),
1370                         &Written,
1371                         NULL);
1372     ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError());
1373     ok(Written == sizeof(ImageFile), "WriteFile wrote %lu bytes\n", Written);
1374 
1375     Status = NtCreateSection(&SectionHandle,
1376                              SECTION_ALL_ACCESS,
1377                              NULL,
1378                              NULL,
1379                              PAGE_EXECUTE_READWRITE,
1380                              SEC_IMAGE,
1381                              Handle);
1382     ok_ntstatus(Status, STATUS_SUCCESS);
1383 
1384     if (NT_SUCCESS(Status))
1385     {
1386         /* Map the section with  */
1387         BaseAddress = NULL;
1388         SectionOffset.QuadPart = 0;
1389         ViewSize = 0;
1390         Status = NtMapViewOfSection(SectionHandle,
1391                                     NtCurrentProcess(),
1392                                     &BaseAddress,
1393                                     0,
1394                                     0,
1395                                     &SectionOffset,
1396                                     &ViewSize,
1397                                     ViewShare,
1398                                     0,
1399                                     PAGE_READWRITE);
1400         if (Relocate)
1401             ok_ntstatus(Status, STATUS_IMAGE_NOT_AT_BASE);
1402         else
1403             ok_ntstatus(Status, STATUS_SUCCESS);
1404         if (NT_SUCCESS(Status))
1405         {
1406             PUCHAR Bytes = BaseAddress;
1407 #define TEST_BYTE(n, v) StartSeh() ok_hex(Bytes[n], v); EndSeh(STATUS_SUCCESS);
1408             TEST_BYTE(0x2000, 0xc3);
1409             TEST_BYTE(0x2001, 0x00);
1410             TEST_BYTE(0x4000, 0x01);
1411             TEST_BYTE(0x4001, 0x23);
1412             TEST_BYTE(0x4007, 0xef);
1413             TEST_BYTE(0x4008, 0xaa);
1414             TEST_BYTE(0x4010, 0xbb);
1415             TEST_BYTE(0x4020, 0xcc);
1416             TEST_BYTE(0x4040, 0xdd);
1417             TEST_BYTE(0x4080, 0xee);
1418             TEST_BYTE(0x40c0, 0xff);
1419             TEST_BYTE(0x40ff, 0xff);
1420             TEST_BYTE(0x4100, 0x00);
1421             TEST_BYTE(0x41ff, 0x00);
1422             Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
1423             ok_ntstatus(Status, STATUS_SUCCESS);
1424         }
1425         Status = NtClose(SectionHandle);
1426         ok_ntstatus(Status, STATUS_SUCCESS);
1427     }
1428 
1429     CloseHandle(Handle);
1430     DeleteFileW(FileName);
1431 }
1432 
1433 static void
1434 Test_EmptyFile(VOID)
1435 {
1436     NTSTATUS Status;
1437     WCHAR TempPath[MAX_PATH];
1438     WCHAR FileName[MAX_PATH];
1439     HANDLE Handle;
1440     HANDLE SectionHandle;
1441     ULONG Length;
1442 
1443     Length = GetTempPathW(MAX_PATH, TempPath);
1444     ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError());
1445     Length = GetTempFileNameW(TempPath, L"nta", 0, FileName);
1446     ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError());
1447     Handle = CreateFileW(FileName,
1448                          FILE_ALL_ACCESS,
1449                          0,
1450                          NULL,
1451                          CREATE_ALWAYS,
1452                          0,
1453                          NULL);
1454     if (Handle == INVALID_HANDLE_VALUE)
1455     {
1456         skip("Failed to create temp file %ls, error %lu\n", FileName, GetLastError());
1457         return;
1458     }
1459 
1460     Status = NtCreateSection(&SectionHandle,
1461                              STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1462                              0, 0, PAGE_READONLY, SEC_COMMIT, Handle);
1463     ok_ntstatus(Status, STATUS_MAPPED_FILE_SIZE_ZERO);
1464 
1465     if (NT_SUCCESS(Status))
1466         NtClose(SectionHandle);
1467 
1468     Status = NtCreateSection(&SectionHandle,
1469                              STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1470                              0, 0, PAGE_READONLY, SEC_IMAGE, Handle);
1471     ok_ntstatus(Status, STATUS_INVALID_FILE_FOR_SECTION);
1472 
1473     if (NT_SUCCESS(Status))
1474         NtClose(SectionHandle);
1475 
1476     CloseHandle(Handle);
1477     DeleteFileW(FileName);
1478 }
1479 
1480 // CORE-11206
1481 static void
1482 Test_Truncate(VOID)
1483 {
1484     WCHAR TempPath[MAX_PATH];
1485     WCHAR FileName[MAX_PATH];
1486     NTSTATUS Status;
1487     SIZE_T ViewSize = 0;
1488     HANDLE Handle;
1489     HANDLE SectionHandle;
1490 
1491     ULONG Length;
1492     BOOL Success;
1493     DWORD Written, Error;
1494     VOID* BaseAddress;
1495 
1496     Length = GetTempPathW(MAX_PATH, TempPath);
1497     ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError());
1498     Length = GetTempFileNameW(TempPath, L"nta", 0, FileName);
1499     ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError());
1500     Handle = CreateFileW(FileName, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, 0, NULL);
1501 
1502     Success = WriteFile(Handle, "TESTDATA", 8, &Written, NULL);
1503     ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError());
1504     ok(Written == 8, "WriteFile wrote %lu bytes\n", Written);
1505 
1506     Written = SetFilePointer(Handle, 6, NULL, FILE_BEGIN);
1507     ok(Written == 6, "SetFilePointer returned %lu bytes\n", Written);
1508     Success = SetEndOfFile(Handle);
1509     ok(Success == TRUE, "SetEndOfFile failed with %lu\n", GetLastError());
1510 
1511     Status = NtCreateSection(&SectionHandle,
1512                              STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1513                              0, 0, PAGE_READONLY, SEC_COMMIT, Handle);
1514     ok_ntstatus(Status, STATUS_SUCCESS);
1515     BaseAddress = NULL;
1516     ViewSize = 0;
1517     Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0,
1518                                 0, 0, &ViewSize, ViewShare, 0, PAGE_READONLY);
1519     ok_ntstatus(Status, STATUS_SUCCESS);
1520 
1521     if (BaseAddress)
1522     {
1523         // First we test data that was truncated even before the file mapping was opened
1524         Length = strlen((char*)BaseAddress);
1525         ok(Length == 6, "Old data was not properly erased! (Length=%lu)\n", Length);
1526     }
1527 
1528     // Now we truncate the file on disk some more
1529     Written = SetFilePointer(Handle, 4, NULL, FILE_BEGIN);
1530     ok(Written == 4, "SetFilePointer returned %lu bytes\n", Written);
1531     Success = SetEndOfFile(Handle);
1532     Error = GetLastError();
1533     ok(Success == FALSE, "SetEndOfFile succeeded\n");
1534     ok(Error == ERROR_USER_MAPPED_FILE, "SetEndOfFile did not set error to ERROR_USER_MAPPED_FILE (%lu)\n", Error);
1535 
1536     if (BaseAddress)
1537     {
1538         Length = strlen((char*)BaseAddress);
1539         ok(Length == 6, "Length should not have changed! (Length=%lu)\n", Length);
1540     }
1541 
1542     // Unmap and set the end shorter.
1543     Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
1544     ok_ntstatus(Status, STATUS_SUCCESS);
1545     Success = CloseHandle(SectionHandle);
1546     ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError());
1547 
1548     Written = SetFilePointer(Handle, 4, NULL, FILE_BEGIN);
1549     ok(Written == 4, "SetFilePointer returned %lu bytes\n", Written);
1550     Success = SetEndOfFile(Handle);
1551     ok(Success == TRUE, "SetEndOfFile failed with %lu\n", GetLastError());
1552 
1553     Status = NtCreateSection(&SectionHandle,
1554                              STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1555                              0, 0, PAGE_READONLY, SEC_COMMIT, Handle);
1556     ok_ntstatus(Status, STATUS_SUCCESS);
1557     BaseAddress = NULL;
1558     ViewSize = 0;
1559     Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0,
1560                                 0, 0, &ViewSize, ViewShare, 0, PAGE_READONLY);
1561     ok_ntstatus(Status, STATUS_SUCCESS);
1562 
1563     // CLEANUP
1564     Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
1565     ok_ntstatus(Status, STATUS_SUCCESS);
1566     Success = CloseHandle(SectionHandle);
1567     ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError());
1568     Success = CloseHandle(Handle);
1569     ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError());
1570 
1571     Success = DeleteFileW(FileName);
1572     ok(Success == TRUE, "DeleteFileW failed with %lu\n", GetLastError());
1573 }
1574 
1575 START_TEST(NtMapViewOfSection)
1576 {
1577     Test_PageFileSection();
1578     Test_ImageSection();
1579     Test_BasedSection();
1580     Test_NoLoadSection(FALSE);
1581     Test_NoLoadSection(TRUE);
1582     Test_EmptyFile();
1583     Test_Truncate();
1584 }
1585