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