[NTDLL_APITEST]
[reactos.git] / rostests / apitests / ntdll / NtMapViewOfSection.c
1
2 #define WIN32_NO_STATUS
3 #include <wine/test.h>
4 #include <ndk/ntndk.h>
5 #include <pseh/pseh2.h>
6
7 NTSYSAPI
8 NTSTATUS
9 NTAPI
10 NtMapViewOfSection(
11 HANDLE SectionHandle,
12 HANDLE ProcessHandle,
13 PVOID *BaseAddress,
14 ULONG_PTR ZeroBits,
15 SIZE_T CommitSize,
16 PLARGE_INTEGER SectionOffset,
17 PSIZE_T ViewSize,
18 SECTION_INHERIT InheritDisposition,
19 ULONG AllocationType,
20 ULONG Protect);
21
22 void
23 Test_PageFileSection(void)
24 {
25 NTSTATUS Status;
26 HANDLE SectionHandle;
27 LARGE_INTEGER MaximumSize, SectionOffset;
28 PVOID BaseAddress;
29 SIZE_T ViewSize;
30
31 /* Create a page file backed section */
32 MaximumSize.QuadPart = 0x20000;
33 Status = NtCreateSection(&SectionHandle,
34 SECTION_ALL_ACCESS,
35 NULL,
36 &MaximumSize,
37 PAGE_READWRITE,
38 SEC_COMMIT,
39 NULL);
40 ok(NT_SUCCESS(Status), "NtCreateSection failed with Status %lx\n", Status);
41 if (!NT_SUCCESS(Status))
42 return;
43
44 /* Try to map a page at an address that is not 64k aligned */
45 BaseAddress = (PVOID)0x30001000;
46 SectionOffset.QuadPart = 0;
47 ViewSize = 0x1000;
48 Status = NtMapViewOfSection(SectionHandle,
49 NtCurrentProcess(),
50 &BaseAddress,
51 0,
52 0,
53 &SectionOffset,
54 &ViewSize,
55 ViewShare,
56 0,
57 PAGE_READWRITE);
58 ok(Status == STATUS_MAPPED_ALIGNMENT,
59 "NtMapViewOfSection returned wrong Status %lx\n", Status);
60
61 /* Try to map a page with execute rights */
62 BaseAddress = (PVOID)0x30000000;
63 SectionOffset.QuadPart = 0;
64 ViewSize = 0x1000;
65 Status = NtMapViewOfSection(SectionHandle,
66 NtCurrentProcess(),
67 &BaseAddress,
68 0,
69 0,
70 &SectionOffset,
71 &ViewSize,
72 ViewShare,
73 0,
74 PAGE_EXECUTE_READWRITE);
75 ok(Status == STATUS_SECTION_PROTECTION,
76 "NtMapViewOfSection returned wrong Status %lx\n", Status);
77
78 /* Map 2 pages, not comitting them */
79 BaseAddress = (PVOID)0x30000000;
80 SectionOffset.QuadPart = 0;
81 ViewSize = 0x2000;
82 Status = NtMapViewOfSection(SectionHandle,
83 NtCurrentProcess(),
84 &BaseAddress,
85 0,
86 0,
87 &SectionOffset,
88 &ViewSize,
89 ViewShare,
90 0,
91 PAGE_READWRITE);
92 ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status);
93 if (!NT_SUCCESS(Status))
94 return;
95
96 /* Commit a page in the section */
97 BaseAddress = (PVOID)0x30000000;
98 ViewSize = 0x1000;
99 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
100 &BaseAddress,
101 0,
102 &ViewSize,
103 MEM_COMMIT,
104 PAGE_READWRITE);
105 ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status);
106
107 /* Try to commit a range larger than the section */
108 BaseAddress = (PVOID)0x30000000;
109 ViewSize = 0x3000;
110 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
111 &BaseAddress,
112 0,
113 &ViewSize,
114 MEM_COMMIT,
115 PAGE_READWRITE);
116 ok(Status == STATUS_CONFLICTING_ADDRESSES,
117 "NtAllocateVirtualMemory failed with wrong Status %lx\n", Status);
118
119 /* Try to commit a page after the section */
120 BaseAddress = (PVOID)0x30002000;
121 ViewSize = 0x1000;
122 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
123 &BaseAddress,
124 0,
125 &ViewSize,
126 MEM_COMMIT,
127 PAGE_READWRITE);
128 ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory Should fail\n");
129
130 /* Try to allocate a page after the section */
131 BaseAddress = (PVOID)0x30002000;
132 ViewSize = 0x1000;
133 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
134 &BaseAddress,
135 0,
136 &ViewSize,
137 MEM_RESERVE | MEM_COMMIT,
138 PAGE_READWRITE);
139 ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory should fail\n");
140
141 /* Need to go to next 64k boundary */
142 BaseAddress = (PVOID)0x30010000;
143 ViewSize = 0x1000;
144 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
145 &BaseAddress,
146 0,
147 &ViewSize,
148 MEM_RESERVE | MEM_COMMIT,
149 PAGE_READWRITE);
150 ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status);
151 if (!NT_SUCCESS(Status))
152 return;
153
154 /* Free the allocation */
155 BaseAddress = (PVOID)0x30010000;
156 ViewSize = 0x1000;
157 Status = NtFreeVirtualMemory(NtCurrentProcess(),
158 &BaseAddress,
159 &ViewSize,
160 MEM_RELEASE);
161 ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed with Status %lx\n", Status);
162
163 /* Free the section mapping */
164 BaseAddress = (PVOID)0x30000000;
165 ViewSize = 0x1000;
166 Status = NtFreeVirtualMemory(NtCurrentProcess(),
167 &BaseAddress,
168 &ViewSize,
169 MEM_RELEASE);
170 ok(Status == STATUS_UNABLE_TO_DELETE_SECTION,
171 "NtFreeVirtualMemory failed with wrong Status %lx\n", Status);
172
173 /* Commit a page in the section */
174 BaseAddress = (PVOID)0x30001000;
175 ViewSize = 0x1000;
176 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
177 &BaseAddress,
178 0,
179 &ViewSize,
180 MEM_COMMIT,
181 PAGE_READWRITE);
182 ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status);
183
184 /* Try to decommit the page */
185 BaseAddress = (PVOID)0x30001000;
186 ViewSize = 0x1000;
187 Status = NtFreeVirtualMemory(NtCurrentProcess(),
188 &BaseAddress,
189 &ViewSize,
190 MEM_DECOMMIT);
191 ok(Status == STATUS_UNABLE_TO_DELETE_SECTION,
192 "NtFreeVirtualMemory failed with wrong Status %lx\n", Status);
193
194 BaseAddress = UlongToPtr(0x40000000);
195 SectionOffset.QuadPart = 0;
196 ViewSize = 0x1000;
197 Status = NtMapViewOfSection(SectionHandle,
198 NtCurrentProcess(),
199 &BaseAddress,
200 0,
201 0,
202 &SectionOffset,
203 &ViewSize,
204 ViewShare,
205 0,
206 PAGE_READWRITE);
207 ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status);
208 if (!NT_SUCCESS(Status))
209 return;
210
211 ok(BaseAddress == UlongToPtr(0x40000000), "Invalid BaseAddress: %p", BaseAddress);
212
213 BaseAddress = (PVOID)0x40080000;
214 SectionOffset.QuadPart = 0x10000;
215 ViewSize = 0x1000;
216 Status = NtMapViewOfSection(SectionHandle,
217 NtCurrentProcess(),
218 &BaseAddress,
219 0,
220 0,
221 &SectionOffset,
222 &ViewSize,
223 ViewShare,
224 0,
225 PAGE_READWRITE);
226 ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status);
227 if (!NT_SUCCESS(Status))
228 return;
229
230 ok(BaseAddress == (PVOID)0x40080000, "Invalid BaseAddress: %p", BaseAddress);
231
232 /* Commit a page in the section */
233 BaseAddress = (PVOID)0x40000000;
234 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
235 &BaseAddress,
236 0,
237 &ViewSize,
238 MEM_COMMIT,
239 PAGE_READWRITE);
240 ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status);
241 if (!NT_SUCCESS(Status))
242 return;
243
244 }
245
246 void
247 Test_ImageSection(void)
248 {
249 UNICODE_STRING FileName;
250 NTSTATUS Status;
251 OBJECT_ATTRIBUTES FileObjectAttributes;
252 IO_STATUS_BLOCK IoStatusBlock;
253 HANDLE FileHandle, DataSectionHandle, ImageSectionHandle;
254 PVOID DataBase, ImageBase;
255 SIZE_T ViewSize;
256
257 if (!RtlDosPathNameToNtPathName_U(L"testdata\\test.dll",
258 &FileName,
259 NULL,
260 NULL))
261 {
262 ok(0, "RtlDosPathNameToNtPathName_U failed\n");
263 return;
264 }
265
266 InitializeObjectAttributes(&FileObjectAttributes,
267 &FileName,
268 0,
269 NULL,
270 NULL);
271
272 Status = NtOpenFile(&FileHandle,
273 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
274 &FileObjectAttributes,
275 &IoStatusBlock,
276 FILE_SHARE_READ,
277 FILE_SYNCHRONOUS_IO_NONALERT);
278 ok(Status == STATUS_SUCCESS, "NtOpenFile failed, Status 0x%lx\n", Status);
279
280 /* Create a data section with write access */
281 Status = NtCreateSection(&DataSectionHandle,
282 SECTION_ALL_ACCESS, // DesiredAccess
283 NULL, // ObjectAttributes
284 NULL, // MaximumSize
285 PAGE_READWRITE, // SectionPageProtection
286 SEC_COMMIT, // AllocationAttributes
287 FileHandle);
288 ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status);
289
290 /* Map the data section */
291 DataBase = NULL;
292 ViewSize = 0;
293 Status = NtMapViewOfSection(DataSectionHandle,
294 NtCurrentProcess(),
295 &DataBase,
296 0,
297 0,
298 NULL,
299 &ViewSize,
300 ViewShare,
301 0,
302 PAGE_READWRITE);
303 ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
304
305 /* Check the original data */
306 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
307
308 /* Modify the PE header (but do not flush!) */
309 *(ULONG*)DataBase = 0xdeadbabe;
310 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
311
312 /* Modify data in the .data section (but do not flush!) */
313 ok(*(ULONG*)((PUCHAR)DataBase + 0x800) == 0x12345678,
314 "Data in .data section invalid: 0x%lx!\n", *(ULONG*)((PUCHAR)DataBase + 0x800));
315 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x87654321;
316
317 /* Now try to create an image section (should fail) */
318 Status = NtCreateSection(&ImageSectionHandle,
319 SECTION_ALL_ACCESS, // DesiredAccess
320 NULL, // ObjectAttributes
321 NULL, // MaximumSize
322 PAGE_READWRITE, // SectionPageProtection
323 SEC_IMAGE, // AllocationAttributes
324 FileHandle);
325 ok(Status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection failed, Status 0x%lx\n", Status);
326
327 /* Restore the original header */
328 *(ULONG*)DataBase = 0x00905a4d;
329
330 /* Modify data in the .data section (but do not flush!) */
331 ok_hex(*(ULONG*)((PUCHAR)DataBase + 0x800), 0x87654321);
332 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xdeadbabe;
333
334 /* Try to create an image section again */
335 Status = NtCreateSection(&ImageSectionHandle,
336 SECTION_ALL_ACCESS, // DesiredAccess
337 NULL, // ObjectAttributes
338 NULL, // MaximumSize
339 PAGE_READWRITE, // SectionPageProtection
340 SEC_IMAGE, // AllocationAttributes
341 FileHandle);
342 ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status);
343
344 /* Map the image section */
345 ImageBase = NULL;
346 ViewSize = 0;
347 Status = NtMapViewOfSection(ImageSectionHandle,
348 NtCurrentProcess(),
349 &ImageBase,
350 0,
351 0,
352 NULL,
353 &ViewSize,
354 ViewShare,
355 0,
356 PAGE_READONLY);
357 #ifdef _M_IX86
358 ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
359 #else
360 ok(Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
361 #endif
362
363 /* Check the header */
364 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
365 ok(*(ULONG*)ImageBase == 0x00905a4d, "Header not ok\n");
366
367 /* Check the data section. Either of these can be present! */
368 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
369 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
370 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
371
372 /* Now modify the data again */
373 *(ULONG*)DataBase = 0xdeadbabe;
374 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xf00dada;
375
376 /* Check the data */
377 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
378 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
379 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
380 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
381 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
382
383 /* Flush the view */
384 ViewSize = 0x1000;
385 Status = NtFlushVirtualMemory(NtCurrentProcess(),
386 &DataBase,
387 &ViewSize,
388 &IoStatusBlock);
389 ok(Status == STATUS_SUCCESS, "NtFlushVirtualMemory failed, Status 0x%lx\n", Status);
390
391 /* Check the data again */
392 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
393 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
394 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
395 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
396
397 /* Restore the original header */
398 *(ULONG*)DataBase = 0x00905a4d;
399 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
400
401 /* Close the image mapping */
402 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
403 NtClose(ImageSectionHandle);
404
405 /* Create an image section again */
406 Status = NtCreateSection(&ImageSectionHandle,
407 SECTION_ALL_ACCESS, // DesiredAccess
408 NULL, // ObjectAttributes
409 NULL, // MaximumSize
410 PAGE_READWRITE, // SectionPageProtection
411 SEC_IMAGE, // AllocationAttributes
412 FileHandle);
413 ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status);
414
415 /* Map the image section again */
416 ImageBase = NULL;
417 ViewSize = 0;
418 Status = NtMapViewOfSection(ImageSectionHandle,
419 NtCurrentProcess(),
420 &ImageBase,
421 0,
422 0,
423 NULL,
424 &ViewSize,
425 ViewShare,
426 0,
427 PAGE_READONLY);
428 #ifdef _M_IX86
429 ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
430 #else
431 ok(Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
432 #endif
433
434 /* Check the .data section again */
435 ok(*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0xf00dada,
436 "Data should be synced: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
437
438 /* Restore the original data */
439 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x12345678;
440
441 /* Close the data mapping */
442 NtUnmapViewOfSection(NtCurrentProcess(), DataBase);
443
444 NtClose(DataSectionHandle);
445
446 /* Try to allocate memory inside the image mapping */
447 DataBase = (PUCHAR)ImageBase + 0x20000;
448 ViewSize = 0x1000;
449 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &DataBase, 0, &ViewSize, MEM_RESERVE, PAGE_NOACCESS);
450 ok(Status == STATUS_CONFLICTING_ADDRESSES, "Wrong Status: 0x%lx\n", Status);
451
452 /* Cleanup */
453 NtClose(FileHandle);
454 NtClose(ImageSectionHandle);
455 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
456 }
457
458
459 START_TEST(NtMapViewOfSection)
460 {
461 Test_PageFileSection();
462 Test_ImageSection();
463 }
464