[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 Status = NtFreeVirtualMemory(NtCurrentProcess(),
107 &BaseAddress,
108 &ViewSize,
109 MEM_DECOMMIT);
110 ok(Status == STATUS_UNABLE_TO_DELETE_SECTION, "NtFreeVirtualMemory returned wrong Status %lx\n", Status);
111 /* Try to commit a range larger than the section */
112 BaseAddress = (PVOID)0x30000000;
113 ViewSize = 0x3000;
114 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
115 &BaseAddress,
116 0,
117 &ViewSize,
118 MEM_COMMIT,
119 PAGE_READWRITE);
120 ok(Status == STATUS_CONFLICTING_ADDRESSES,
121 "NtAllocateVirtualMemory failed with wrong Status %lx\n", Status);
122
123 /* Try to commit a page after the section */
124 BaseAddress = (PVOID)0x30002000;
125 ViewSize = 0x1000;
126 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
127 &BaseAddress,
128 0,
129 &ViewSize,
130 MEM_COMMIT,
131 PAGE_READWRITE);
132 ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory Should fail\n");
133
134 /* Try to allocate a page after the section */
135 BaseAddress = (PVOID)0x30002000;
136 ViewSize = 0x1000;
137 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
138 &BaseAddress,
139 0,
140 &ViewSize,
141 MEM_RESERVE | MEM_COMMIT,
142 PAGE_READWRITE);
143 ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory should fail\n");
144
145 /* Need to go to next 64k boundary */
146 BaseAddress = (PVOID)0x30010000;
147 ViewSize = 0x1000;
148 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
149 &BaseAddress,
150 0,
151 &ViewSize,
152 MEM_RESERVE | MEM_COMMIT,
153 PAGE_READWRITE);
154 ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status);
155 if (!NT_SUCCESS(Status))
156 return;
157
158 /* Free the allocation */
159 BaseAddress = (PVOID)0x30010000;
160 ViewSize = 0x1000;
161 Status = NtFreeVirtualMemory(NtCurrentProcess(),
162 &BaseAddress,
163 &ViewSize,
164 MEM_RELEASE);
165 ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed with Status %lx\n", Status);
166
167 /* Free the section mapping */
168 BaseAddress = (PVOID)0x30000000;
169 ViewSize = 0x1000;
170 Status = NtFreeVirtualMemory(NtCurrentProcess(),
171 &BaseAddress,
172 &ViewSize,
173 MEM_RELEASE);
174 ok(Status == STATUS_UNABLE_TO_DELETE_SECTION,
175 "NtFreeVirtualMemory failed with wrong Status %lx\n", Status);
176
177 /* Commit a page in the section */
178 BaseAddress = (PVOID)0x30001000;
179 ViewSize = 0x1000;
180 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
181 &BaseAddress,
182 0,
183 &ViewSize,
184 MEM_COMMIT,
185 PAGE_READWRITE);
186 ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status);
187
188 /* Try to decommit the page */
189 BaseAddress = (PVOID)0x30001000;
190 ViewSize = 0x1000;
191 Status = NtFreeVirtualMemory(NtCurrentProcess(),
192 &BaseAddress,
193 &ViewSize,
194 MEM_DECOMMIT);
195 ok(Status == STATUS_UNABLE_TO_DELETE_SECTION,
196 "NtFreeVirtualMemory failed with wrong Status %lx\n", Status);
197
198 BaseAddress = UlongToPtr(0x40000000);
199 SectionOffset.QuadPart = 0;
200 ViewSize = 0x1000;
201 Status = NtMapViewOfSection(SectionHandle,
202 NtCurrentProcess(),
203 &BaseAddress,
204 0,
205 0,
206 &SectionOffset,
207 &ViewSize,
208 ViewShare,
209 0,
210 PAGE_READWRITE);
211 ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status);
212 if (!NT_SUCCESS(Status))
213 return;
214
215 ok(BaseAddress == UlongToPtr(0x40000000), "Invalid BaseAddress: %p", BaseAddress);
216
217 BaseAddress = (PVOID)0x40080000;
218 SectionOffset.QuadPart = 0x10000;
219 ViewSize = 0x1000;
220 Status = NtMapViewOfSection(SectionHandle,
221 NtCurrentProcess(),
222 &BaseAddress,
223 0,
224 0,
225 &SectionOffset,
226 &ViewSize,
227 ViewShare,
228 0,
229 PAGE_READWRITE);
230 ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status);
231 if (!NT_SUCCESS(Status))
232 return;
233
234 ok(BaseAddress == (PVOID)0x40080000, "Invalid BaseAddress: %p", BaseAddress);
235
236 /* Commit a page in the section */
237 BaseAddress = (PVOID)0x40000000;
238 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
239 &BaseAddress,
240 0,
241 &ViewSize,
242 MEM_COMMIT,
243 PAGE_READWRITE);
244 ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status);
245 if (!NT_SUCCESS(Status))
246 return;
247
248 }
249
250 void
251 Test_ImageSection(void)
252 {
253 UNICODE_STRING FileName;
254 NTSTATUS Status;
255 OBJECT_ATTRIBUTES FileObjectAttributes;
256 IO_STATUS_BLOCK IoStatusBlock;
257 HANDLE FileHandle, DataSectionHandle, ImageSectionHandle;
258 PVOID DataBase, ImageBase;
259 SIZE_T ViewSize;
260
261 if (!RtlDosPathNameToNtPathName_U(L"testdata\\test.dll",
262 &FileName,
263 NULL,
264 NULL))
265 {
266 ok(0, "RtlDosPathNameToNtPathName_U failed\n");
267 return;
268 }
269
270 InitializeObjectAttributes(&FileObjectAttributes,
271 &FileName,
272 0,
273 NULL,
274 NULL);
275
276 Status = NtOpenFile(&FileHandle,
277 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
278 &FileObjectAttributes,
279 &IoStatusBlock,
280 FILE_SHARE_READ,
281 FILE_SYNCHRONOUS_IO_NONALERT);
282 ok(Status == STATUS_SUCCESS, "NtOpenFile failed, Status 0x%lx\n", Status);
283
284 /* Create a data section with write access */
285 Status = NtCreateSection(&DataSectionHandle,
286 SECTION_ALL_ACCESS, // DesiredAccess
287 NULL, // ObjectAttributes
288 NULL, // MaximumSize
289 PAGE_READWRITE, // SectionPageProtection
290 SEC_COMMIT, // AllocationAttributes
291 FileHandle);
292 ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status);
293
294 /* Map the data section */
295 DataBase = NULL;
296 ViewSize = 0;
297 Status = NtMapViewOfSection(DataSectionHandle,
298 NtCurrentProcess(),
299 &DataBase,
300 0,
301 0,
302 NULL,
303 &ViewSize,
304 ViewShare,
305 0,
306 PAGE_READWRITE);
307 ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
308
309 /* Check the original data */
310 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
311
312 /* Modify the PE header (but do not flush!) */
313 *(ULONG*)DataBase = 0xdeadbabe;
314 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
315
316 /* Modify data in the .data section (but do not flush!) */
317 ok(*(ULONG*)((PUCHAR)DataBase + 0x800) == 0x12345678,
318 "Data in .data section invalid: 0x%lx!\n", *(ULONG*)((PUCHAR)DataBase + 0x800));
319 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x87654321;
320
321 /* Now try to create an image section (should fail) */
322 Status = NtCreateSection(&ImageSectionHandle,
323 SECTION_ALL_ACCESS, // DesiredAccess
324 NULL, // ObjectAttributes
325 NULL, // MaximumSize
326 PAGE_READWRITE, // SectionPageProtection
327 SEC_IMAGE, // AllocationAttributes
328 FileHandle);
329 ok(Status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection failed, Status 0x%lx\n", Status);
330
331 /* Restore the original header */
332 *(ULONG*)DataBase = 0x00905a4d;
333
334 /* Modify data in the .data section (but do not flush!) */
335 ok_hex(*(ULONG*)((PUCHAR)DataBase + 0x800), 0x87654321);
336 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xdeadbabe;
337
338 /* Try to create an image section again */
339 Status = NtCreateSection(&ImageSectionHandle,
340 SECTION_ALL_ACCESS, // DesiredAccess
341 NULL, // ObjectAttributes
342 NULL, // MaximumSize
343 PAGE_READWRITE, // SectionPageProtection
344 SEC_IMAGE, // AllocationAttributes
345 FileHandle);
346 ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status);
347
348 /* Map the image section */
349 ImageBase = NULL;
350 ViewSize = 0;
351 Status = NtMapViewOfSection(ImageSectionHandle,
352 NtCurrentProcess(),
353 &ImageBase,
354 0,
355 0,
356 NULL,
357 &ViewSize,
358 ViewShare,
359 0,
360 PAGE_READONLY);
361 #ifdef _M_IX86
362 ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
363 #else
364 ok(Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
365 #endif
366
367 /* Check the header */
368 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
369 ok(*(ULONG*)ImageBase == 0x00905a4d, "Header not ok\n");
370
371 /* Check the data section. Either of these can be present! */
372 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
373 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
374 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
375
376 /* Now modify the data again */
377 *(ULONG*)DataBase = 0xdeadbabe;
378 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xf00dada;
379
380 /* Check the data */
381 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
382 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
383 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
384 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
385 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
386
387 /* Flush the view */
388 ViewSize = 0x1000;
389 Status = NtFlushVirtualMemory(NtCurrentProcess(),
390 &DataBase,
391 &ViewSize,
392 &IoStatusBlock);
393 ok(Status == STATUS_SUCCESS, "NtFlushVirtualMemory failed, Status 0x%lx\n", Status);
394
395 /* Check the data again */
396 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
397 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
398 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
399 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
400
401 /* Restore the original header */
402 *(ULONG*)DataBase = 0x00905a4d;
403 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
404
405 /* Close the image mapping */
406 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
407 NtClose(ImageSectionHandle);
408
409 /* Create an image section again */
410 Status = NtCreateSection(&ImageSectionHandle,
411 SECTION_ALL_ACCESS, // DesiredAccess
412 NULL, // ObjectAttributes
413 NULL, // MaximumSize
414 PAGE_READWRITE, // SectionPageProtection
415 SEC_IMAGE, // AllocationAttributes
416 FileHandle);
417 ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status);
418
419 /* Map the image section again */
420 ImageBase = NULL;
421 ViewSize = 0;
422 Status = NtMapViewOfSection(ImageSectionHandle,
423 NtCurrentProcess(),
424 &ImageBase,
425 0,
426 0,
427 NULL,
428 &ViewSize,
429 ViewShare,
430 0,
431 PAGE_READONLY);
432 #ifdef _M_IX86
433 ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
434 #else
435 ok(Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
436 #endif
437
438 /* Check the .data section again */
439 ok(*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0xf00dada,
440 "Data should be synced: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));
441
442 /* Restore the original data */
443 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x12345678;
444
445 /* Close the data mapping */
446 NtUnmapViewOfSection(NtCurrentProcess(), DataBase);
447
448 NtClose(DataSectionHandle);
449
450 /* Try to allocate memory inside the image mapping */
451 DataBase = (PUCHAR)ImageBase + 0x20000;
452 ViewSize = 0x1000;
453 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &DataBase, 0, &ViewSize, MEM_RESERVE, PAGE_NOACCESS);
454 ok(Status == STATUS_CONFLICTING_ADDRESSES, "Wrong Status: 0x%lx\n", Status);
455
456 /* Cleanup */
457 NtClose(FileHandle);
458 NtClose(ImageSectionHandle);
459 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
460 }
461
462
463 START_TEST(NtMapViewOfSection)
464 {
465 Test_PageFileSection();
466 Test_ImageSection();
467 }
468