92e2747700d5bf6b701f96d8bb5862caf8ee6dab
[reactos.git] / rostests / kmtests / ntos_mm / MmSection.c
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
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
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
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 }