[MMEBUDDY]
[reactos.git] / reactos / ntoskrnl / cache / section / reqtools.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
52 #define DPRINTC DPRINT
53
54 NTSTATUS
55 NTAPI
56 MiGetOnePage
57 (PMMSUPPORT AddressSpace,
58 PMEMORY_AREA MemoryArea,
59 PMM_REQUIRED_RESOURCES Required)
60 {
61 int i;
62 NTSTATUS Status = STATUS_SUCCESS;
63
64 for (i = 0; i < Required->Amount; i++)
65 {
66 DPRINTC("MiGetOnePage(%s:%d)\n", Required->File, Required->Line);
67 Status = MmRequestPageMemoryConsumer(Required->Consumer, TRUE, &Required->Page[i]);
68 if (!NT_SUCCESS(Status))
69 {
70 while (i > 0)
71 {
72 MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[i-1]);
73 i--;
74 }
75 return Status;
76 }
77 }
78
79 return Status;
80 }
81
82 NTSTATUS
83 NTAPI
84 MiReadFilePage
85 (PMMSUPPORT AddressSpace,
86 PMEMORY_AREA MemoryArea,
87 PMM_REQUIRED_RESOURCES RequiredResources)
88 {
89 PFILE_OBJECT FileObject = RequiredResources->Context;
90 PPFN_NUMBER Page = &RequiredResources->Page[RequiredResources->Offset];
91 PLARGE_INTEGER FileOffset = &RequiredResources->FileOffset;
92 NTSTATUS Status;
93 PVOID PageBuf = NULL;
94 PMEMORY_AREA TmpArea;
95 IO_STATUS_BLOCK IOSB;
96 PHYSICAL_ADDRESS BoundaryAddressMultiple;
97
98 BoundaryAddressMultiple.QuadPart = 0;
99
100 DPRINTC
101 ("Pulling page %08x%08x from %wZ to %x\n",
102 FileOffset->u.HighPart, FileOffset->u.LowPart,
103 &FileObject->FileName,
104 Page);
105
106 Status = MmRequestPageMemoryConsumer(RequiredResources->Consumer, TRUE, Page);
107 if (!NT_SUCCESS(Status))
108 {
109 DPRINT1("Status: %x\n", Status);
110 return Status;
111 }
112
113 MmLockAddressSpace(MmGetKernelAddressSpace());
114 Status = MmCreateMemoryArea
115 (MmGetKernelAddressSpace(),
116 MEMORY_AREA_VIRTUAL_MEMORY,
117 &PageBuf,
118 PAGE_SIZE,
119 PAGE_READWRITE,
120 &TmpArea,
121 FALSE,
122 MEM_TOP_DOWN,
123 BoundaryAddressMultiple);
124
125 DPRINT("Status %x, PageBuf %x\n", Status, PageBuf);
126 if (!NT_SUCCESS(Status))
127 {
128 DPRINT1("STATUS_NO_MEMORY: %x\n", Status);
129 MmUnlockAddressSpace(MmGetKernelAddressSpace());
130 MmReleasePageMemoryConsumer(MC_CACHE, *Page);
131 return STATUS_NO_MEMORY;
132 }
133
134 Status = MmCreateVirtualMapping(NULL, PageBuf, PAGE_READWRITE, Page, 1);
135 if (!NT_SUCCESS(Status))
136 {
137 MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL);
138 MmUnlockAddressSpace(MmGetKernelAddressSpace());
139 MmReleasePageMemoryConsumer(MC_CACHE, *Page);
140 DPRINT1("Status: %x\n", Status);
141 return Status;
142 }
143
144 MmUnlockAddressSpace(MmGetKernelAddressSpace());
145
146 Status = MiSimpleRead
147 (FileObject,
148 FileOffset,
149 PageBuf,
150 RequiredResources->Amount,
151 &IOSB);
152 RtlZeroMemory
153 ((PCHAR)PageBuf+RequiredResources->Amount,
154 PAGE_SIZE-RequiredResources->Amount);
155
156 DPRINT("Read Status %x (Page %x)\n", Status, *Page);
157
158 MmLockAddressSpace(MmGetKernelAddressSpace());
159 MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL);
160 MmUnlockAddressSpace(MmGetKernelAddressSpace());
161
162 if (!NT_SUCCESS(Status))
163 {
164 MmReleasePageMemoryConsumer(MC_CACHE, *Page);
165 DPRINT("Status: %x\n", Status);
166 return Status;
167 }
168
169 return STATUS_SUCCESS;
170 }
171
172 ULONG
173 NTAPI
174 MiChecksumPage(PFN_NUMBER Page, BOOLEAN Lock)
175 {
176 int i;
177 NTSTATUS Status;
178 ULONG Total = 0;
179 PULONG PageBuf = NULL;
180 PMEMORY_AREA TmpArea;
181 PHYSICAL_ADDRESS BoundaryAddressMultiple;
182
183 BoundaryAddressMultiple.QuadPart = 0;
184
185 if (Lock) MmLockAddressSpace(MmGetKernelAddressSpace());
186
187 Status = MmCreateMemoryArea
188 (MmGetKernelAddressSpace(),
189 MEMORY_AREA_VIRTUAL_MEMORY,
190 (PVOID*)&PageBuf,
191 PAGE_SIZE,
192 PAGE_READWRITE,
193 &TmpArea,
194 FALSE,
195 MEM_TOP_DOWN,
196 BoundaryAddressMultiple);
197
198 DPRINT("Status %x, PageBuf %x\n", Status, PageBuf);
199 if (!NT_SUCCESS(Status))
200 {
201 DPRINT1("STATUS_NO_MEMORY: %x\n", Status);
202 if (Lock) MmUnlockAddressSpace(MmGetKernelAddressSpace());
203 return 0;
204 }
205
206 Status = MmCreateVirtualMapping(NULL, PageBuf, PAGE_READWRITE, &Page, 1);
207 if (!NT_SUCCESS(Status))
208 {
209 MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL);
210 if (Lock) MmUnlockAddressSpace(MmGetKernelAddressSpace());
211 DPRINT1("Status: %x\n", Status);
212 return Status;
213 }
214
215 for (i = 0; i < 1024; i++) {
216 Total += PageBuf[i];
217 }
218
219 MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL);
220 if (Lock) MmUnlockAddressSpace(MmGetKernelAddressSpace());
221
222 return Total;
223 }
224
225 NTSTATUS
226 NTAPI
227 MiSwapInPage
228 (PMMSUPPORT AddressSpace,
229 PMEMORY_AREA MemoryArea,
230 PMM_REQUIRED_RESOURCES Resources)
231 {
232 NTSTATUS Status;
233
234 Status = MmRequestPageMemoryConsumer(Resources->Consumer, TRUE, &Resources->Page[Resources->Offset]);
235 if (!NT_SUCCESS(Status))
236 {
237 DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status);
238 return Status;
239 }
240
241 Status = MmReadFromSwapPage(Resources->SwapEntry, Resources->Page[Resources->Offset]);
242 if (!NT_SUCCESS(Status))
243 {
244 DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
245 return Status;
246 }
247
248 MmSetSavedSwapEntryPage(Resources->Page[Resources->Offset], Resources->SwapEntry);
249
250 DPRINT1("MiSwapInPage(%x,%x)\n", Resources->Page[Resources->Offset], Resources->SwapEntry);
251
252 return Status;
253 }
254
255 NTSTATUS
256 NTAPI
257 MiWriteFilePage
258 (PMMSUPPORT AddressSpace,
259 PMEMORY_AREA MemoryArea,
260 PMM_REQUIRED_RESOURCES Required)
261 {
262 DPRINT1("MiWriteFilePage(%x,%x)\n", Required->Page[Required->Offset], Required->FileOffset.LowPart);
263
264 return MiWriteBackPage
265 (Required->Context,
266 &Required->FileOffset,
267 PAGE_SIZE,
268 Required->Page[Required->Offset]);
269 }