2 * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * PROJECT: ReactOS kernel
20 * FILE: ntoskrnl/mm/section.c
21 * PURPOSE: Implements section objects
23 * PROGRAMMERS: Rex Jolliff
36 * Thomas Weidenmueller
37 * Gunnar Andre' Dalsnes
45 /* INCLUDES *****************************************************************/
51 #include <reactos/exeformat.h>
53 #if defined (ALLOC_PRAGMA)
54 #pragma alloc_text(INIT, MmCreatePhysicalMemorySection)
55 #pragma alloc_text(INIT, MmInitSectionImplementation)
58 KEVENT CcpLazyWriteEvent
;
62 MmGetDeviceObjectForFile(IN PFILE_OBJECT FileObject
)
64 return IoGetRelatedDeviceObject(FileObject
);
70 This completion function is really required. Paging io completion does almost
71 nothing, including freeing the mdls.
76 MiSimpleReadComplete(PDEVICE_OBJECT DeviceObject
,
80 PMDL Mdl
= Irp
->MdlAddress
;
82 /* Unlock MDL Pages, page 167. */
83 DPRINT("MiSimpleReadComplete %p\n", Irp
);
86 DPRINT("MDL Unlock %p\n", Mdl
);
91 /* Check if there's an MDL */
92 while ((Mdl
= Irp
->MdlAddress
))
94 /* Clear all of them */
95 Irp
->MdlAddress
= Mdl
->Next
;
99 return STATUS_SUCCESS
;
104 MiSimpleRead is a convenience function that provides either paging or non
105 paging reads. The caching and mm systems use this in paging mode, where
106 a completion function is required as above. The Paging BOOLEAN determines
107 whether the read is issued as a paging read or as an ordinary buffered read.
113 MiSimpleRead(PFILE_OBJECT FileObject
,
114 PLARGE_INTEGER FileOffset
,
118 PIO_STATUS_BLOCK ReadStatus
)
123 PDEVICE_OBJECT DeviceObject
;
124 PIO_STACK_LOCATION IrpSp
;
131 DeviceObject
= MmGetDeviceObjectForFile(FileObject
);
132 ReadStatus
->Status
= STATUS_INTERNAL_ERROR
;
133 ReadStatus
->Information
= 0;
135 ASSERT(DeviceObject
);
137 DPRINT("PAGING READ: FileObject %p <%wZ> Offset %08x%08x Length %d\n",
139 &FileObject
->FileName
,
140 FileOffset
->HighPart
,
144 KeInitializeEvent(&ReadWait
, NotificationEvent
, FALSE
);
146 Irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_READ
,
155 return STATUS_NO_MEMORY
;
158 Irp
->Flags
|= (Paging
? IRP_PAGING_IO
| IRP_SYNCHRONOUS_PAGING_IO
| IRP_NOCACHE
: 0) | IRP_SYNCHRONOUS_API
;
160 Irp
->UserEvent
= &ReadWait
;
161 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
162 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
163 IrpSp
= IoGetNextIrpStackLocation(Irp
);
164 IrpSp
->Control
|= SL_INVOKE_ON_SUCCESS
| SL_INVOKE_ON_ERROR
;
165 IrpSp
->FileObject
= FileObject
;
166 IrpSp
->CompletionRoutine
= MiSimpleReadComplete
;
168 /* Non paging case, the FileObject will be dereferenced at completion */
170 ObReferenceObject(FileObject
);
172 Status
= IoCallDriver(DeviceObject
, Irp
);
173 if (Status
== STATUS_PENDING
)
175 DPRINT("KeWaitForSingleObject(&ReadWait)\n");
176 if (!NT_SUCCESS(KeWaitForSingleObject(&ReadWait
,
182 DPRINT1("Warning: Failed to wait for synchronous IRP\n");
188 DPRINT("Paging IO Done: %08x\n", ReadStatus
->Status
);
189 Status
= ReadStatus
->Status
== STATUS_END_OF_FILE
? STATUS_SUCCESS
: ReadStatus
->Status
;
195 Convenience function for writing from kernel space. This issues a paging
202 _MiSimpleWrite(PFILE_OBJECT FileObject
,
203 PLARGE_INTEGER FileOffset
,
206 PIO_STATUS_BLOCK ReadStatus
,
213 PDEVICE_OBJECT DeviceObject
;
214 PIO_STACK_LOCATION IrpSp
;
221 DeviceObject
= MmGetDeviceObjectForFile(FileObject
);
222 ASSERT(DeviceObject
);
224 DPRINT("PAGING WRITE: FileObject %x <%wZ> Offset %x Length %d (%s:%d)\n",
226 &FileObject
->FileName
,
232 KeInitializeEvent(&ReadWait
, NotificationEvent
, FALSE
);
234 Irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE
,
243 return STATUS_NO_MEMORY
;
246 Irp
->Flags
= IRP_PAGING_IO
| IRP_SYNCHRONOUS_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_API
;
248 Irp
->UserEvent
= &ReadWait
;
249 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
250 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
251 IrpSp
= IoGetNextIrpStackLocation(Irp
);
252 IrpSp
->Control
|= SL_INVOKE_ON_SUCCESS
| SL_INVOKE_ON_ERROR
;
253 IrpSp
->FileObject
= FileObject
;
254 IrpSp
->CompletionRoutine
= MiSimpleReadComplete
;
256 DPRINT("Call Driver\n");
257 Status
= IoCallDriver(DeviceObject
, Irp
);
258 DPRINT("Status %x\n", Status
);
260 if (Status
== STATUS_PENDING
)
262 DPRINT("KeWaitForSingleObject(&ReadWait)\n");
263 if (!NT_SUCCESS(KeWaitForSingleObject(&ReadWait
,
269 DPRINT1("Warning: Failed to wait for synchronous IRP\n");
275 DPRINT("Paging IO Done: %08x\n", ReadStatus
->Status
);
276 return ReadStatus
->Status
;
279 extern KEVENT MpwThreadEvent
;
280 FAST_MUTEX MiWriteMutex
;
284 Function which uses MiSimpleWrite to write back a single page to a file.
285 The page in question does not need to be mapped. This function could be
286 made a bit more efficient by avoiding the copy and making a system space
293 _MiWriteBackPage(PFILE_OBJECT FileObject
,
294 PLARGE_INTEGER FileOffset
,
302 IO_STATUS_BLOCK Iosb
;
304 PVOID PageBuffer
= ExAllocatePool(NonPagedPool
, PAGE_SIZE
);
306 if (!PageBuffer
) return STATUS_NO_MEMORY
;
308 Hyperspace
= MiMapPageInHyperSpace(PsGetCurrentProcess(), Page
, &OldIrql
);
311 ExFreePool(PageBuffer
);
312 return STATUS_NO_MEMORY
;
314 RtlCopyMemory(PageBuffer
, Hyperspace
, PAGE_SIZE
);
315 MiUnmapPageInHyperSpace(PsGetCurrentProcess(), Hyperspace
, OldIrql
);
317 DPRINT("MiWriteBackPage(%wZ,%08x%08x,%s:%d)\n",
318 &FileObject
->FileName
,
319 FileOffset
->u
.HighPart
,
320 FileOffset
->u
.LowPart
,
324 Status
= MiSimpleWrite(FileObject
,
330 ExFreePool(PageBuffer
);
332 if (!NT_SUCCESS(Status
))
334 DPRINT1("MiSimpleWrite failed (%x)\n", Status
);