95d1eec192807c83211a53ab69a3f2630f2d7e7a
[reactos.git] / rostests / kmtests / ntos_mm / MmMapLockedPagesSpecifyCache_drv.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test driver for MmMapLockedPagesSpecifyCache function
5 * PROGRAMMER: Pierre Schweitzer <pierre@reactos.org>
6 */
7
8 #include <kmt_test.h>
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #include "MmMapLockedPagesSpecifyCache.h"
14
15 static KMT_IRP_HANDLER TestIrpHandler;
16 static KMT_MESSAGE_HANDLER TestMessageHandler;
17
18 static PVOID CurrentBuffer;
19 static PMDL CurrentMdl;
20 static PVOID CurrentUser;
21 static SIZE_T NonCachedLength;
22
23 NTSTATUS
24 TestEntry(
25 IN PDRIVER_OBJECT DriverObject,
26 IN PCUNICODE_STRING RegistryPath,
27 OUT PCWSTR *DeviceName,
28 IN OUT INT *Flags)
29 {
30 NTSTATUS Status = STATUS_SUCCESS;
31
32 PAGED_CODE();
33
34 UNREFERENCED_PARAMETER(RegistryPath);
35 UNREFERENCED_PARAMETER(Flags);
36
37 *DeviceName = L"MmMapLockedPagesSpecifyCache";
38
39 KmtRegisterIrpHandler(IRP_MJ_CLEANUP, NULL, TestIrpHandler);
40 KmtRegisterMessageHandler(0, NULL, TestMessageHandler);
41
42 return Status;
43 }
44
45 VOID
46 TestUnload(
47 IN PDRIVER_OBJECT DriverObject)
48 {
49 PAGED_CODE();
50 }
51
52 VOID
53 TestCleanEverything(VOID)
54 {
55 NTSTATUS SehStatus;
56
57 if (CurrentMdl == NULL)
58 {
59 return;
60 }
61
62 if (CurrentUser != NULL)
63 {
64 SehStatus = STATUS_SUCCESS;
65 _SEH2_TRY
66 {
67 MmUnmapLockedPages(CurrentUser, CurrentMdl);
68 }
69 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
70 {
71 SehStatus = _SEH2_GetExceptionCode();
72 }
73 _SEH2_END;
74 ok_eq_hex(SehStatus, STATUS_SUCCESS);
75 CurrentUser = NULL;
76 }
77
78 SehStatus = STATUS_SUCCESS;
79 _SEH2_TRY
80 {
81 MmUnlockPages(CurrentMdl);
82 }
83 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
84 {
85 SehStatus = _SEH2_GetExceptionCode();
86 }
87 _SEH2_END;
88 ok_eq_hex(SehStatus, STATUS_SUCCESS);
89 IoFreeMdl(CurrentMdl);
90 if (NonCachedLength)
91 {
92 MmFreeNonCachedMemory(CurrentBuffer, NonCachedLength);
93 }
94 else
95 {
96 ExFreePoolWithTag(CurrentBuffer, 'MLPC');
97 }
98 CurrentMdl = NULL;
99 }
100
101 static
102 NTSTATUS
103 TestMessageHandler(
104 IN PDEVICE_OBJECT DeviceObject,
105 IN ULONG ControlCode,
106 IN PVOID Buffer OPTIONAL,
107 IN SIZE_T InLength,
108 IN OUT PSIZE_T OutLength)
109 {
110 NTSTATUS Status = STATUS_SUCCESS;
111 NTSTATUS SehStatus;
112
113 switch (ControlCode)
114 {
115 case IOCTL_QUERY_BUFFER:
116 {
117 ok(Buffer != NULL, "Buffer is NULL\n");
118 ok_eq_size(InLength, sizeof(QUERY_BUFFER));
119 ok_eq_size(*OutLength, sizeof(QUERY_BUFFER));
120 ok_eq_pointer(CurrentMdl, NULL);
121
122 TestCleanEverything();
123
124 ok(ExGetPreviousMode() == UserMode, "Not comming from umode!\n");
125 if (!skip(Buffer && InLength >= sizeof(QUERY_BUFFER) && *OutLength >= sizeof(QUERY_BUFFER), "Cannot read/write from/to buffer!\n"))
126 {
127 PQUERY_BUFFER QueryBuffer;
128 USHORT Length;
129 MEMORY_CACHING_TYPE CacheType;
130
131 QueryBuffer = Buffer;
132 CacheType = (QueryBuffer->Cached ? MmCached : MmNonCached);
133 Length = QueryBuffer->Length;
134 CurrentUser = NULL;
135 ok(Length > 0, "Null size!\n");
136
137 if (!skip(Length > 0, "Null size!\n"))
138 {
139 if (QueryBuffer->Cached)
140 {
141 CurrentBuffer = ExAllocatePoolWithTag(NonPagedPool, Length, 'MLPC');
142 ok(CurrentBuffer != NULL, "ExAllocatePool failed!\n");
143 NonCachedLength = 0;
144 }
145 else
146 {
147 CurrentBuffer = MmAllocateNonCachedMemory(Length);
148 ok(CurrentBuffer != NULL, "MmAllocateNonCachedMemory failed!\n");
149 if (CurrentBuffer)
150 {
151 RtlZeroMemory(CurrentBuffer, Length);
152 NonCachedLength = Length;
153 }
154 }
155 if (!skip(CurrentBuffer != NULL, "ExAllocatePool failed!\n"))
156 {
157 CurrentMdl = IoAllocateMdl(CurrentBuffer, Length, FALSE, FALSE, NULL);
158 ok(CurrentMdl != NULL, "IoAllocateMdl failed!\n");
159 if (!skip(CurrentMdl != NULL, "IoAllocateMdl failed!\n"))
160 {
161 KIRQL Irql;
162
163 SehStatus = STATUS_SUCCESS;
164 _SEH2_TRY
165 {
166 MmProbeAndLockPages(CurrentMdl, KernelMode, IoWriteAccess);
167 }
168 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
169 {
170 SehStatus = _SEH2_GetExceptionCode();
171 }
172 _SEH2_END;
173 ok_eq_hex(SehStatus, STATUS_SUCCESS);
174
175 Irql = KeGetCurrentIrql();
176 ok(Irql <= APC_LEVEL, "IRQL > APC_LEVEL: %d\n", Irql);
177
178 SehStatus = STATUS_SUCCESS;
179 _SEH2_TRY
180 {
181 CurrentUser = MmMapLockedPagesSpecifyCache(CurrentMdl, UserMode, CacheType, NULL, FALSE, NormalPagePriority);
182 }
183 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
184 {
185 SehStatus = _SEH2_GetExceptionCode();
186 }
187 _SEH2_END;
188 ok_eq_hex(SehStatus, STATUS_SUCCESS);
189 ok(CurrentUser != NULL, "MmMapLockedPagesSpecifyCache failed!\n");
190 }
191 else
192 {
193 ExFreePoolWithTag(CurrentBuffer, 'MLPC');
194 }
195 }
196 }
197
198 QueryBuffer->Buffer = CurrentUser;
199 *OutLength = sizeof(QUERY_BUFFER);
200 }
201
202 break;
203 }
204 case IOCTL_READ_BUFFER:
205 {
206 ok(Buffer != NULL, "Buffer is NULL\n");
207 ok_eq_size(InLength, sizeof(READ_BUFFER));
208 ok_eq_size(*OutLength, 0);
209 ok(CurrentMdl != NULL, "MDL is not in use!\n");
210
211 if (!skip(Buffer && InLength >= sizeof(QUERY_BUFFER), "Cannot read from buffer!\n"))
212 {
213 PREAD_BUFFER ReadBuffer;
214
215 ReadBuffer = Buffer;
216 if (!skip(ReadBuffer && ReadBuffer->Buffer == CurrentUser, "Cannot find matching MDL\n"))
217 {
218 if (ReadBuffer->Buffer != NULL)
219 {
220 USHORT i;
221 PULONG KBuffer = MmGetSystemAddressForMdlSafe(CurrentMdl, NormalPagePriority);
222 ok(KBuffer != NULL, "Failed to get kmode ptr\n");
223 ok(ReadBuffer->Length % sizeof(ULONG) == 0, "Invalid size: %d\n", ReadBuffer->Length);
224
225 if (!skip(Buffer != NULL, "Failed to get kmode ptr\n"))
226 {
227 for (i = 0; i < ReadBuffer->Length / sizeof(ULONG); ++i)
228 {
229 ok_eq_ulong(KBuffer[i], ReadBuffer->Pattern);
230 }
231 }
232 }
233 }
234
235 TestCleanEverything();
236 }
237
238 break;
239 }
240 default:
241 ok(0, "Got an unknown message! DeviceObject=%p, ControlCode=%lu, Buffer=%p, In=%lu, Out=%lu bytes\n",
242 DeviceObject, ControlCode, Buffer, InLength, *OutLength);
243 break;
244 }
245
246 return Status;
247 }
248
249 static
250 NTSTATUS
251 TestIrpHandler(
252 _In_ PDEVICE_OBJECT DeviceObject,
253 _In_ PIRP Irp,
254 _In_ PIO_STACK_LOCATION IoStack)
255 {
256 NTSTATUS Status;
257
258 PAGED_CODE();
259
260 DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction);
261 ASSERT(IoStack->MajorFunction == IRP_MJ_CLEANUP);
262
263 Status = STATUS_NOT_SUPPORTED;
264 Irp->IoStatus.Information = 0;
265
266 if (IoStack->MajorFunction == IRP_MJ_CLEANUP)
267 {
268 TestCleanEverything();
269 Status = STATUS_SUCCESS;
270 }
271
272 if (Status == STATUS_PENDING)
273 {
274 IoMarkIrpPending(Irp);
275 IoCompleteRequest(Irp, IO_NO_INCREMENT);
276 Status = STATUS_PENDING;
277 }
278 else
279 {
280 Irp->IoStatus.Status = Status;
281 IoCompleteRequest(Irp, IO_NO_INCREMENT);
282 }
283
284 return Status;
285 }