d731381b32775b1bbc21fa2a0aa10cdff5e6387a
[reactos.git] / reactos / ntoskrnl / mm / section.c
1 /* $Id: section.c,v 1.19 1999/12/20 02:14:39 dwelch Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/section.c
6 * PURPOSE: Implements section objects
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/mm.h>
16 #include <internal/ob.h>
17 #include <internal/io.h>
18 #include <internal/ps.h>
19 #include <wchar.h>
20
21 #define NDEBUG
22 #include <internal/debug.h>
23
24 /* GLOBALS *******************************************************************/
25
26 POBJECT_TYPE MmSectionType = NULL;
27
28 /* FUNCTIONS *****************************************************************/
29
30 PVOID MiTryToSharePageInSection(PSECTION_OBJECT Section,
31 ULONG Offset)
32 {
33 KIRQL oldIrql;
34 PLIST_ENTRY current_entry;
35 PMEMORY_AREA current;
36 PVOID Address;
37 ULONG PhysPage;
38
39 DPRINT("MiTryToSharePageInSection(Section %x, Offset %x)\n",
40 Section, Offset);
41
42 KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
43
44 current_entry = Section->ViewListHead.Flink;
45
46 while (current_entry != &Section->ViewListHead)
47 {
48 current = CONTAINING_RECORD(current_entry, MEMORY_AREA,
49 Data.SectionData.ViewListEntry);
50
51 if (current->Data.SectionData.ViewOffset <= Offset &&
52 (current->Data.SectionData.ViewOffset + current->Length) >= Offset)
53 {
54 Address = current->BaseAddress +
55 (Offset - current->Data.SectionData.ViewOffset);
56
57 PhysPage = MmGetPhysicalAddressForProcess(current->Process,
58 Address);
59 MmReferencePage((PVOID)PhysPage);
60 KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
61 return((PVOID)PhysPage);
62 }
63
64 current_entry = current_entry->Flink;
65 }
66
67 KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
68 return(NULL);
69 }
70
71 VOID MmpDeleteSection(PVOID ObjectBody)
72 {
73 }
74
75 NTSTATUS MmpCreateSection(PVOID ObjectBody,
76 PVOID Parent,
77 PWSTR RemainingPath,
78 POBJECT_ATTRIBUTES ObjectAttributes)
79 {
80 NTSTATUS Status;
81
82 DPRINT("MmpCreateDevice(ObjectBody %x, Parent %x, RemainingPath %w)\n",
83 ObjectBody, Parent, RemainingPath);
84
85 if (RemainingPath == NULL)
86 {
87 return(STATUS_SUCCESS);
88 }
89
90 if (wcschr(RemainingPath+1, L'\\') != NULL)
91 {
92 return(STATUS_UNSUCCESSFUL);
93 }
94
95 Status = ObReferenceObjectByPointer(Parent,
96 STANDARD_RIGHTS_REQUIRED,
97 ObDirectoryType,
98 UserMode);
99 if (!NT_SUCCESS(Status))
100 {
101 return(Status);
102 }
103
104 ObAddEntryDirectory(Parent, ObjectBody, RemainingPath+1);
105 ObDereferenceObject(Parent);
106
107 return(STATUS_SUCCESS);
108 }
109
110 NTSTATUS MmInitSectionImplementation(VOID)
111 {
112 ANSI_STRING AnsiString;
113
114 MmSectionType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
115
116 MmSectionType->TotalObjects = 0;
117 MmSectionType->TotalHandles = 0;
118 MmSectionType->MaxObjects = ULONG_MAX;
119 MmSectionType->MaxHandles = ULONG_MAX;
120 MmSectionType->PagedPoolCharge = 0;
121 MmSectionType->NonpagedPoolCharge = sizeof(SECTION_OBJECT);
122 MmSectionType->Dump = NULL;
123 MmSectionType->Open = NULL;
124 MmSectionType->Close = NULL;
125 MmSectionType->Delete = MmpDeleteSection;
126 MmSectionType->Parse = NULL;
127 MmSectionType->Security = NULL;
128 MmSectionType->QueryName = NULL;
129 MmSectionType->OkayToClose = NULL;
130 MmSectionType->Create = MmpCreateSection;
131
132 RtlInitAnsiString(&AnsiString,"Section");
133 RtlAnsiStringToUnicodeString(&MmSectionType->TypeName,
134 &AnsiString,TRUE);
135 return(STATUS_SUCCESS);
136 }
137
138
139 NTSTATUS STDCALL NtCreateSection (OUT PHANDLE SectionHandle,
140 IN ACCESS_MASK DesiredAccess,
141 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
142 IN PLARGE_INTEGER MaximumSize OPTIONAL,
143 IN ULONG SectionPageProtection OPTIONAL,
144 IN ULONG AllocationAttributes,
145 IN HANDLE FileHandle OPTIONAL)
146 /*
147 * FUNCTION: Creates a section object.
148 * ARGUMENTS:
149 * SectionHandle (OUT) = Caller supplied storage for the resulting
150 * handle
151 * DesiredAccess = Specifies the desired access to the section can be a
152 * combination of STANDARD_RIGHTS_REQUIRED |
153 * SECTION_QUERY | SECTION_MAP_WRITE |
154 * SECTION_MAP_READ | SECTION_MAP_EXECUTE.
155 * ObjectAttribute = Initialized attributes for the object can be used
156 * to create a named section
157 * MaxiumSize = Maximizes the size of the memory section. Must be
158 * non-NULL for a page-file backed section.
159 * If value specified for a mapped file and the file is
160 * not large enough, file will be extended.
161 * SectionPageProtection = Can be a combination of PAGE_READONLY |
162 * PAGE_READWRITE | PAGE_WRITEONLY |
163 * PAGE_WRITECOPY.
164 * AllocationAttributes = can be a combination of SEC_IMAGE |
165 * SEC_RESERVE
166 * FileHandle = Handle to a file to create a section mapped to a file
167 * instead of a memory backed section.
168 * RETURNS: Status
169 */
170 {
171 PSECTION_OBJECT Section;
172 NTSTATUS Status;
173
174 DPRINT("NtCreateSection()\n");
175
176 Section = ObCreateObject(SectionHandle,
177 DesiredAccess,
178 ObjectAttributes,
179 MmSectionType);
180 if (Section == NULL)
181 {
182 return(STATUS_UNSUCCESSFUL);
183 }
184
185 if (MaximumSize != NULL)
186 {
187 Section->MaximumSize = *MaximumSize;
188 }
189 else
190 {
191 Section->MaximumSize.QuadPart = 0xffffffff;
192 }
193 Section->SectionPageProtection = SectionPageProtection;
194 Section->AllocateAttributes = AllocationAttributes;
195 InitializeListHead(&Section->ViewListHead);
196 KeInitializeSpinLock(&Section->ViewListLock);
197
198 if (FileHandle != NULL)
199 {
200 Status = ObReferenceObjectByHandle(FileHandle,
201 FILE_READ_DATA,
202 IoFileType,
203 UserMode,
204 (PVOID*)&Section->FileObject,
205 NULL);
206 if (Status != STATUS_SUCCESS)
207 {
208 /*
209 * Delete section object
210 */
211 DPRINT("NtCreateSection() = %x\n",Status);
212 ZwClose(SectionHandle);
213 ObDereferenceObject(Section);
214 return(Status);
215 }
216 }
217 else
218 {
219 Section->FileObject = NULL;
220 }
221
222 DPRINT("NtCreateSection() = STATUS_SUCCESS\n");
223 return(STATUS_SUCCESS);
224 }
225
226
227 /**********************************************************************
228 * NAME
229 * NtOpenSection
230 *
231 * DESCRIPTION
232 *
233 * ARGUMENTS
234 * SectionHandle
235 *
236 * DesiredAccess
237 *
238 * ObjectAttributes
239 *
240 * RETURN VALUE
241 *
242 * REVISIONS
243 *
244 */
245 NTSTATUS STDCALL NtOpenSection(PHANDLE SectionHandle,
246 ACCESS_MASK DesiredAccess,
247 POBJECT_ATTRIBUTES ObjectAttributes)
248 {
249 PVOID Object;
250 NTSTATUS Status;
251
252 *SectionHandle = 0;
253
254 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
255 ObjectAttributes->Attributes,
256 NULL,
257 DesiredAccess,
258 MmSectionType,
259 UserMode,
260 NULL,
261 &Object);
262 if (!NT_SUCCESS(Status))
263 {
264 return Status;
265 }
266
267 Status = ObCreateHandle(PsGetCurrentProcess(),
268 Object,
269 DesiredAccess,
270 FALSE,
271 SectionHandle);
272 ObDereferenceObject(Object);
273 return(Status);
274 }
275
276
277 /**********************************************************************
278 * NAME EXPORTED
279 * NtMapViewOfSection
280 *
281 * DESCRIPTION
282 * Maps a view of a section into the virtual address space of a
283 * process.
284 *
285 * ARGUMENTS
286 * SectionHandle
287 * Handle of the section.
288 *
289 * ProcessHandle
290 * Handle of the process.
291 *
292 * BaseAddress
293 * Desired base address (or NULL) on entry;
294 * Actual base address of the view on exit.
295 *
296 * ZeroBits
297 * Number of high order address bits that must be zero.
298 *
299 * CommitSize
300 * Size in bytes of the initially committed section of
301 * the view.
302 *
303 * SectionOffset
304 * Offset in bytes from the beginning of the section
305 * to the beginning of the view.
306 *
307 * ViewSize
308 * Desired length of map (or zero to map all) on entry
309 * Actual length mapped on exit.
310 *
311 * InheritDisposition
312 * Specified how the view is to be shared with
313 * child processes.
314 *
315 * AllocateType
316 * Type of allocation for the pages.
317 *
318 * Protect
319 * Protection for the committed region of the view.
320 *
321 * RETURN VALUE
322 * Status.
323 */
324 NTSTATUS STDCALL NtMapViewOfSection(HANDLE SectionHandle,
325 HANDLE ProcessHandle,
326 PVOID* BaseAddress,
327 ULONG ZeroBits,
328 ULONG CommitSize,
329 PLARGE_INTEGER SectionOffset,
330 PULONG ViewSize,
331 SECTION_INHERIT InheritDisposition,
332 ULONG AllocationType,
333 ULONG Protect)
334 {
335 PSECTION_OBJECT Section;
336 PEPROCESS Process;
337 MEMORY_AREA * Result;
338 NTSTATUS Status;
339 KIRQL oldIrql;
340 ULONG ViewOffset;
341
342 DPRINT("NtMapViewOfSection(Section:%08lx, Process:%08lx,\n"
343 " Base:%08lx, ZeroBits:%08lx, CommitSize:%08lx,\n"
344 " SectionOffs:%08lx, *ViewSize:%08lx, InheritDisp:%08lx,\n"
345 " AllocType:%08lx, Protect:%08lx)\n",
346 SectionHandle, ProcessHandle, BaseAddress, ZeroBits,
347 CommitSize, SectionOffset, *ViewSize, InheritDisposition,
348 AllocationType, Protect);
349
350 DPRINT(" *Base:%08lx\n", *BaseAddress);
351
352 Status = ObReferenceObjectByHandle(SectionHandle,
353 SECTION_MAP_READ,
354 MmSectionType,
355 UserMode,
356 (PVOID*)&Section,
357 NULL);
358 if (!(NT_SUCCESS(Status)))
359 {
360 DPRINT("ObReference failed rc=%x\n",Status);
361 return Status;
362 }
363
364 DPRINT("Section %x\n",Section);
365
366 Status = ObReferenceObjectByHandle(ProcessHandle,
367 PROCESS_VM_OPERATION,
368 PsProcessType,
369 UserMode,
370 (PVOID*)&Process,
371 NULL);
372 if (!NT_SUCCESS(Status))
373 {
374 DPRINT("ObReferenceObjectByHandle(ProcessHandle, ...) failed (%x)\n",
375 Status);
376 ObDereferenceObject(Section);
377 return Status;
378 }
379
380 DPRINT("Process %x\n", Process);
381 DPRINT("ViewSize %x\n",ViewSize);
382
383 if (SectionOffset == NULL)
384 {
385 ViewOffset = 0;
386 }
387 else
388 {
389 ViewOffset = SectionOffset->u.LowPart;
390 }
391
392 if (((*ViewSize)+ViewOffset) > Section->MaximumSize.u.LowPart)
393 {
394 (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
395 }
396
397 DPRINT("Creating memory area\n");
398 Status = MmCreateMemoryArea(UserMode,
399 Process,
400 MEMORY_AREA_SECTION_VIEW_COMMIT,
401 BaseAddress,
402 *ViewSize,
403 Protect,
404 &Result);
405 if (!NT_SUCCESS(Status))
406 {
407 DPRINT("NtMapViewOfSection() = %x\n",Status);
408
409 ObDereferenceObject(Process);
410 ObDereferenceObject(Section);
411
412 return Status;
413 }
414
415 KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
416 InsertTailList(&Section->ViewListHead,
417 &Result->Data.SectionData.ViewListEntry);
418 KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
419
420 Result->Data.SectionData.Section = Section;
421 Result->Data.SectionData.ViewOffset = ViewOffset;
422
423 DPRINT("SectionOffset %x\n",SectionOffset);
424
425
426 DPRINT("*BaseAddress %x\n",*BaseAddress);
427 ObDereferenceObject(Process);
428 ObDereferenceObject(Section);
429
430 return(STATUS_SUCCESS);
431 }
432
433 NTSTATUS MmUnmapViewOfSection(PEPROCESS Process,
434 PMEMORY_AREA MemoryArea)
435 {
436 PSECTION_OBJECT Section;
437 KIRQL oldIrql;
438
439 Section = MemoryArea->Data.SectionData.Section;
440 KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
441 RemoveEntryList(&MemoryArea->Data.SectionData.ViewListEntry);
442 KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
443
444 return(STATUS_SUCCESS);
445 }
446
447 /**********************************************************************
448 * NAME EXPORTED
449 * NtUnmapViewOfSection
450 *
451 * DESCRIPTION
452 *
453 * ARGUMENTS
454 * ProcessHandle
455 *
456 * BaseAddress
457 *
458 * RETURN VALUE
459 * Status.
460 *
461 * REVISIONS
462 *
463 */
464 NTSTATUS STDCALL NtUnmapViewOfSection (HANDLE ProcessHandle,
465 PVOID BaseAddress)
466 {
467 PEPROCESS Process;
468 NTSTATUS Status;
469 PMEMORY_AREA MemoryArea;
470
471 Status = ObReferenceObjectByHandle(ProcessHandle,
472 PROCESS_VM_OPERATION,
473 PsProcessType,
474 UserMode,
475 (PVOID*)&Process,
476 NULL);
477
478 MemoryArea = MmOpenMemoryAreaByAddress(Process, BaseAddress);
479 if (MemoryArea == NULL)
480 {
481 ObDereferenceObject(Process);
482 return(STATUS_UNSUCCESSFUL);
483 }
484
485 Status = MmUnmapViewOfSection(Process, MemoryArea);
486
487 Status = MmFreeMemoryArea(Process,
488 BaseAddress,
489 0,
490 TRUE);
491
492 ObDereferenceObject(Process);
493
494 return Status;
495 }
496
497
498 NTSTATUS STDCALL NtQuerySection (IN HANDLE SectionHandle,
499 IN CINT SectionInformationClass,
500 OUT PVOID SectionInformation,
501 IN ULONG Length,
502 OUT PULONG ResultLength)
503 /*
504 * FUNCTION: Queries the information of a section object.
505 * ARGUMENTS:
506 * SectionHandle = Handle to the section link object
507 * SectionInformationClass = Index to a certain information structure
508 * SectionInformation (OUT)= Caller supplies storage for resulting
509 * information
510 * Length = Size of the supplied storage
511 * ResultLength = Data written
512 * RETURNS: Status
513 *
514 */
515 {
516 return(STATUS_UNSUCCESSFUL);
517 }
518
519
520 NTSTATUS STDCALL NtExtendSection(IN HANDLE SectionHandle,
521 IN ULONG NewMaximumSize)
522 {
523 UNIMPLEMENTED;
524 }
525
526
527 /* EOF */