[CMAKE]
[reactos.git] / reactos / ntoskrnl / cache / section / io.c
1 /*
2 * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
3 *
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.
8 *
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.
13 *
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.
17 *
18 *
19 * PROJECT: ReactOS kernel
20 * FILE: ntoskrnl/mm/section.c
21 * PURPOSE: Implements section objects
22 *
23 * PROGRAMMERS: Rex Jolliff
24 * David Welch
25 * Eric Kohl
26 * Emanuele Aliberti
27 * Eugene Ingerman
28 * Casper Hornstrup
29 * KJK::Hyperion
30 * Guido de Jong
31 * Ge van Geldorp
32 * Royce Mitchell III
33 * Filip Navara
34 * Aleksey Bragin
35 * Jason Filby
36 * Thomas Weidenmueller
37 * Gunnar Andre' Dalsnes
38 * Mike Nordell
39 * Alex Ionescu
40 * Gregor Anich
41 * Steven Edwards
42 * Herve Poussineau
43 */
44
45 /* INCLUDES *****************************************************************/
46
47 #include <ntoskrnl.h>
48 #include "newmm.h"
49 #define NDEBUG
50 #include <debug.h>
51 #include <reactos/exeformat.h>
52
53 #if defined (ALLOC_PRAGMA)
54 #pragma alloc_text(INIT, MmCreatePhysicalMemorySection)
55 #pragma alloc_text(INIT, MmInitSectionImplementation)
56 #endif
57
58 KEVENT CcpLazyWriteEvent;
59
60 PDEVICE_OBJECT
61 NTAPI
62 MmGetDeviceObjectForFile(IN PFILE_OBJECT FileObject)
63 {
64 return IoGetRelatedDeviceObject(FileObject);
65 }
66
67 NTSTATUS
68 NTAPI
69 MiSimpleReadComplete
70 (PDEVICE_OBJECT DeviceObject,
71 PIRP Irp,
72 PVOID Context)
73 {
74 PMDL Mdl = Irp->MdlAddress;
75
76 /* Unlock MDL Pages, page 167. */
77 DPRINT("MiSimpleReadComplete %x\n", Irp);
78 while (Mdl)
79 {
80 DPRINT("MDL Unlock %x\n", Mdl);
81 MmUnlockPages(Mdl);
82 Mdl = Mdl->Next;
83 }
84
85 /* Check if there's an MDL */
86 while ((Mdl = Irp->MdlAddress))
87 {
88 /* Clear all of them */
89 Irp->MdlAddress = Mdl->Next;
90 IoFreeMdl(Mdl);
91 }
92
93 return STATUS_SUCCESS;
94 }
95
96 NTSTATUS
97 NTAPI
98 MiSimpleRead
99 (PFILE_OBJECT FileObject,
100 PLARGE_INTEGER FileOffset,
101 PVOID Buffer,
102 ULONG Length,
103 #ifdef __ROS_DWARF__
104 BOOLEAN Paging,
105 #endif
106 PIO_STATUS_BLOCK ReadStatus)
107 {
108 NTSTATUS Status;
109 PIRP Irp = NULL;
110 KEVENT ReadWait;
111 PDEVICE_OBJECT DeviceObject;
112 PIO_STACK_LOCATION IrpSp;
113
114 ASSERT(FileObject);
115 ASSERT(FileOffset);
116 ASSERT(Buffer);
117 ASSERT(ReadStatus);
118
119 DeviceObject = MmGetDeviceObjectForFile(FileObject);
120 ReadStatus->Status = STATUS_INTERNAL_ERROR;
121 ReadStatus->Information = 0;
122
123 ASSERT(DeviceObject);
124
125 DPRINT
126 ("PAGING READ: FileObject %x <%wZ> Offset %08x%08x Length %d\n",
127 &FileObject,
128 &FileObject->FileName,
129 FileOffset->HighPart,
130 FileOffset->LowPart,
131 Length);
132
133 KeInitializeEvent(&ReadWait, NotificationEvent, FALSE);
134
135 Irp = IoBuildAsynchronousFsdRequest
136 (IRP_MJ_READ,
137 DeviceObject,
138 Buffer,
139 Length,
140 FileOffset,
141 ReadStatus);
142
143 if (!Irp)
144 {
145 return STATUS_NO_MEMORY;
146 }
147
148 #ifndef __ROS_DWARF__
149 Irp->Flags |= IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_API;
150 #else
151 Irp->Flags |= (Paging ? IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE : 0) | IRP_SYNCHRONOUS_API;
152 #endif
153
154 Irp->UserEvent = &ReadWait;
155 Irp->Tail.Overlay.OriginalFileObject = FileObject;
156 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
157 IrpSp = IoGetNextIrpStackLocation(Irp);
158 IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
159 IrpSp->FileObject = FileObject;
160 IrpSp->CompletionRoutine = MiSimpleReadComplete;
161
162 #ifdef __ROS_DWARF__
163 ObReferenceObject(FileObject);
164 #endif
165
166 Status = IoCallDriver(DeviceObject, Irp);
167 if (Status == STATUS_PENDING)
168 {
169 DPRINT1("KeWaitForSingleObject(&ReadWait)\n");
170 if (!NT_SUCCESS
171 (KeWaitForSingleObject
172 (&ReadWait,
173 Suspended,
174 KernelMode,
175 FALSE,
176 NULL)))
177 {
178 DPRINT1("Warning: Failed to wait for synchronous IRP\n");
179 ASSERT(FALSE);
180 return Status;
181 }
182 }
183
184 DPRINT("Paging IO Done: %08x\n", ReadStatus->Status);
185 Status =
186 ReadStatus->Status == STATUS_END_OF_FILE ?
187 STATUS_SUCCESS : ReadStatus->Status;
188 return Status;
189 }
190
191 NTSTATUS
192 NTAPI
193 _MiSimpleWrite
194 (PFILE_OBJECT FileObject,
195 PLARGE_INTEGER FileOffset,
196 PVOID Buffer,
197 ULONG Length,
198 PIO_STATUS_BLOCK ReadStatus,
199 const char *File,
200 int Line)
201 {
202 NTSTATUS Status;
203 PIRP Irp = NULL;
204 KEVENT ReadWait;
205 PDEVICE_OBJECT DeviceObject;
206 PIO_STACK_LOCATION IrpSp;
207
208 ASSERT(FileObject);
209 ASSERT(FileOffset);
210 ASSERT(Buffer);
211 ASSERT(ReadStatus);
212
213 ObReferenceObject(FileObject);
214 DeviceObject = MmGetDeviceObjectForFile(FileObject);
215 ASSERT(DeviceObject);
216
217 DPRINT
218 ("PAGING WRITE: FileObject %x Offset %x Length %d (%s:%d)\n",
219 &FileObject,
220 FileOffset->LowPart,
221 Length,
222 File,
223 Line);
224
225 KeInitializeEvent(&ReadWait, NotificationEvent, FALSE);
226
227 Irp = IoBuildAsynchronousFsdRequest
228 (IRP_MJ_WRITE,
229 DeviceObject,
230 Buffer,
231 Length,
232 FileOffset,
233 ReadStatus);
234
235 if (!Irp)
236 {
237 ObDereferenceObject(FileObject);
238 return STATUS_NO_MEMORY;
239 }
240
241 Irp->Flags = IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_API;
242
243 Irp->UserEvent = &ReadWait;
244 Irp->Tail.Overlay.OriginalFileObject = FileObject;
245 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
246 IrpSp = IoGetNextIrpStackLocation(Irp);
247 IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
248 IrpSp->FileObject = FileObject;
249 IrpSp->CompletionRoutine = MiSimpleReadComplete;
250
251 DPRINT("Call Driver\n");
252 Status = IoCallDriver(DeviceObject, Irp);
253 DPRINT("Status %x\n", Status);
254
255 ObDereferenceObject(FileObject);
256
257 if (Status == STATUS_PENDING)
258 {
259 DPRINT1("KeWaitForSingleObject(&ReadWait)\n");
260 if (!NT_SUCCESS
261 (KeWaitForSingleObject
262 (&ReadWait,
263 Suspended,
264 KernelMode,
265 FALSE,
266 NULL)))
267 {
268 DPRINT1("Warning: Failed to wait for synchronous IRP\n");
269 ASSERT(FALSE);
270 return Status;
271 }
272 }
273
274 DPRINT("Paging IO Done: %08x\n", ReadStatus->Status);
275 return ReadStatus->Status;
276 }
277
278 extern KEVENT MpwThreadEvent;
279 FAST_MUTEX MiWriteMutex;
280
281 NTSTATUS
282 NTAPI
283 _MiWriteBackPage
284 (PFILE_OBJECT FileObject,
285 PLARGE_INTEGER FileOffset,
286 ULONG Length,
287 PFN_NUMBER Page,
288 const char *File,
289 int Line)
290 {
291 NTSTATUS Status;
292 PVOID Hyperspace;
293 IO_STATUS_BLOCK Iosb;
294 KIRQL OldIrql;
295 PVOID PageBuffer = ExAllocatePool(NonPagedPool, PAGE_SIZE);
296
297 if (!PageBuffer) return STATUS_NO_MEMORY;
298
299 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
300 Hyperspace = MmCreateHyperspaceMapping(Page);
301 RtlCopyMemory(PageBuffer, Hyperspace, PAGE_SIZE);
302 MmDeleteHyperspaceMapping(Hyperspace);
303 KeLowerIrql(OldIrql);
304
305 DPRINT1("MiWriteBackPage(%wZ,%08x%08x,%s:%d)\n", &FileObject->FileName, FileOffset->u.HighPart, FileOffset->u.LowPart, File, Line);
306 Status = MiSimpleWrite
307 (FileObject,
308 FileOffset,
309 PageBuffer,
310 Length,
311 &Iosb);
312
313 ExFreePool(PageBuffer);
314
315 if (!NT_SUCCESS(Status))
316 {
317 DPRINT1("MiSimpleWrite failed (%x)\n", Status);
318 }
319
320 return Status;
321 }