[USP10_WINETEST] Sync with Wine Staging 2.9. CORE-13362
[reactos.git] / rostests / kmtests / ntos_mm / ZwMapViewOfSection.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite ZwMapViewOfSection
5 * PROGRAMMER: Nikolay Borisov <nib9@aber.ac.uk>
6 */
7
8 #include <kmt_test.h>
9
10 #define IGNORE -99
11 #define NEW_CONTENT "NewContent"
12 #define NEW_CONTENT_LEN sizeof(NEW_CONTENT)
13
14 static UNICODE_STRING FileReadOnlyPath = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntdll.dll");
15 static UNICODE_STRING NtosImgPath = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntoskrnl.exe");
16 static UNICODE_STRING WritableFilePath = RTL_CONSTANT_STRING(L"\\SystemRoot\\kmtest-MmSection.txt");
17 static UNICODE_STRING SharedSectionName = RTL_CONSTANT_STRING(L"\\BaseNamedObjects\\kmtest-SharedSection");
18 extern const char TestString[];
19 extern const ULONG TestStringSize;
20 static OBJECT_ATTRIBUTES NtdllObject;
21 static OBJECT_ATTRIBUTES KmtestFileObject;
22 static OBJECT_ATTRIBUTES NtoskrnlFileObject;
23
24 #define TestMapView(SectionHandle, ProcessHandle, BaseAddress2, ZeroBits, CommitSize, SectionOffset, ViewSize2, InheritDisposition, AllocationType, Win32Protect, MapStatus, UnmapStatus) do \
25 { \
26 Status = ZwMapViewOfSection(SectionHandle, ProcessHandle, BaseAddress2, ZeroBits, CommitSize, SectionOffset, ViewSize2, InheritDisposition, AllocationType, Win32Protect); \
27 ok_eq_hex(Status, MapStatus); \
28 if (NT_SUCCESS(Status)) \
29 { \
30 Status = ZwUnmapViewOfSection(ProcessHandle, BaseAddress); \
31 if (UnmapStatus != IGNORE) ok_eq_hex(Status, UnmapStatus); \
32 *BaseAddress2 = NULL; \
33 *ViewSize2 = 0; \
34 } \
35 } while (0) \
36
37 #define MmTestMapView(Object, ProcessHandle, BaseAddress2, ZeroBits, CommitSize, SectionOffset, ViewSize2, InheritDisposition, AllocationType, Win32Protect, MapStatus, UnmapStatus) do \
38 { \
39 Status = MmMapViewOfSection(Object, ProcessHandle, BaseAddress2, ZeroBits, CommitSize, SectionOffset, ViewSize2, InheritDisposition, AllocationType, Win32Protect); \
40 ok_eq_hex(Status, MapStatus); \
41 if (NT_SUCCESS(Status)) \
42 { \
43 Status = MmUnmapViewOfSection(ProcessHandle, BaseAddress); \
44 if (UnmapStatus != IGNORE) ok_eq_hex(Status, UnmapStatus); \
45 *BaseAddress2 = NULL; \
46 *ViewSize2 = 0; \
47 } \
48 } while (0) \
49
50 #define CheckObject(Handle, Pointers, Handles) do \
51 { \
52 PUBLIC_OBJECT_BASIC_INFORMATION ObjectInfo; \
53 Status = ZwQueryObject(Handle, ObjectBasicInformation, \
54 &ObjectInfo, sizeof ObjectInfo, NULL); \
55 ok_eq_hex(Status, STATUS_SUCCESS); \
56 ok_eq_ulong(ObjectInfo.PointerCount, Pointers); \
57 ok_eq_ulong(ObjectInfo.HandleCount, Handles); \
58 } while (0) \
59
60 static
61 VOID
62 KmtInitTestFiles(PHANDLE ReadOnlyFile, PHANDLE WriteOnlyFile, PHANDLE ExecutableFile)
63 {
64 NTSTATUS Status;
65 LARGE_INTEGER FileOffset;
66 IO_STATUS_BLOCK IoStatusBlock;
67
68 //INIT THE READ-ONLY FILE
69 Status = ZwCreateFile(ReadOnlyFile, GENERIC_READ, &NtdllObject, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0);
70 ok_eq_hex(Status, STATUS_SUCCESS);
71 ok(*ReadOnlyFile != NULL, "Couldn't acquire READONLY handle\n");
72
73 //INIT THE EXECUTABLE FILE
74 Status = ZwCreateFile(ExecutableFile, GENERIC_EXECUTE, &NtdllObject, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0);
75 ok_eq_hex(Status, STATUS_SUCCESS);
76 ok(*ExecutableFile != NULL, "Couldn't acquire EXECUTE handle\n");
77
78 //INIT THE WRITE-ONLY FILE
79 //TODO: Delete the file when the tests are all executed
80 Status = ZwCreateFile(WriteOnlyFile, (GENERIC_WRITE | SYNCHRONIZE), &KmtestFileObject, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_SUPERSEDE, (FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE), NULL, 0);
81 ok_eq_hex(Status, STATUS_SUCCESS);
82 ok_eq_ulongptr(IoStatusBlock.Information, FILE_CREATED);
83 ok(*WriteOnlyFile != NULL, "WriteOnlyFile is NULL\n");
84 if (!skip(*WriteOnlyFile != NULL, "No WriteOnlyFile\n"))
85 {
86 FileOffset.QuadPart = 0;
87 Status = ZwWriteFile(*WriteOnlyFile, NULL, NULL, NULL, &IoStatusBlock, (PVOID)TestString, TestStringSize, &FileOffset, NULL);
88 ok(Status == STATUS_SUCCESS || Status == STATUS_PENDING, "Status = 0x%08lx\n", Status);
89 Status = ZwWaitForSingleObject(*WriteOnlyFile, FALSE, NULL);
90 ok_eq_hex(Status, STATUS_SUCCESS);
91 ok_eq_ulongptr(IoStatusBlock.Information, TestStringSize);
92 }
93 }
94
95 static
96 VOID
97 SimpleErrorChecks(HANDLE FileHandleReadOnly, HANDLE FileHandleWriteOnly, HANDLE ExecutableImg)
98 {
99 NTSTATUS Status;
100 HANDLE WriteSectionHandle;
101 HANDLE ReadOnlySection;
102 HANDLE PageFileSectionHandle;
103 LARGE_INTEGER MaximumSize;
104 LARGE_INTEGER SectionOffset;
105 SIZE_T AllocSize = TestStringSize;
106 SIZE_T ViewSize = 0;
107 PVOID BaseAddress = NULL;
108 PVOID AllocBase = NULL;
109 MaximumSize.QuadPart = TestStringSize;
110
111 //Used for parameters working on file-based section
112 Status = ZwCreateSection(&WriteSectionHandle, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, FileHandleWriteOnly);
113 ok_eq_hex(Status, STATUS_SUCCESS);
114
115 Status = ZwCreateSection(&ReadOnlySection, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_READONLY, SEC_COMMIT, FileHandleReadOnly);
116 ok_eq_hex(Status, STATUS_SUCCESS);
117
118 //Used for parameters taking effect only on page-file backed section
119 MaximumSize.QuadPart = 5 * MM_ALLOCATION_GRANULARITY;
120 Status = ZwCreateSection(&PageFileSectionHandle, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, NULL);
121 ok_eq_hex(Status, STATUS_SUCCESS);
122
123 MaximumSize.QuadPart = TestStringSize;
124
125 //section handle
126 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
127 TestMapView((HANDLE)0xDEADBEEF, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE);
128 TestMapView(INVALID_HANDLE_VALUE, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_OBJECT_TYPE_MISMATCH, IGNORE);
129 TestMapView(NULL, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE);
130
131 //process handle
132 TestMapView(WriteSectionHandle, (HANDLE)0xDEADBEEF, &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE);
133 TestMapView(WriteSectionHandle, (HANDLE)NULL, &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE);
134
135 //base address
136 BaseAddress = (PVOID)0x00567A20;
137 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_MAPPED_ALIGNMENT, IGNORE);
138
139 BaseAddress = (PVOID) 0x60000000;
140 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
141
142 BaseAddress = (PVOID)((char *)MmSystemRangeStart + 200);
143 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_3, IGNORE);
144
145 //invalid section handle AND unaligned base address
146 BaseAddress = (PVOID)0x00567A20;
147 TestMapView((HANDLE)0xDEADBEEF, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE);
148
149 //invalid process handle AND unaligned base address
150 BaseAddress = (PVOID)0x00567A20;
151 TestMapView(WriteSectionHandle, (HANDLE)0xDEADBEEF, &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE);
152
153 //try mapping section to an already mapped address
154 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &AllocBase, 0, &AllocSize, MEM_COMMIT, PAGE_READWRITE);
155 if (!skip(NT_SUCCESS(Status), "Cannot allocate memory\n"))
156 {
157 BaseAddress = AllocBase;
158 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_CONFLICTING_ADDRESSES, IGNORE);
159 Status = ZwFreeVirtualMemory(NtCurrentProcess(), &AllocBase, &AllocSize, MEM_RELEASE);
160 ok_eq_hex(Status, STATUS_SUCCESS);
161 }
162
163 //zero bits
164 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 1, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
165 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 5, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
166 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, -1, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_4, IGNORE);
167 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 20, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_NO_MEMORY, IGNORE);
168 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 21, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_NO_MEMORY, IGNORE);
169 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 22, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_4, IGNORE);
170
171 //commit size
172 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 500, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
173 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
174 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, -1, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, IGNORE);
175 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0x10000000, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, IGNORE);
176 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 500, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, IGNORE);
177 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 500, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
178
179 //section offset
180 SectionOffset.QuadPart = 0;
181 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
182 ok_eq_ulonglong(SectionOffset.QuadPart, 0);
183
184 SectionOffset.QuadPart = 0x00040211; //MSDN is wrong, in w2k3 the ZwMapViewOfSection doesn't align offsets automatically
185 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 500, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_MAPPED_ALIGNMENT, IGNORE);
186
187 SectionOffset.QuadPart = -1;
188 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_MAPPED_ALIGNMENT, IGNORE);
189
190 //View Size
191 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
192
193 ViewSize = -1;
194 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_3, IGNORE);
195
196 ViewSize = TestStringSize+1;
197 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_VIEW_SIZE, IGNORE);
198 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
199
200 ViewSize = TestStringSize;
201 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
202
203 ViewSize = TestStringSize-1;
204 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
205
206 //allocation type
207 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
208 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE, STATUS_INVALID_PARAMETER_9, STATUS_SUCCESS);
209 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE, STATUS_INVALID_PARAMETER_9, IGNORE);
210 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, (MEM_LARGE_PAGES | MEM_RESERVE), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
211
212 //win32protect
213 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READONLY, STATUS_SUCCESS, STATUS_SUCCESS);
214 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_NOACCESS, STATUS_SUCCESS, STATUS_SUCCESS);
215 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_EXECUTE_WRITECOPY, STATUS_SECTION_PROTECTION, IGNORE);
216 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SECTION_PROTECTION, IGNORE);
217 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_WRITECOPY, STATUS_SUCCESS, STATUS_SUCCESS);
218 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_EXECUTE_READ, STATUS_SECTION_PROTECTION, IGNORE);
219 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_EXECUTE, STATUS_SECTION_PROTECTION, IGNORE);
220 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READONLY, STATUS_SUCCESS, STATUS_SUCCESS);
221 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_NOACCESS, STATUS_SUCCESS, STATUS_SUCCESS);
222 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, (PAGE_READWRITE | PAGE_READONLY), STATUS_INVALID_PAGE_PROTECTION, IGNORE);
223 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READONLY, STATUS_SECTION_PROTECTION, IGNORE);
224
225 ZwClose(WriteSectionHandle);
226 ZwClose(PageFileSectionHandle);
227 ZwClose(ReadOnlySection);
228 }
229
230
231 static
232 VOID
233 AdvancedErrorChecks(HANDLE FileHandleReadOnly, HANDLE FileHandleWriteOnly)
234 {
235 NTSTATUS Status;
236 PVOID BaseAddress;
237 HANDLE FileSectionHandle;
238 LARGE_INTEGER SectionOffset;
239 LARGE_INTEGER MaximumSize;
240 SIZE_T ViewSize = 0;
241 PVOID SectionObject;
242
243 MaximumSize.QuadPart = TestStringSize;
244 //Used for parameters working on file-based section
245 Status = ZwCreateSection(&FileSectionHandle, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, FileHandleWriteOnly);
246 ok_eq_hex(Status, STATUS_SUCCESS);
247
248 Status = ObReferenceObjectByHandle(FileSectionHandle,
249 STANDARD_RIGHTS_ALL,
250 NULL,
251 KernelMode,
252 &SectionObject,
253 NULL);
254
255 ok_eq_hex(Status, STATUS_SUCCESS);
256
257 //Bypassing Zw function calls mean bypassing the alignment checks which are not crucial for the branches being tested here
258
259 //test first conditional branch
260 ViewSize = -1;
261 MmTestMapView(SectionObject, PsGetCurrentProcess(), &BaseAddress, 0, TestStringSize, &SectionOffset, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE, STATUS_INVALID_VIEW_SIZE, IGNORE);
262
263 //test second conditional branch
264 ViewSize = 1;
265 SectionOffset.QuadPart = TestStringSize;
266 MmTestMapView(SectionObject, PsGetCurrentProcess(), &BaseAddress, 0, TestStringSize, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_VIEW_SIZE, IGNORE);
267
268 ObDereferenceObject(SectionObject);
269 ZwClose(FileSectionHandle);
270 }
271
272 static
273 SIZE_T
274 CompareFileContents(HANDLE FileHandle, ULONG BufferLength, PVOID Buffer)
275 {
276 NTSTATUS Status;
277 LARGE_INTEGER ByteOffset;
278 IO_STATUS_BLOCK IoStatusBlock;
279 PVOID FileContent;
280 SIZE_T Match;
281
282 Match = 0;
283 ByteOffset.QuadPart = 0;
284
285 FileContent = ExAllocatePoolWithTag(PagedPool, BufferLength, 'Test');
286 if (!skip((FileContent != NULL), "Error allocating memory for FileContent\n"))
287 {
288 Status = ZwReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, FileContent, BufferLength, &ByteOffset, NULL);
289 ok_eq_hex(Status, STATUS_SUCCESS);
290 ok_eq_ulongptr(IoStatusBlock.Information, BufferLength);
291
292 Match = 0;
293 Match = RtlCompareMemory(FileContent, Buffer, BufferLength);
294 ExFreePoolWithTag(FileContent, 'Test');
295 }
296
297 return Match;
298 }
299
300
301 static
302 VOID
303 NTAPI
304 SystemProcessWorker(PVOID StartContext)
305 {
306 NTSTATUS Status;
307 PVOID BaseAddress;
308 HANDLE SectionHandle;
309 SIZE_T ViewSize;
310 SIZE_T Match;
311 LARGE_INTEGER SectionOffset;
312 OBJECT_ATTRIBUTES ObjectAttributes;
313
314 UNREFERENCED_PARAMETER(StartContext);
315
316 BaseAddress = NULL;
317 ViewSize = TestStringSize;
318 SectionOffset.QuadPart = 0;
319
320 InitializeObjectAttributes(&ObjectAttributes, &SharedSectionName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
321 Status = ZwOpenSection(&SectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes);
322 if (!skip(NT_SUCCESS(Status), "Error acquiring handle to section. Error = %p\n", Status))
323 {
324 CheckObject(SectionHandle, 4, 2);
325 Status = ZwMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0, TestStringSize, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE);
326
327 //make sure ZwMapViewofSection doesn't touch the section ref counts.
328 CheckObject(SectionHandle, 4, 2);
329
330 if (!skip(NT_SUCCESS(Status), "Error mapping page file view in system process. Error = %p\n", Status))
331 {
332 Match = RtlCompareMemory(BaseAddress, TestString, TestStringSize);
333 ok_eq_size(Match, TestStringSize);
334
335 RtlCopyMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN);
336 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
337
338 //make sure ZwMapViewofSection doesn't touch the section ref counts.
339 CheckObject(SectionHandle, 4, 2);
340 }
341
342 ZwClose(SectionHandle);
343 }
344
345 PsTerminateSystemThread(STATUS_SUCCESS);
346 }
347
348
349 static
350 VOID
351 BehaviorChecks(HANDLE FileHandleReadOnly, HANDLE FileHandleWriteOnly)
352 {
353 NTSTATUS Status;
354 PVOID BaseAddress = NULL;
355 PVOID ThreadObject;
356 HANDLE WriteSectionHandle;
357 HANDLE SysThreadHandle;
358 OBJECT_ATTRIBUTES ObjectAttributes;
359 LARGE_INTEGER SectionOffset;
360 LARGE_INTEGER MaximumSize;
361 SIZE_T Match;
362 SIZE_T ViewSize = 0;
363
364 InitializeObjectAttributes(&ObjectAttributes, &SharedSectionName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
365 MaximumSize.QuadPart = TestStringSize;
366 SectionOffset.QuadPart = 0;
367
368 Status = ZwCreateSection(&WriteSectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, FileHandleWriteOnly);
369 CheckObject(WriteSectionHandle, 3, 1);
370 ok(NT_SUCCESS(Status), "Error creating write section from file. Error = %p\n", Status);
371
372 //check for section reading/writing by comparing section content to a well-known value.
373 Status = ZwMapViewOfSection(WriteSectionHandle, NtCurrentProcess() ,&BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE);
374 CheckObject(WriteSectionHandle, 3, 1);
375 if (!skip(NT_SUCCESS(Status), "Error mapping view with READ/WRITE priv. Error = %p\n", Status))
376 {
377 Match = RtlCompareMemory(BaseAddress, TestString, TestStringSize);
378 ok_eq_size(Match, TestStringSize);
379
380 //now check writing to section
381 RtlCopyMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN);
382
383 Match = RtlCompareMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN);
384 ok_eq_size(Match, NEW_CONTENT_LEN);
385
386 //check to see if the contents have been flushed to the actual file on disk.
387 Match = CompareFileContents(FileHandleWriteOnly, NEW_CONTENT_LEN, NEW_CONTENT);
388 ok_eq_size(Match, NEW_CONTENT_LEN);
389
390 //bring everything back to normal
391 RtlCopyMemory(BaseAddress, TestString, TestStringSize);
392
393 //Initiate an external thread to modify the file
394 InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
395 Status = PsCreateSystemThread(&SysThreadHandle, STANDARD_RIGHTS_ALL, &ObjectAttributes, NULL, NULL, SystemProcessWorker, NULL);
396 if (!skip(NT_SUCCESS(Status), "Error creating System thread. Error = %p\n", Status))
397 {
398 Status = ObReferenceObjectByHandle(SysThreadHandle, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &ThreadObject, NULL);
399 if (!skip(NT_SUCCESS(Status), "Error getting reference to System thread when testing file-backed section\n"))
400 {
401 //wait until the system thread actually terminates
402 KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, NULL);
403
404 //no longer need the thread object
405 ObDereferenceObject(ThreadObject);
406
407 //test for bi-directional access to the shared page file
408 Match = RtlCompareMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN);
409 ok_eq_size(Match, NEW_CONTENT_LEN);
410
411 //bring everything back to normal, again
412 RtlCopyMemory(BaseAddress, TestString, TestStringSize);
413 }
414 }
415
416 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
417 }
418
419 //Try to write to read-only mapped view
420 BaseAddress = NULL;
421 ViewSize = 0;
422 SectionOffset.QuadPart = 0;
423 Status = ZwMapViewOfSection(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READONLY);
424 if (!skip(NT_SUCCESS(Status), "Error mapping view with READ priv. Error = %p\n", Status))
425 {
426 Match = RtlCompareMemory(BaseAddress, TestString, TestStringSize);
427 ok_eq_size(Match, TestStringSize);
428
429 KmtStartSeh()
430 RtlCopyMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN);
431 KmtEndSeh(STATUS_ACCESS_VIOLATION);
432
433 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
434 }
435
436 /* FIXME: Crash. See ROSTESTS-110 */
437 #ifdef ROSTESTS_110_FIXED
438 //try to access forbidden memory
439 BaseAddress = NULL;
440 ViewSize = 0;
441 SectionOffset.QuadPart = 0;
442 Status = ZwMapViewOfSection(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_NOACCESS);
443 if (!skip(NT_SUCCESS(Status), "Error mapping view with PAGE_NOACCESS priv. Error = %p\n", Status))
444 {
445 KmtStartSeh()
446 RtlCompareMemory(BaseAddress, TestString, TestStringSize);
447 KmtEndSeh(STATUS_ACCESS_VIOLATION);
448
449 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
450 }
451 #endif /* ROSTESTS_110_FIXED */
452
453 ZwClose(WriteSectionHandle);
454
455 //section created with sec_reserve should not be commited.
456 BaseAddress = NULL;
457 ViewSize = 0;
458 SectionOffset.QuadPart = 0;
459 Status = ZwCreateSection(&WriteSectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes, &MaximumSize, PAGE_READWRITE, SEC_RESERVE, FileHandleWriteOnly);
460 if (!skip(NT_SUCCESS(Status), "Error creating page file section. Error = %p\n", Status))
461 {
462 Status = ZwMapViewOfSection(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, TestStringSize, &SectionOffset, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE);
463 if (!skip(NT_SUCCESS(Status), "Error mapping page file view. Error = %p\n", Status))
464 {
465 //check also the SEC_COMMIT flag
466 /* This test proves that MSDN is once again wrong
467 * msdn.microsoft.com/en-us/library/windows/hardware/aa366537.aspx states that SEC_RESERVE
468 * should cause the allocated memory for the view to be reserved but in fact it is always committed.
469 * It fails also on windows.
470 */
471 Test_NtQueryVirtualMemory(BaseAddress, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE);
472 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
473 }
474
475 ZwClose(WriteSectionHandle);
476 }
477 }
478
479
480 static
481 VOID
482 PageFileBehaviorChecks()
483 {
484 NTSTATUS Status;
485 LARGE_INTEGER MaxSectionSize;
486 LARGE_INTEGER SectionOffset;
487 HANDLE PageFileSectionHandle;
488 PVOID BaseAddress;
489 SIZE_T ViewSize;
490 SIZE_T Match;
491 PVOID ThreadObject;
492 OBJECT_ATTRIBUTES ObjectAttributes;
493
494 MaxSectionSize.QuadPart = TestStringSize;
495 SectionOffset.QuadPart = 0;
496 PageFileSectionHandle = INVALID_HANDLE_VALUE;
497 BaseAddress = NULL;
498 ViewSize = TestStringSize;
499 InitializeObjectAttributes(&ObjectAttributes, &SharedSectionName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
500
501 //test memory sharing between 2 different processes
502 Status = ZwCreateSection(&PageFileSectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes, &MaxSectionSize, PAGE_READWRITE, SEC_COMMIT, NULL);
503 if (!skip(NT_SUCCESS(Status), "Error creating page file section. Error = %p\n", Status))
504 {
505 CheckObject(PageFileSectionHandle, 3, 1);
506 Status = ZwMapViewOfSection(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, TestStringSize, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE);
507 if (!skip(NT_SUCCESS(Status), "Error mapping page file view. Error = %p\n", Status))
508 {
509 HANDLE SysThreadHandle;
510
511 CheckObject(PageFileSectionHandle, 3, 1);
512
513 //check also the SEC_COMMIT flag
514 Test_NtQueryVirtualMemory(BaseAddress, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE);
515
516 RtlCopyMemory(BaseAddress, TestString, TestStringSize);
517
518 InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
519 Status = PsCreateSystemThread(&SysThreadHandle, STANDARD_RIGHTS_ALL, &ObjectAttributes, NULL, NULL, SystemProcessWorker, NULL);
520
521 if (!skip(NT_SUCCESS(Status), "Error creating System thread. Error = %p\n", Status))
522 {
523 Status = ObReferenceObjectByHandle(SysThreadHandle, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &ThreadObject, NULL);
524 if (!skip(NT_SUCCESS(Status), "Error getting reference to System thread when testing pagefile-backed section\n"))
525 {
526 //wait until the system thread actually terminates
527 KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, NULL);
528
529 //no longer need the thread object
530 ObDereferenceObject(ThreadObject);
531
532 //test for bi-directional access to the shared page file
533 Match = RtlCompareMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN);
534 ok_eq_size(Match, NEW_CONTENT_LEN);
535 }
536 }
537 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
538 }
539 ZwClose(PageFileSectionHandle);
540 }
541 }
542
543
544 START_TEST(ZwMapViewOfSection)
545 {
546 HANDLE FileHandleReadOnly = NULL;
547 HANDLE FileHandleWriteOnly = NULL;
548 HANDLE ExecutableFileHandle = NULL;
549
550 InitializeObjectAttributes(&NtdllObject, &FileReadOnlyPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
551 InitializeObjectAttributes(&KmtestFileObject, &WritableFilePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
552 InitializeObjectAttributes(&NtoskrnlFileObject, &NtosImgPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
553
554 KmtInitTestFiles(&FileHandleReadOnly, &FileHandleWriteOnly, &ExecutableFileHandle);
555
556 SimpleErrorChecks(FileHandleReadOnly, FileHandleWriteOnly, ExecutableFileHandle);
557 AdvancedErrorChecks(FileHandleReadOnly, FileHandleWriteOnly);
558 BehaviorChecks(FileHandleReadOnly, FileHandleWriteOnly);
559 PageFileBehaviorChecks();
560
561 if (FileHandleReadOnly)
562 ZwClose(FileHandleReadOnly);
563
564 if (FileHandleWriteOnly)
565 ZwClose(FileHandleWriteOnly);
566
567 if (ExecutableFileHandle)
568 ZwClose(ExecutableFileHandle);
569 }