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
Test_PageFileSection(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
Test_ImageSection(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
Test_ImageSection2(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
Test_BasedSection(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
Test_SectionContents(BOOL Relocate)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
Test_RawSize(ULONG TestNumber)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
Test_EmptyFile(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
Test_Truncate(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
START_TEST(NtMapViewOfSection)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