1 /*
2  * PROJECT:         ReactOS kernel-mode tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Kernel-Mode Test Suite Section Object test
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include <kmt_test.h>
9 
10 #define CheckObject(Handle, Pointers, Handles) do                   \
11 {                                                                   \
12     PUBLIC_OBJECT_BASIC_INFORMATION ObjectInfo;                     \
13     Status = ZwQueryObject(Handle, ObjectBasicInformation,          \
14                             &ObjectInfo, sizeof ObjectInfo, NULL);  \
15     ok_eq_hex(Status, STATUS_SUCCESS);                              \
16     ok_eq_ulong(ObjectInfo.PointerCount, Pointers);                 \
17     ok_eq_ulong(ObjectInfo.HandleCount, Handles);                   \
18 } while (0)
19 
20 #define CheckSection(SectionObject, SectionFlag) do                     \
21 {                                                                       \
22     SECTION_BASIC_INFORMATION Sbi;                                      \
23     HANDLE SectionHandle = NULL;                                        \
24     NTSTATUS Status;                                                    \
25     if (skip(SectionObject != NULL &&                                   \
26              SectionObject != (PVOID)0x5555555555555555ULL,             \
27              "No section object\n"))                                    \
28         break;                                                          \
29     Status = ObOpenObjectByPointer(SectionObject, OBJ_KERNEL_HANDLE,    \
30                                    NULL, 0, MmSectionObjectType,        \
31                                    KernelMode, &SectionHandle);         \
32     ok_eq_hex(Status, STATUS_SUCCESS);                                  \
33     ok(SectionHandle != NULL, "Section handle null\n");                 \
34     if (!skip(NT_SUCCESS(Status) && SectionHandle,                      \
35               "No section handle\n"))                                   \
36     {                                                                   \
37         Status = ZwQuerySection(SectionHandle, SectionBasicInformation, \
38                                 &Sbi, sizeof Sbi, NULL);                \
39         ok_eq_hex(Status, STATUS_SUCCESS);                              \
40         ok_eq_pointer(Sbi.BaseAddress, NULL);                           \
41         ok_eq_longlong(Sbi.Size.QuadPart, 1LL);                         \
42         ok_eq_hex(Sbi.Attributes, SectionFlag | SEC_FILE);              \
43         ZwClose(SectionHandle);                                         \
44     }                                                                   \
45 } while (0)
46 
47 #define TestMapView(SectionObject, ExpectAtBase, ExpectM) do                    \
48 {                                                                               \
49     NTSTATUS Status;                                                            \
50     PVOID BaseAddress = NULL;                                                   \
51     SIZE_T ViewSize = 0;                                                        \
52     LARGE_INTEGER SectionOffset;                                                \
53     if (skip(SectionObject != NULL &&                                           \
54              SectionObject != (PVOID)0x5555555555555555ULL,                     \
55              "No section object\n"))                                            \
56         break;                                                                  \
57                                                                                 \
58     SectionOffset.QuadPart = 0;                                                 \
59     Status = MmMapViewOfSection(SectionObject, PsGetCurrentProcess(),           \
60                                 &BaseAddress, 0, 1, &SectionOffset,             \
61                                 &ViewSize, ViewUnmap, 0, PAGE_READONLY);        \
62     ok_eq_hex(Status, ExpectAtBase ? STATUS_SUCCESS : STATUS_IMAGE_NOT_AT_BASE);\
63     if (!skip(NT_SUCCESS(Status), "Section not mapped\n"))                      \
64     {                                                                           \
65         ok((LONG_PTR)BaseAddress > 0, "BaseAddress = %p\n", BaseAddress);       \
66         ok_eq_uint(*(PUCHAR)BaseAddress, ExpectM ? 'M' : 0);                    \
67         Status = MmUnmapViewOfSection(PsGetCurrentProcess(), BaseAddress);      \
68         ok_eq_hex(Status, STATUS_SUCCESS);                                      \
69     }                                                                           \
70     BaseAddress = NULL;                                                         \
71     ViewSize = 0;                                                               \
72     Status = MmMapViewOfSection(SectionObject, PsGetCurrentProcess(),           \
73                                 &BaseAddress, 0, 1, &SectionOffset,             \
74                                 &ViewSize, ViewUnmap, 0,                        \
75                                 PAGE_READONLY | PAGE_NOCACHE);                  \
76     ok_eq_hex(Status, ExpectAtBase ? STATUS_SUCCESS : STATUS_IMAGE_NOT_AT_BASE);\
77     if (!skip(NT_SUCCESS(Status), "Section not mapped\n"))                      \
78     {                                                                           \
79         ok((LONG_PTR)BaseAddress > 0, "BaseAddress = %p\n", BaseAddress);       \
80         ok_eq_uint(*(PUCHAR)BaseAddress, ExpectM ? 'M' : 0);                    \
81         Status = MmUnmapViewOfSection(PsGetCurrentProcess(), BaseAddress);      \
82         ok_eq_hex(Status, STATUS_SUCCESS);                                      \
83     }                                                                           \
84 } while (0)
85 
86 static
87 VOID
TestCreateSection(IN HANDLE FileHandle1,IN PFILE_OBJECT FileObject1,IN HANDLE FileHandle2,IN PFILE_OBJECT FileObject2)88 TestCreateSection(
89     IN HANDLE FileHandle1,
90     IN PFILE_OBJECT FileObject1,
91     IN HANDLE FileHandle2,
92     IN PFILE_OBJECT FileObject2)
93 {
94     NTSTATUS Status = STATUS_SUCCESS;
95     PVOID SectionObject;
96     LARGE_INTEGER MaximumSize;
97     ULONG PointerCount1, PointerCount2;
98 
99     KmtStartSeh()
100         Status = MmCreateSection(NULL, 0, NULL, NULL, 0, SEC_RESERVE, NULL, NULL);
101     KmtEndSeh(STATUS_SUCCESS);
102     ok_eq_hex(Status, STATUS_INVALID_PAGE_PROTECTION);
103 
104     if (!KmtIsCheckedBuild)
105     {
106         /* PAGE_NOACCESS and missing SEC_RESERVE/SEC_COMMIT/SEC_IMAGE assert */
107         KmtStartSeh()
108             Status = MmCreateSection(NULL, 0, NULL, NULL, PAGE_NOACCESS, SEC_RESERVE, NULL, NULL);
109         KmtEndSeh(STATUS_ACCESS_VIOLATION);
110 
111         KmtStartSeh()
112             Status = MmCreateSection(NULL, 0, NULL, NULL, PAGE_NOACCESS, 0, NULL, NULL);
113         KmtEndSeh(STATUS_ACCESS_VIOLATION);
114     }
115 
116     SectionObject = KmtInvalidPointer;
117     KmtStartSeh()
118         Status = MmCreateSection(&SectionObject, 0, NULL, NULL, 0, SEC_RESERVE, NULL, NULL);
119     KmtEndSeh(STATUS_SUCCESS);
120     ok_eq_hex(Status, STATUS_INVALID_PAGE_PROTECTION);
121     ok_eq_pointer(SectionObject, KmtInvalidPointer);
122 
123     if (SectionObject && SectionObject != KmtInvalidPointer)
124         ObDereferenceObject(SectionObject);
125 
126     KmtStartSeh()
127         Status = MmCreateSection(NULL, 0, NULL, NULL, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
128     KmtEndSeh(STATUS_ACCESS_VIOLATION);
129 
130     SectionObject = KmtInvalidPointer;
131     KmtStartSeh()
132         Status = MmCreateSection(&SectionObject, 0, NULL, NULL, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
133     KmtEndSeh(STATUS_ACCESS_VIOLATION);
134     ok_eq_pointer(SectionObject, KmtInvalidPointer);
135 
136     if (SectionObject && SectionObject != KmtInvalidPointer)
137         ObDereferenceObject(SectionObject);
138 
139     SectionObject = KmtInvalidPointer;
140     MaximumSize.QuadPart = 0;
141     KmtStartSeh()
142         Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_IMAGE, NULL, NULL);
143     KmtEndSeh(STATUS_SUCCESS);
144     ok_eq_hex(Status, STATUS_INVALID_FILE_FOR_SECTION);
145     ok_eq_longlong(MaximumSize.QuadPart, 0LL);
146     ok_eq_pointer(SectionObject, KmtInvalidPointer);
147 
148     if (SectionObject && SectionObject != KmtInvalidPointer)
149         ObDereferenceObject(SectionObject);
150 
151     MaximumSize.QuadPart = 0;
152     KmtStartSeh()
153         Status = MmCreateSection(NULL, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
154     KmtEndSeh(STATUS_SUCCESS);
155     ok_eq_hex(Status, STATUS_INVALID_PARAMETER_4);
156     ok_eq_longlong(MaximumSize.QuadPart, 0LL);
157 
158     if (SectionObject && SectionObject != KmtInvalidPointer)
159         ObDereferenceObject(SectionObject);
160 
161     MaximumSize.QuadPart = 1;
162     KmtStartSeh()
163         Status = MmCreateSection(NULL, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
164     KmtEndSeh(STATUS_ACCESS_VIOLATION);
165     ok_eq_longlong(MaximumSize.QuadPart, 1LL);
166 
167     if (SectionObject && SectionObject != KmtInvalidPointer)
168         ObDereferenceObject(SectionObject);
169 
170     SectionObject = KmtInvalidPointer;
171     MaximumSize.QuadPart = 0;
172     KmtStartSeh()
173         Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
174     KmtEndSeh(STATUS_SUCCESS);
175     ok_eq_hex(Status, STATUS_INVALID_PARAMETER_4);
176     ok_eq_longlong(MaximumSize.QuadPart, 0LL);
177     ok_eq_pointer(SectionObject, KmtInvalidPointer);
178 
179     if (SectionObject && SectionObject != KmtInvalidPointer)
180         ObDereferenceObject(SectionObject);
181 
182     /* page file section */
183     SectionObject = KmtInvalidPointer;
184     MaximumSize.QuadPart = 1;
185     KmtStartSeh()
186         Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
187     KmtEndSeh(STATUS_SUCCESS);
188     ok_eq_hex(Status, STATUS_SUCCESS);
189     ok_eq_longlong(MaximumSize.QuadPart, 1LL);
190     ok(SectionObject != KmtInvalidPointer, "Section object pointer untouched\n");
191     ok(SectionObject != NULL, "Section object pointer NULL\n");
192 
193     if (SectionObject && SectionObject != KmtInvalidPointer)
194         ObDereferenceObject(SectionObject);
195 
196     if (!skip(FileHandle1 != NULL && FileObject1 != NULL &&
197               FileHandle2 != NULL && FileObject2 != NULL, "No file handle or object\n"))
198     {
199         PointerCount1 = 3;
200         PointerCount2 = 3;
201         /* image section */
202         CheckObject(FileHandle2, PointerCount2, 1L);
203         SectionObject = KmtInvalidPointer;
204         MaximumSize.QuadPart = 1;
205         KmtStartSeh()
206             Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_IMAGE, FileHandle2, NULL);
207         KmtEndSeh(STATUS_SUCCESS);
208         ok_eq_hex(Status, STATUS_SUCCESS);
209         ok_eq_longlong(MaximumSize.QuadPart, 1LL);
210         ok(SectionObject != KmtInvalidPointer, "Section object pointer untouched\n");
211         ok(SectionObject != NULL, "Section object pointer NULL\n");
212         CheckObject(FileHandle2, PointerCount2, 1L);
213         CheckSection(SectionObject, SEC_IMAGE);
214         TestMapView(SectionObject, FALSE, TRUE);
215 
216         if (SectionObject && SectionObject != KmtInvalidPointer)
217             ObDereferenceObject(SectionObject);
218 
219         CheckObject(FileHandle2, PointerCount2, 1L);
220         SectionObject = KmtInvalidPointer;
221         MaximumSize.QuadPart = 1;
222         KmtStartSeh()
223             Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_IMAGE, NULL, FileObject2);
224         KmtEndSeh(STATUS_SUCCESS);
225         ok_eq_hex(Status, STATUS_SUCCESS);
226         ok_eq_longlong(MaximumSize.QuadPart, 1LL);
227         ok(SectionObject != KmtInvalidPointer, "Section object pointer untouched\n");
228         ok(SectionObject != NULL, "Section object pointer NULL\n");
229         ++PointerCount2;
230         CheckObject(FileHandle2, PointerCount2, 1L);
231         CheckSection(SectionObject, 0);
232         TestMapView(SectionObject, TRUE, TRUE);
233 
234         if (SectionObject && SectionObject != KmtInvalidPointer)
235             ObDereferenceObject(SectionObject);
236         //--PointerCount2;  // ????
237 
238         CheckObject(FileHandle2, PointerCount2, 1L);
239         SectionObject = KmtInvalidPointer;
240         MaximumSize.QuadPart = 1;
241         KmtStartSeh()
242             Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_IMAGE, FileHandle2, FileObject2);
243         KmtEndSeh(STATUS_SUCCESS);
244         ok_eq_hex(Status, STATUS_SUCCESS);
245         ok_eq_longlong(MaximumSize.QuadPart, 1LL);
246         ok(SectionObject != KmtInvalidPointer, "Section object pointer untouched\n");
247         ok(SectionObject != NULL, "Section object pointer NULL\n");
248         CheckObject(FileHandle2, PointerCount2, 1L);
249         CheckSection(SectionObject, 0);
250         TestMapView(SectionObject, TRUE, TRUE);
251 
252         if (SectionObject && SectionObject != KmtInvalidPointer)
253             ObDereferenceObject(SectionObject);
254 
255         /* image section with inappropriate file */
256         CheckObject(FileHandle1, PointerCount1, 1L);
257         SectionObject = KmtInvalidPointer;
258         MaximumSize.QuadPart = 1;
259         KmtStartSeh()
260             Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_IMAGE, FileHandle1, NULL);
261         KmtEndSeh(STATUS_SUCCESS);
262         ok_eq_hex(Status, STATUS_INVALID_IMAGE_NOT_MZ);
263         ok_eq_longlong(MaximumSize.QuadPart, 1LL);
264         ok_eq_pointer(SectionObject, KmtInvalidPointer);
265         CheckObject(FileHandle1, PointerCount1, 1L);
266 
267         if (SectionObject && SectionObject != KmtInvalidPointer)
268             ObDereferenceObject(SectionObject);
269 
270         CheckObject(FileHandle1, PointerCount1, 1L);
271         SectionObject = KmtInvalidPointer;
272         MaximumSize.QuadPart = 1;
273         KmtStartSeh()
274             Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_IMAGE, NULL, FileObject1);
275         KmtEndSeh(STATUS_SUCCESS);
276         ok_eq_hex(Status, STATUS_SUCCESS);
277         ok_eq_longlong(MaximumSize.QuadPart, 1LL);
278         ok(SectionObject != KmtInvalidPointer, "Section object pointer untouched\n");
279         ok(SectionObject != NULL, "Section object pointer NULL\n");
280         ++PointerCount1;
281         CheckObject(FileHandle1, PointerCount1, 1L);
282         CheckSection(SectionObject, 0);
283         TestMapView(SectionObject, TRUE, FALSE);
284 
285         if (SectionObject && SectionObject != KmtInvalidPointer)
286             ObDereferenceObject(SectionObject);
287         //--PointerCount1; // ????
288 
289         CheckObject(FileHandle1, PointerCount1, 1L);
290         SectionObject = KmtInvalidPointer;
291         MaximumSize.QuadPart = 1;
292         KmtStartSeh()
293             Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_IMAGE, FileHandle1, FileObject1);
294         KmtEndSeh(STATUS_SUCCESS);
295         ok_eq_hex(Status, STATUS_SUCCESS);
296         ok_eq_longlong(MaximumSize.QuadPart, 1LL);
297         ok(SectionObject != KmtInvalidPointer, "Section object pointer untouched\n");
298         ok(SectionObject != NULL, "Section object pointer NULL\n");
299         CheckObject(FileHandle1, PointerCount1, 1L);
300         CheckSection(SectionObject, 0);
301         TestMapView(SectionObject, TRUE, FALSE);
302 
303         if (SectionObject && SectionObject != KmtInvalidPointer)
304             ObDereferenceObject(SectionObject);
305 
306         /* image section with two different files */
307         CheckObject(FileHandle1, PointerCount1, 1L);
308         SectionObject = KmtInvalidPointer;
309         MaximumSize.QuadPart = 1;
310         KmtStartSeh()
311             Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_IMAGE, FileHandle1, FileObject2);
312         KmtEndSeh(STATUS_SUCCESS);
313         ok_eq_hex(Status, STATUS_SUCCESS);
314         ok_eq_longlong(MaximumSize.QuadPart, 1LL);
315         ok(SectionObject != KmtInvalidPointer, "Section object pointer untouched\n");
316         ok(SectionObject != NULL, "Section object pointer NULL\n");
317         CheckObject(FileHandle1, PointerCount1, 1L);
318         CheckObject(FileHandle2, PointerCount2, 1L);
319         CheckSection(SectionObject, 0);
320         TestMapView(SectionObject, TRUE, TRUE);
321 
322         if (SectionObject && SectionObject != KmtInvalidPointer)
323             ObDereferenceObject(SectionObject);
324 
325         CheckObject(FileHandle1, PointerCount1, 1L);
326         SectionObject = KmtInvalidPointer;
327         MaximumSize.QuadPart = 1;
328         KmtStartSeh()
329             Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_IMAGE, FileHandle2, FileObject1);
330         KmtEndSeh(STATUS_SUCCESS);
331         ok_eq_hex(Status, STATUS_SUCCESS);
332         ok_eq_longlong(MaximumSize.QuadPart, 1LL);
333         ok(SectionObject != KmtInvalidPointer, "Section object pointer untouched\n");
334         ok(SectionObject != NULL, "Section object pointer NULL\n");
335         CheckObject(FileHandle1, PointerCount1, 1L);
336         CheckObject(FileHandle2, PointerCount2, 1L);
337         CheckSection(SectionObject, 0);
338         TestMapView(SectionObject, TRUE, FALSE);
339 
340         if (SectionObject && SectionObject != KmtInvalidPointer)
341             ObDereferenceObject(SectionObject);
342 
343         /* data file section */
344         CheckObject(FileHandle1, PointerCount1, 1L);
345         SectionObject = KmtInvalidPointer;
346         MaximumSize.QuadPart = 1;
347         KmtStartSeh()
348             Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_RESERVE, FileHandle1, NULL);
349         KmtEndSeh(STATUS_SUCCESS);
350         ok_eq_hex(Status, STATUS_SUCCESS);
351         ok_eq_longlong(MaximumSize.QuadPart, 1LL);
352         ok(SectionObject != KmtInvalidPointer, "Section object pointer untouched\n");
353         ok(SectionObject != NULL, "Section object pointer NULL\n");
354         CheckObject(FileHandle1, PointerCount1, 1L);
355         CheckSection(SectionObject, 0);
356         TestMapView(SectionObject, TRUE, FALSE);
357 
358         if (SectionObject && SectionObject != KmtInvalidPointer)
359             ObDereferenceObject(SectionObject);
360 
361         CheckObject(FileHandle1, PointerCount1, 1L);
362         SectionObject = KmtInvalidPointer;
363         MaximumSize.QuadPart = 1;
364         KmtStartSeh()
365             Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_RESERVE, NULL, FileObject1);
366         KmtEndSeh(STATUS_SUCCESS);
367         ok_eq_hex(Status, STATUS_SUCCESS);
368         ok_eq_longlong(MaximumSize.QuadPart, 1LL);
369         ok(SectionObject != KmtInvalidPointer, "Section object pointer untouched\n");
370         ok(SectionObject != NULL, "Section object pointer NULL\n");
371         CheckObject(FileHandle1, PointerCount1, 1L);
372         CheckSection(SectionObject, 0);
373         TestMapView(SectionObject, TRUE, FALSE);
374 
375         if (SectionObject && SectionObject != KmtInvalidPointer)
376             ObDereferenceObject(SectionObject);
377 
378         CheckObject(FileHandle1, PointerCount1, 1L);
379         SectionObject = KmtInvalidPointer;
380         MaximumSize.QuadPart = 1;
381         KmtStartSeh()
382             Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_RESERVE, FileHandle1, FileObject1);
383         KmtEndSeh(STATUS_SUCCESS);
384         ok_eq_hex(Status, STATUS_SUCCESS);
385         ok_eq_longlong(MaximumSize.QuadPart, 1LL);
386         ok(SectionObject != KmtInvalidPointer, "Section object pointer untouched\n");
387         ok(SectionObject != NULL, "Section object pointer NULL\n");
388         CheckObject(FileHandle1, PointerCount1, 1L);
389         CheckSection(SectionObject, 0);
390         TestMapView(SectionObject, TRUE, FALSE);
391 
392         if (SectionObject && SectionObject != KmtInvalidPointer)
393             ObDereferenceObject(SectionObject);
394 
395         CheckObject(FileHandle1, PointerCount1, 1L);
396     }
397 }
398 
399 static
400 VOID
TestPhysicalMemorySection(VOID)401 TestPhysicalMemorySection(VOID)
402 {
403     NTSTATUS Status;
404     UNICODE_STRING SectionName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
405     OBJECT_ATTRIBUTES ObjectAttributes;
406     HANDLE SectionHandle;
407     PVOID SectionObject;
408     PUCHAR MyPage;
409     PHYSICAL_ADDRESS MyPagePhysical;
410     PUCHAR ZeroPageContents;
411     PHYSICAL_ADDRESS ZeroPagePhysical;
412     PHYSICAL_ADDRESS PhysicalAddress;
413     PVOID Mapping;
414     SYSTEM_BASIC_INFORMATION BasicInfo;
415     PUCHAR MappingBytes;
416     SIZE_T ViewSize;
417     SIZE_T EqualBytes;
418     struct
419     {
420         PVOID Mapping;
421         PHYSICAL_ADDRESS PhysicalAddress;
422         SIZE_T ViewSize;
423     } *UserStruct;
424     PVOID UserMem;
425     SIZE_T UserSize;
426 
427     MyPage = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, 'MPmK');
428     if (skip(MyPage != NULL, "Out of memory\n"))
429         return;
430     MyPagePhysical = MmGetPhysicalAddress(MyPage);
431     RtlFillMemory(MyPage + 0 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0x23);
432     RtlFillMemory(MyPage + 1 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0x67);
433     RtlFillMemory(MyPage + 2 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0xab);
434     RtlFillMemory(MyPage + 3 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0xef);
435 
436     ZeroPageContents = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, 'ZPmK');
437     if (skip(ZeroPageContents != NULL, "Out of memory\n"))
438     {
439         ExFreePoolWithTag(MyPage, 'MPmK');
440         return;
441     }
442     ZeroPagePhysical.QuadPart = 0;
443 
444     Mapping = MmMapIoSpace(ZeroPagePhysical, PAGE_SIZE, MmCached);
445     if (skip(Mapping != NULL, "Failed to map zero page\n"))
446     {
447         ExFreePoolWithTag(ZeroPageContents, 'ZPmK');
448         ExFreePoolWithTag(MyPage, 'MPmK');
449         return;
450     }
451 
452     RtlCopyMemory(ZeroPageContents, Mapping, PAGE_SIZE);
453     MmUnmapIoSpace(Mapping, PAGE_SIZE);
454 
455     InitializeObjectAttributes(&ObjectAttributes,
456                                &SectionName,
457                                0,
458                                NULL,
459                                NULL);
460     Status = ZwOpenSection(&SectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes);
461     ok_eq_hex(Status, STATUS_SUCCESS);
462     if (!skip(NT_SUCCESS(Status), "No section\n"))
463     {
464         /* Map zero page and compare */
465         Mapping = NULL;
466         ViewSize = PAGE_SIZE;
467         Status = ZwMapViewOfSection(SectionHandle,
468                                     ZwCurrentProcess(),
469                                     &Mapping,
470                                     0,
471                                     0,
472                                     &ZeroPagePhysical,
473                                     &ViewSize,
474                                     ViewUnmap,
475                                     0,
476                                     PAGE_READWRITE);
477         ok_eq_hex(Status, STATUS_SUCCESS);
478         if (!skip(NT_SUCCESS(Status), "No view\n"))
479         {
480             ok((LONG_PTR)Mapping > 0, "Mapping = %p\n", Mapping);
481             EqualBytes = RtlCompareMemory(Mapping,
482                                           ZeroPageContents,
483                                           PAGE_SIZE);
484             ok_eq_size(EqualBytes, PAGE_SIZE);
485             Status = ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping);
486             ok_eq_hex(Status, STATUS_SUCCESS);
487         }
488 
489         /* Map the zero page non-cached */
490         Mapping = NULL;
491         ViewSize = PAGE_SIZE;
492         Status = ZwMapViewOfSection(SectionHandle,
493                                     ZwCurrentProcess(),
494                                     &Mapping,
495                                     0,
496                                     0,
497                                     &ZeroPagePhysical,
498                                     &ViewSize,
499                                     ViewUnmap,
500                                     0,
501                                     PAGE_READWRITE | PAGE_NOCACHE);
502         ok_eq_hex(Status, STATUS_SUCCESS);
503         if (!skip(NT_SUCCESS(Status), "No view\n"))
504         {
505             ok((LONG_PTR)Mapping > 0, "Mapping = %p\n", Mapping);
506             EqualBytes = RtlCompareMemory(Mapping,
507                                           ZeroPageContents,
508                                           PAGE_SIZE);
509             ok_eq_size(EqualBytes, PAGE_SIZE);
510             Status = ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping);
511             ok_eq_hex(Status, STATUS_SUCCESS);
512         }
513 
514         /* Map our NP page, compare, and check that modifications are reflected */
515         Mapping = NULL;
516         ViewSize = PAGE_SIZE;
517         Status = ZwMapViewOfSection(SectionHandle,
518                                     ZwCurrentProcess(),
519                                     &Mapping,
520                                     0,
521                                     0,
522                                     &MyPagePhysical,
523                                     &ViewSize,
524                                     ViewUnmap,
525                                     0,
526                                     PAGE_READWRITE);
527         ok_eq_hex(Status, STATUS_SUCCESS);
528         if (!skip(NT_SUCCESS(Status), "No view\n"))
529         {
530             ok((LONG_PTR)Mapping > 0, "Mapping = %p\n", Mapping);
531             EqualBytes = RtlCompareMemory(Mapping,
532                                           MyPage,
533                                           PAGE_SIZE);
534             ok_eq_size(EqualBytes, PAGE_SIZE);
535 
536             MappingBytes = Mapping;
537             ok(MappingBytes[5] == 0x23, "Mapping[5] = 0x%x\n", MappingBytes[5]);
538             ok(MyPage[5] == 0x23, "MyPage[5] = 0x%x\n", MyPage[5]);
539 
540             MyPage[5] = 0x44;
541             ok(MappingBytes[5] == 0x44, "Mapping[5] = 0x%x\n", MappingBytes[5]);
542             ok(MyPage[5] == 0x44, "MyPage[5] = 0x%x\n", MyPage[5]);
543 
544             MappingBytes[5] = 0x88;
545             ok(MappingBytes[5] == 0x88, "Mapping[5] = 0x%x\n", MappingBytes[5]);
546             ok(MyPage[5] == 0x88, "MyPage[5] = 0x%x\n", MyPage[5]);
547 
548             Status = ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping);
549             ok_eq_hex(Status, STATUS_SUCCESS);
550         }
551 
552         /* Unaligned mapping will get aligned automatically */
553         Mapping = NULL;
554         ViewSize = PAGE_SIZE - 4;
555         PhysicalAddress.QuadPart = MyPagePhysical.QuadPart + 4;
556         Status = ZwMapViewOfSection(SectionHandle,
557                                     ZwCurrentProcess(),
558                                     &Mapping,
559                                     0,
560                                     0,
561                                     &PhysicalAddress,
562                                     &ViewSize,
563                                     ViewUnmap,
564                                     0,
565                                     PAGE_READWRITE);
566         ok_eq_hex(Status, STATUS_SUCCESS);
567         if (!skip(NT_SUCCESS(Status), "No view\n"))
568         {
569             ok((LONG_PTR)Mapping > 0, "Mapping = %p\n", Mapping);
570             ok(((ULONG_PTR)Mapping % PAGE_SIZE) == 0, "Mapping = %p\n", Mapping);
571             ok_eq_ulong(ViewSize, PAGE_SIZE);
572 
573             EqualBytes = RtlCompareMemory(Mapping,
574                                           MyPage,
575                                           PAGE_SIZE);
576             ok_eq_size(EqualBytes, PAGE_SIZE);
577 
578             Status = ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping);
579             ok_eq_hex(Status, STATUS_SUCCESS);
580         }
581 
582         /* The following tests need to pass parameters in user mode */
583         UserStruct = NULL;
584         UserMem = NULL;
585         UserSize = PAGE_SIZE;
586         Status = ZwAllocateVirtualMemory(ZwCurrentProcess(),
587                                          &UserMem,
588                                          0,
589                                          &UserSize,
590                                          MEM_COMMIT,
591                                          PAGE_READWRITE);
592         ok_eq_hex(Status, STATUS_SUCCESS);
593         if (NT_SUCCESS(Status))
594             UserStruct = UserMem;
595 
596         /* Find highest physical page -- only kernel can map beyond this */
597         Status = ZwQuerySystemInformation(SystemBasicInformation,
598                                           &BasicInfo,
599                                           sizeof(BasicInfo),
600                                           NULL);
601         ok_eq_hex(Status, STATUS_SUCCESS);
602         trace("HighestPhysicalPageNumber: %lx\n", BasicInfo.HighestPhysicalPageNumber);
603 
604         /* Start one page before highest physical -- succeeds for user/kernel */
605         Mapping = NULL;
606         ViewSize = PAGE_SIZE;
607         PhysicalAddress.QuadPart = (ULONGLONG)(BasicInfo.HighestPhysicalPageNumber - 1) << PAGE_SHIFT;
608         Status = ZwMapViewOfSection(SectionHandle,
609                                     ZwCurrentProcess(),
610                                     &Mapping,
611                                     0,
612                                     0,
613                                     &PhysicalAddress,
614                                     &ViewSize,
615                                     ViewUnmap,
616                                     0,
617                                     PAGE_READWRITE);
618         ok_eq_hex(Status, STATUS_SUCCESS);
619         if (NT_SUCCESS(Status))
620             ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping);
621 
622         /* Repeat from user mode */
623         if (!skip(UserStruct != NULL, "No user memory\n"))
624         {
625             KmtStartSeh()
626                 UserStruct->Mapping = NULL;
627                 UserStruct->PhysicalAddress.QuadPart = PhysicalAddress.QuadPart;
628                 UserStruct->ViewSize = PAGE_SIZE;
629             KmtEndSeh(STATUS_SUCCESS);
630 
631             Status = NtMapViewOfSection(SectionHandle,
632                                         NtCurrentProcess(),
633                                         &UserStruct->Mapping,
634                                         0,
635                                         0,
636                                         &UserStruct->PhysicalAddress,
637                                         &UserStruct->ViewSize,
638                                         ViewUnmap,
639                                         0,
640                                         PAGE_READWRITE);
641             ok_eq_hex(Status, STATUS_SUCCESS);
642             if (NT_SUCCESS(Status))
643             {
644                 KmtStartSeh()
645                     ZwUnmapViewOfSection(ZwCurrentProcess(), UserStruct->Mapping);
646                 KmtEndSeh(STATUS_SUCCESS);
647             }
648         }
649 
650         /* Now start at highest physical -- fails for user */
651         Mapping = NULL;
652         ViewSize = PAGE_SIZE;
653         PhysicalAddress.QuadPart = (ULONGLONG)BasicInfo.HighestPhysicalPageNumber << PAGE_SHIFT;
654         Status = ZwMapViewOfSection(SectionHandle,
655                                     ZwCurrentProcess(),
656                                     &Mapping,
657                                     0,
658                                     0,
659                                     &PhysicalAddress,
660                                     &ViewSize,
661                                     ViewUnmap,
662                                     0,
663                                     PAGE_READWRITE);
664         ok_eq_hex(Status, STATUS_SUCCESS);
665         if (NT_SUCCESS(Status))
666             ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping);
667 
668         /* Repeat from user mode */
669         if (!skip(UserStruct != NULL, "No user memory\n"))
670         {
671             KmtStartSeh()
672                 UserStruct->Mapping = NULL;
673                 UserStruct->PhysicalAddress.QuadPart = PhysicalAddress.QuadPart;
674                 UserStruct->ViewSize = PAGE_SIZE;
675             KmtEndSeh(STATUS_SUCCESS);
676 
677             Status = NtMapViewOfSection(SectionHandle,
678                                         NtCurrentProcess(),
679                                         &UserStruct->Mapping,
680                                         0,
681                                         0,
682                                         &UserStruct->PhysicalAddress,
683                                         &UserStruct->ViewSize,
684                                         ViewUnmap,
685                                         0,
686                                         PAGE_READWRITE);
687             ok_eq_hex(Status, STATUS_INVALID_PARAMETER_6);
688             if (NT_SUCCESS(Status))
689             {
690                 KmtStartSeh()
691                     ZwUnmapViewOfSection(ZwCurrentProcess(), UserStruct->Mapping);
692                 KmtEndSeh(STATUS_SUCCESS);
693             }
694         }
695 
696         /* End of view crosses highest physical -- fails for user */
697         Mapping = NULL;
698         ViewSize = 2 * PAGE_SIZE;
699         PhysicalAddress.QuadPart = (ULONGLONG)(BasicInfo.HighestPhysicalPageNumber - 1) << PAGE_SHIFT;
700         Status = ZwMapViewOfSection(SectionHandle,
701                                     ZwCurrentProcess(),
702                                     &Mapping,
703                                     0,
704                                     0,
705                                     &PhysicalAddress,
706                                     &ViewSize,
707                                     ViewUnmap,
708                                     0,
709                                     PAGE_READWRITE);
710         ok_eq_hex(Status, STATUS_SUCCESS);
711         if (NT_SUCCESS(Status))
712             ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping);
713 
714         /* Repeat from user mode */
715         if (!skip(UserStruct != NULL, "No user memory\n"))
716         {
717             KmtStartSeh()
718                 UserStruct->Mapping = NULL;
719                 UserStruct->PhysicalAddress.QuadPart = PhysicalAddress.QuadPart;
720                 UserStruct->ViewSize = 2 * PAGE_SIZE;
721             KmtEndSeh(STATUS_SUCCESS);
722 
723             Status = NtMapViewOfSection(SectionHandle,
724                                         NtCurrentProcess(),
725                                         &UserStruct->Mapping,
726                                         0,
727                                         0,
728                                         &UserStruct->PhysicalAddress,
729                                         &UserStruct->ViewSize,
730                                         ViewUnmap,
731                                         0,
732                                         PAGE_READWRITE);
733             ok_eq_hex(Status, STATUS_INVALID_PARAMETER_6);
734             if (NT_SUCCESS(Status))
735             {
736                 KmtStartSeh()
737                     ZwUnmapViewOfSection(ZwCurrentProcess(), UserStruct->Mapping);
738                 KmtEndSeh(STATUS_SUCCESS);
739             }
740         }
741 
742         /* Free user memory and close section */
743         if (!skip(UserStruct != NULL, "No user memory\n"))
744         {
745             UserSize = 0;
746             Status = ZwFreeVirtualMemory(ZwCurrentProcess(),
747                                          &UserMem,
748                                          &UserSize,
749                                          MEM_RELEASE);
750             ok_eq_hex(Status, STATUS_SUCCESS);
751         }
752 
753         Status = ObCloseHandle(SectionHandle, UserMode);
754         ok_eq_hex(Status, STATUS_SUCCESS);
755     }
756 
757     /* Try flag 0x80000000, which ROS calls SEC_PHYSICALMEMORY */
758     InitializeObjectAttributes(&ObjectAttributes,
759                                NULL,
760                                OBJ_KERNEL_HANDLE,
761                                NULL,
762                                NULL);
763     Status = ZwCreateSection(&SectionHandle,
764                              SECTION_ALL_ACCESS,
765                              &ObjectAttributes,
766                              NULL,
767                              PAGE_READWRITE,
768                              0x80000000,
769                              NULL);
770     ok_eq_hex(Status, STATUS_INVALID_PARAMETER_6);
771     if (NT_SUCCESS(Status))
772         ZwClose(SectionHandle);
773 
774     /* Assertion failure: AllocationAttributes & SEC_IMAGE | SEC_RESERVE | SEC_COMMIT */
775     if (!KmtIsCheckedBuild)
776     {
777     InitializeObjectAttributes(&ObjectAttributes,
778                                NULL,
779                                OBJ_KERNEL_HANDLE,
780                                NULL,
781                                NULL);
782     Status = MmCreateSection(&SectionObject,
783                              SECTION_ALL_ACCESS,
784                              &ObjectAttributes,
785                              NULL,
786                              PAGE_READWRITE,
787                              0x80000000,
788                              NULL,
789                              NULL);
790     ok_eq_hex(Status, STATUS_INVALID_PARAMETER_6);
791     if (NT_SUCCESS(Status))
792         ObDereferenceObject(SectionObject);
793     }
794 
795     InitializeObjectAttributes(&ObjectAttributes,
796                                NULL,
797                                OBJ_KERNEL_HANDLE,
798                                NULL,
799                                NULL);
800     Status = MmCreateSection(&SectionObject,
801                              SECTION_ALL_ACCESS,
802                              &ObjectAttributes,
803                              NULL,
804                              PAGE_READWRITE,
805                              SEC_RESERVE | 0x80000000,
806                              NULL,
807                              NULL);
808     ok_eq_hex(Status, STATUS_INVALID_PARAMETER_6);
809     if (NT_SUCCESS(Status))
810         ObDereferenceObject(SectionObject);
811 
812     ExFreePoolWithTag(ZeroPageContents, 'ZPmK');
813     ExFreePoolWithTag(MyPage, 'MPmK');
814 }
815 
START_TEST(MmSection)816 START_TEST(MmSection)
817 {
818     NTSTATUS Status;
819     HANDLE FileHandle1 = NULL, FileHandle2 = NULL;
820     PFILE_OBJECT FileObject1 = NULL, FileObject2 = NULL;
821     OBJECT_ATTRIBUTES ObjectAttributes;
822     IO_STATUS_BLOCK IoStatusBlock;
823     UNICODE_STRING FileName1 = RTL_CONSTANT_STRING(L"\\SystemRoot\\kmtest-MmSection.txt");
824     UNICODE_STRING FileName2 = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntdll.dll");
825     LARGE_INTEGER FileOffset;
826     UCHAR FileData = 0;
827 
828     ok(ExGetPreviousMode() == UserMode, "Previous mode is kernel mode\n");
829     /* create a one-byte file that we can use */
830     InitializeObjectAttributes(&ObjectAttributes, &FileName1, OBJ_CASE_INSENSITIVE, NULL, NULL);
831     Status = ZwCreateFile(&FileHandle1, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_SUPERSEDE, FILE_NON_DIRECTORY_FILE, NULL, 0);
832     ok_eq_hex(Status, STATUS_SUCCESS);
833     ok_eq_ulongptr(IoStatusBlock.Information, FILE_CREATED);
834     ok(FileHandle1 != NULL, "FileHandle1 is NULL\n");
835     if (FileHandle1)
836     {
837         FileOffset.QuadPart = 0;
838         Status = ZwWriteFile(FileHandle1, NULL, NULL, NULL, &IoStatusBlock, &FileData, sizeof FileData, &FileOffset, NULL);
839         ok(Status == STATUS_SUCCESS || Status == STATUS_PENDING, "Status = 0x%08lx\n", Status);
840         Status = ZwWaitForSingleObject(FileHandle1, FALSE, NULL);
841         ok_eq_hex(Status, STATUS_SUCCESS);
842         ok_eq_ulongptr(IoStatusBlock.Information, 1);
843         Status = ZwClose(FileHandle1);
844         ok_eq_hex(Status, STATUS_SUCCESS);
845         FileHandle1 = NULL;
846     }
847 
848     InitializeObjectAttributes(&ObjectAttributes, &FileName1, OBJ_CASE_INSENSITIVE, NULL, NULL);
849     Status = ZwCreateFile(&FileHandle1, GENERIC_ALL, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, 0);
850     ok_eq_hex(Status, STATUS_SUCCESS);
851     ok_eq_ulongptr(IoStatusBlock.Information, FILE_OPENED);
852     ok(FileHandle1 != NULL, "FileHandle1 is NULL\n");
853     CheckObject(FileHandle1, 2L, 1L);
854 
855     InitializeObjectAttributes(&ObjectAttributes, &FileName2, OBJ_CASE_INSENSITIVE, NULL, NULL);
856     Status = ZwCreateFile(&FileHandle2, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0);
857     ok_eq_hex(Status, STATUS_SUCCESS);
858     ok_eq_ulongptr(IoStatusBlock.Information, FILE_OPENED);
859     ok(FileHandle2 != NULL, "FileHandle2 is NULL\n");
860 
861     if (!skip(Status == STATUS_SUCCESS && FileHandle1 != NULL, "Failed to open file 1\n"))
862     {
863         Status = ObReferenceObjectByHandle(FileHandle1, FILE_READ_DATA | FILE_WRITE_DATA, *IoFileObjectType, KernelMode, (PVOID *)&FileObject1, NULL);
864         ok_eq_hex(Status, STATUS_SUCCESS);
865         ok(FileObject1 != NULL, "FileObject1 is NULL\n");
866         CheckObject(FileHandle1, 3L, 1L);
867     }
868 
869     if (!skip(Status == STATUS_SUCCESS && FileHandle2 != NULL, "Failed to open file 2\n"))
870     {
871         Status = ObReferenceObjectByHandle(FileHandle2, FILE_READ_DATA | FILE_WRITE_DATA, *IoFileObjectType, KernelMode, (PVOID *)&FileObject2, NULL);
872         ok_eq_hex(Status, STATUS_SUCCESS);
873         ok(FileObject2 != NULL, "FileObject2 is NULL\n");
874     }
875 
876     trace("FileHandle1=%p, FileObject1=%p\n", FileHandle1, FileObject1);
877     trace("FileHandle2=%p, FileObject2=%p\n", FileHandle2, FileObject2);
878     TestCreateSection(FileHandle1, FileObject1, FileHandle2, FileObject2);
879 
880     if (FileObject2)
881         ObDereferenceObject(FileObject2);
882     if (FileObject1)
883         ObDereferenceObject(FileObject1);
884     if (FileHandle2)
885         ZwClose(FileHandle2);
886     if (FileHandle1)
887         ZwClose(FileHandle1);
888 
889     TestPhysicalMemorySection();
890 }
891