Corrected additional object manager issues pointed by Philip Susi
[reactos.git] / reactos / ntoskrnl / mm / section.c
1 /* $Id: section.c,v 1.20 1999/12/22 14:48:25 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 ObDereferenceObject(Section);
224 return(STATUS_SUCCESS);
225 }
226
227
228 /**********************************************************************
229 * NAME
230 * NtOpenSection
231 *
232 * DESCRIPTION
233 *
234 * ARGUMENTS
235 * SectionHandle
236 *
237 * DesiredAccess
238 *
239 * ObjectAttributes
240 *
241 * RETURN VALUE
242 *
243 * REVISIONS
244 *
245 */
246 NTSTATUS STDCALL NtOpenSection(PHANDLE SectionHandle,
247 ACCESS_MASK DesiredAccess,
248 POBJECT_ATTRIBUTES ObjectAttributes)
249 {
250 PVOID Object;
251 NTSTATUS Status;
252
253 *SectionHandle = 0;
254
255 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
256 ObjectAttributes->Attributes,
257 NULL,
258 DesiredAccess,
259 MmSectionType,
260 UserMode,
261 NULL,
262 &Object);
263 if (!NT_SUCCESS(Status))
264 {
265 return Status;
266 }
267
268 Status = ObCreateHandle(PsGetCurrentProcess(),
269 Object,
270 DesiredAccess,
271 FALSE,
272 SectionHandle);
273 ObDereferenceObject(Object);
274 return(Status);
275 }
276
277
278 /**********************************************************************
279 * NAME EXPORTED
280 * NtMapViewOfSection
281 *
282 * DESCRIPTION
283 * Maps a view of a section into the virtual address space of a
284 * process.
285 *
286 * ARGUMENTS
287 * SectionHandle
288 * Handle of the section.
289 *
290 * ProcessHandle
291 * Handle of the process.
292 *
293 * BaseAddress
294 * Desired base address (or NULL) on entry;
295 * Actual base address of the view on exit.
296 *
297 * ZeroBits
298 * Number of high order address bits that must be zero.
299 *
300 * CommitSize
301 * Size in bytes of the initially committed section of
302 * the view.
303 *
304 * SectionOffset
305 * Offset in bytes from the beginning of the section
306 * to the beginning of the view.
307 *
308 * ViewSize
309 * Desired length of map (or zero to map all) on entry
310 * Actual length mapped on exit.
311 *
312 * InheritDisposition
313 * Specified how the view is to be shared with
314 * child processes.
315 *
316 * AllocateType
317 * Type of allocation for the pages.
318 *
319 * Protect
320 * Protection for the committed region of the view.
321 *
322 * RETURN VALUE
323 * Status.
324 */
325 NTSTATUS STDCALL NtMapViewOfSection(HANDLE SectionHandle,
326 HANDLE ProcessHandle,
327 PVOID* BaseAddress,
328 ULONG ZeroBits,
329 ULONG CommitSize,
330 PLARGE_INTEGER SectionOffset,
331 PULONG ViewSize,
332 SECTION_INHERIT InheritDisposition,
333 ULONG AllocationType,
334 ULONG Protect)
335 {
336 PSECTION_OBJECT Section;
337 PEPROCESS Process;
338 MEMORY_AREA * Result;
339 NTSTATUS Status;
340 KIRQL oldIrql;
341 ULONG ViewOffset;
342
343 DPRINT("NtMapViewOfSection(Section:%08lx, Process:%08lx,\n"
344 " Base:%08lx, ZeroBits:%08lx, CommitSize:%08lx,\n"
345 " SectionOffs:%08lx, *ViewSize:%08lx, InheritDisp:%08lx,\n"
346 " AllocType:%08lx, Protect:%08lx)\n",
347 SectionHandle, ProcessHandle, BaseAddress, ZeroBits,
348 CommitSize, SectionOffset, *ViewSize, InheritDisposition,
349 AllocationType, Protect);
350
351 DPRINT(" *Base:%08lx\n", *BaseAddress);
352
353 Status = ObReferenceObjectByHandle(SectionHandle,
354 SECTION_MAP_READ,
355 MmSectionType,
356 UserMode,
357 (PVOID*)&Section,
358 NULL);
359 if (!(NT_SUCCESS(Status)))
360 {
361 DPRINT("ObReference failed rc=%x\n",Status);
362 return Status;
363 }
364
365 DPRINT("Section %x\n",Section);
366
367 Status = ObReferenceObjectByHandle(ProcessHandle,
368 PROCESS_VM_OPERATION,
369 PsProcessType,
370 UserMode,
371 (PVOID*)&Process,
372 NULL);
373 if (!NT_SUCCESS(Status))
374 {
375 DPRINT("ObReferenceObjectByHandle(ProcessHandle, ...) failed (%x)\n",
376 Status);
377 ObDereferenceObject(Section);
378 return Status;
379 }
380
381 DPRINT("Process %x\n", Process);
382 DPRINT("ViewSize %x\n",ViewSize);
383
384 if (SectionOffset == NULL)
385 {
386 ViewOffset = 0;
387 }
388 else
389 {
390 ViewOffset = SectionOffset->u.LowPart;
391 }
392
393 if (((*ViewSize)+ViewOffset) > Section->MaximumSize.u.LowPart)
394 {
395 (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
396 }
397
398 DPRINT("Creating memory area\n");
399 Status = MmCreateMemoryArea(UserMode,
400 Process,
401 MEMORY_AREA_SECTION_VIEW_COMMIT,
402 BaseAddress,
403 *ViewSize,
404 Protect,
405 &Result);
406 if (!NT_SUCCESS(Status))
407 {
408 DPRINT("NtMapViewOfSection() = %x\n",Status);
409
410 ObDereferenceObject(Process);
411 ObDereferenceObject(Section);
412
413 return Status;
414 }
415
416 KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
417 InsertTailList(&Section->ViewListHead,
418 &Result->Data.SectionData.ViewListEntry);
419 KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
420
421 Result->Data.SectionData.Section = Section;
422 Result->Data.SectionData.ViewOffset = ViewOffset;
423
424 DPRINT("SectionOffset %x\n",SectionOffset);
425
426
427 DPRINT("*BaseAddress %x\n",*BaseAddress);
428 ObDereferenceObject(Process);
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 ObDereferenceObject(Section);
444
445 return(STATUS_SUCCESS);
446 }
447
448 /**********************************************************************
449 * NAME EXPORTED
450 * NtUnmapViewOfSection
451 *
452 * DESCRIPTION
453 *
454 * ARGUMENTS
455 * ProcessHandle
456 *
457 * BaseAddress
458 *
459 * RETURN VALUE
460 * Status.
461 *
462 * REVISIONS
463 *
464 */
465 NTSTATUS STDCALL NtUnmapViewOfSection (HANDLE ProcessHandle,
466 PVOID BaseAddress)
467 {
468 PEPROCESS Process;
469 NTSTATUS Status;
470 PMEMORY_AREA MemoryArea;
471
472 Status = ObReferenceObjectByHandle(ProcessHandle,
473 PROCESS_VM_OPERATION,
474 PsProcessType,
475 UserMode,
476 (PVOID*)&Process,
477 NULL);
478
479 MemoryArea = MmOpenMemoryAreaByAddress(Process, BaseAddress);
480 if (MemoryArea == NULL)
481 {
482 ObDereferenceObject(Process);
483 return(STATUS_UNSUCCESSFUL);
484 }
485
486 Status = MmUnmapViewOfSection(Process, MemoryArea);
487
488 Status = MmFreeMemoryArea(Process,
489 BaseAddress,
490 0,
491 TRUE);
492
493 ObDereferenceObject(Process);
494
495 return Status;
496 }
497
498
499 NTSTATUS STDCALL NtQuerySection (IN HANDLE SectionHandle,
500 IN CINT SectionInformationClass,
501 OUT PVOID SectionInformation,
502 IN ULONG Length,
503 OUT PULONG ResultLength)
504 /*
505 * FUNCTION: Queries the information of a section object.
506 * ARGUMENTS:
507 * SectionHandle = Handle to the section link object
508 * SectionInformationClass = Index to a certain information structure
509 * SectionInformation (OUT)= Caller supplies storage for resulting
510 * information
511 * Length = Size of the supplied storage
512 * ResultLength = Data written
513 * RETURNS: Status
514 *
515 */
516 {
517 return(STATUS_UNSUCCESSFUL);
518 }
519
520
521 NTSTATUS STDCALL NtExtendSection(IN HANDLE SectionHandle,
522 IN ULONG NewMaximumSize)
523 {
524 UNIMPLEMENTED;
525 }
526
527
528 /* EOF */