Merge from amd64-branch:
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / drvmgmt.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/drvmgmt.c
5 * PURPOSE: ARM Memory Manager Driver Management
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 #line 15 "ARMĀ³::DRVMGMT"
16 #define MODULE_INVOLVED_IN_ARM3
17 #include "../ARM3/miarm.h"
18
19 /* GLOBALS *******************************************************************/
20
21 MM_DRIVER_VERIFIER_DATA MmVerifierData;
22 LIST_ENTRY MiVerifierDriverAddedThunkListHead;
23 ULONG MiActiveVerifierThunks;
24
25 /* PRIVATE FUNCTIONS *********************************************************/
26
27 PLDR_DATA_TABLE_ENTRY
28 NTAPI
29 MiLookupDataTableEntry(IN PVOID Address)
30 {
31 PLDR_DATA_TABLE_ENTRY LdrEntry, FoundEntry = NULL;
32 PLIST_ENTRY NextEntry;
33 PAGED_CODE();
34
35 //
36 // Loop entries
37 //
38 NextEntry = PsLoadedModuleList.Flink;
39 do
40 {
41 //
42 // Get the loader entry
43 //
44 LdrEntry = CONTAINING_RECORD(NextEntry,
45 LDR_DATA_TABLE_ENTRY,
46 InLoadOrderLinks);
47
48 //
49 // Check if the address matches
50 //
51 if ((Address >= LdrEntry->DllBase) &&
52 (Address < (PVOID)((ULONG_PTR)LdrEntry->DllBase +
53 LdrEntry->SizeOfImage)))
54 {
55 //
56 // Found a match
57 //
58 FoundEntry = LdrEntry;
59 break;
60 }
61
62 //
63 // Move on
64 //
65 NextEntry = NextEntry->Flink;
66 } while(NextEntry != &PsLoadedModuleList);
67
68 //
69 // Return the entry
70 //
71 return FoundEntry;
72 }
73
74 /* PUBLIC FUNCTIONS ***********************************************************/
75
76 /*
77 * @unimplemented
78 */
79 VOID
80 NTAPI
81 MmUnlockPageableImageSection(IN PVOID ImageSectionHandle)
82 {
83 UNIMPLEMENTED;
84 }
85
86 /*
87 * @unimplemented
88 */
89 VOID
90 NTAPI
91 MmLockPageableSectionByHandle(IN PVOID ImageSectionHandle)
92 {
93 UNIMPLEMENTED;
94 }
95
96 /*
97 * @unimplemented
98 */
99 PVOID
100 NTAPI
101 MmLockPageableDataSection(IN PVOID AddressWithinSection)
102 {
103 //
104 // We should just find the section and call MmLockPageableSectionByHandle
105 //
106 UNIMPLEMENTED;
107 return AddressWithinSection;
108 }
109
110 /*
111 * @unimplemented
112 */
113 PVOID
114 NTAPI
115 MmPageEntireDriver(IN PVOID AddressWithinSection)
116 {
117 //PMMPTE StartPte, EndPte;
118 PLDR_DATA_TABLE_ENTRY LdrEntry;
119 PAGED_CODE();
120
121 //
122 // Get the loader entry
123 //
124 LdrEntry = MiLookupDataTableEntry(AddressWithinSection);
125 if (!LdrEntry) return NULL;
126
127 //
128 // Check if paging of kernel mode is disabled or if the driver is mapped as
129 // an image
130 //
131 if ((MmDisablePagingExecutive & 0x1) || (LdrEntry->SectionPointer))
132 {
133 //
134 // Don't do anything, just return the base address
135 //
136 return LdrEntry->DllBase;
137 }
138
139 //
140 // Wait for active DPCs to finish before we page out the driver
141 //
142 KeFlushQueuedDpcs();
143
144 //
145 // Get the PTE range for the whole driver image
146 //
147 //StartPte = MiGetPteAddress(LdrEntry->DllBase);
148 //EndPte = MiGetPteAddress(LdrEntry->DllBase +
149 // LdrEntry->SizeOfImage);
150
151 //
152 // Enable paging for the PTE range
153 //
154 //MiSetPagingOfDriver(StartPte, EndPte);
155
156 //
157 // Return the base address
158 //
159 return LdrEntry->DllBase;
160 }
161
162 /*
163 * @unimplemented
164 */
165 VOID
166 NTAPI
167 MmResetDriverPaging(IN PVOID AddressWithinSection)
168 {
169 UNIMPLEMENTED;
170 }
171
172 /*
173 * @unimplemented
174 */
175 ULONG
176 NTAPI
177 MmTrimAllSystemPageableMemory(IN ULONG PurgeTransitionList)
178 {
179 UNIMPLEMENTED;
180 return 0;
181 }
182
183 /*
184 * @implemented
185 */
186 NTSTATUS
187 NTAPI
188 MmAddVerifierThunks(IN PVOID ThunkBuffer,
189 IN ULONG ThunkBufferSize)
190 {
191 PDRIVER_VERIFIER_THUNK_PAIRS ThunkTable;
192 ULONG ThunkCount;
193 PDRIVER_SPECIFIED_VERIFIER_THUNKS DriverThunks;
194 PLDR_DATA_TABLE_ENTRY LdrEntry;
195 PVOID ModuleBase, ModuleEnd;
196 ULONG i;
197 NTSTATUS Status = STATUS_SUCCESS;
198 PAGED_CODE();
199
200 //
201 // Make sure the driver verifier is initialized
202 //
203 if (!MiVerifierDriverAddedThunkListHead.Flink) return STATUS_NOT_SUPPORTED;
204
205 //
206 // Get the thunk pairs and count them
207 //
208 ThunkCount = ThunkBufferSize / sizeof(DRIVER_VERIFIER_THUNK_PAIRS);
209 if (!ThunkCount) return STATUS_INVALID_PARAMETER_1;
210
211 //
212 // Now allocate our own thunk table
213 //
214 DriverThunks = ExAllocatePoolWithTag(PagedPool,
215 sizeof(*DriverThunks) +
216 ThunkCount *
217 sizeof(DRIVER_VERIFIER_THUNK_PAIRS),
218 'tVmM');
219 if (!DriverThunks) return STATUS_INSUFFICIENT_RESOURCES;
220
221 //
222 // Now copy the driver-fed part
223 //
224 ThunkTable = (PDRIVER_VERIFIER_THUNK_PAIRS)(DriverThunks + 1);
225 RtlCopyMemory(ThunkTable,
226 ThunkBuffer,
227 ThunkCount * sizeof(DRIVER_VERIFIER_THUNK_PAIRS));
228
229 //
230 // Acquire the system load lock
231 //
232 KeEnterCriticalRegion();
233 KeWaitForSingleObject(&MmSystemLoadLock,
234 WrVirtualMemory,
235 KernelMode,
236 FALSE,
237 NULL);
238
239 //
240 // Get the loader entry
241 //
242 LdrEntry = MiLookupDataTableEntry(ThunkTable->PristineRoutine);
243 if (!LdrEntry)
244 {
245 //
246 // Fail
247 //
248 Status = STATUS_INVALID_PARAMETER_2;
249 goto Cleanup;
250 }
251
252 //
253 // Get driver base and end
254 //
255 ModuleBase = LdrEntry->DllBase;
256 ModuleEnd = (PVOID)((ULONG_PTR)LdrEntry->DllBase + LdrEntry->SizeOfImage);
257
258 //
259 // Don't allow hooking the kernel or HAL
260 //
261 if (ModuleBase < (PVOID)(KSEG0_BASE + MmBootImageSize))
262 {
263 //
264 // Fail
265 //
266 Status = STATUS_INVALID_PARAMETER_2;
267 goto Cleanup;
268 }
269
270 //
271 // Loop all the thunks
272 //
273 for (i = 0; i < ThunkCount; i++)
274 {
275 //
276 // Make sure it's in the driver
277 //
278 if (((ULONG_PTR)ThunkTable->PristineRoutine < (ULONG_PTR)ModuleBase) ||
279 ((ULONG_PTR)ThunkTable->PristineRoutine >= (ULONG_PTR)ModuleEnd))
280 {
281 //
282 // Nope, fail
283 //
284 Status = STATUS_INVALID_PARAMETER_2;
285 goto Cleanup;
286 }
287 }
288
289 //
290 // Otherwise, add this entry
291 //
292 DriverThunks->DataTableEntry = LdrEntry;
293 DriverThunks->NumberOfThunks = ThunkCount;
294 MiActiveVerifierThunks++;
295 InsertTailList(&MiVerifierDriverAddedThunkListHead,
296 &DriverThunks->ListEntry);
297 DriverThunks = NULL;
298
299 Cleanup:
300 //
301 // Release the lock
302 //
303 KeReleaseMutant(&MmSystemLoadLock, 1, FALSE, FALSE);
304 KeLeaveCriticalRegion();
305
306 //
307 // Free the table if we failed and return status
308 //
309 if (DriverThunks) ExFreePool(DriverThunks);
310 return Status;
311 }
312
313 /*
314 * @implemented
315 */
316 LOGICAL
317 NTAPI
318 MmIsDriverVerifying(IN PDRIVER_OBJECT DriverObject)
319 {
320 PLDR_DATA_TABLE_ENTRY LdrEntry;
321
322 //
323 // Get the loader entry
324 //
325 LdrEntry = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection;
326 if (!LdrEntry) return FALSE;
327
328 //
329 // Check if we're verifying or not
330 //
331 return (LdrEntry->Flags & LDRP_IMAGE_VERIFYING) ? TRUE: FALSE;
332 }
333
334 /*
335 * @implemented
336 */
337 NTSTATUS
338 NTAPI
339 MmIsVerifierEnabled(OUT PULONG VerifierFlags)
340 {
341 //
342 // Check if we've actually added anything to the list
343 //
344 if (MiVerifierDriverAddedThunkListHead.Flink)
345 {
346 //
347 // We have, read the verifier level
348 //
349 *VerifierFlags = MmVerifierData.Level;
350 return STATUS_SUCCESS;
351 }
352
353 //
354 // Otherwise, we're disabled
355 //
356 *VerifierFlags = 0;
357 return STATUS_NOT_SUPPORTED;
358 }
359
360 /* EOF */