2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4 * PURPOSE: Kernel-Mode Test Suite user-mode support routines
5 * COPYRIGHT: Copyright 2011-2018 Thomas Faber <thomas.faber@reactos.org>
6 * Copyright 2013 Nikolay Borisov <nib9@aber.ac.uk>
12 #include <kmt_public.h>
17 extern HANDLE KmtestHandle
;
20 * @name KmtUserCallbackThread
22 * Thread routine which awaits callback requests from kernel-mode
24 * @return Win32 error code
28 KmtUserCallbackThread(
31 DWORD Error
= ERROR_SUCCESS
;
32 /* TODO: RequestPacket? */
33 KMT_CALLBACK_REQUEST_PACKET RequestPacket
;
34 KMT_RESPONSE Response
;
36 HANDLE LocalKmtHandle
;
38 UNREFERENCED_PARAMETER(Parameter
);
40 /* concurrent IoCtls on the same (non-overlapped) handle aren't possible,
41 * so open a separate one.
42 * For more info http://www.osronline.com/showthread.cfm?link=230782 */
43 LocalKmtHandle
= CreateFile(KMTEST_DEVICE_PATH
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
44 if (LocalKmtHandle
== INVALID_HANDLE_VALUE
)
45 error_goto(Error
, cleanup
);
49 if (!DeviceIoControl(LocalKmtHandle
, IOCTL_KMTEST_USERMODE_AWAIT_REQ
, NULL
, 0, &RequestPacket
, sizeof(RequestPacket
), &BytesReturned
, NULL
))
50 error_goto(Error
, cleanup
);
51 ASSERT(BytesReturned
== sizeof(RequestPacket
));
53 switch (RequestPacket
.OperationClass
)
55 case QueryVirtualMemory
:
57 SIZE_T InfoBufferSize
= VirtualQuery(RequestPacket
.Parameters
, &Response
.MemInfo
, sizeof(Response
.MemInfo
));
58 /* FIXME: an error is a valid result. That should go as a response to kernel mode instead of terminating the thread */
59 if (InfoBufferSize
== 0)
60 error_goto(Error
, cleanup
);
62 if (!DeviceIoControl(LocalKmtHandle
, IOCTL_KMTEST_USERMODE_SEND_RESPONSE
, &RequestPacket
.RequestId
, sizeof(RequestPacket
.RequestId
), &Response
, sizeof(Response
), &BytesReturned
, NULL
))
63 error_goto(Error
, cleanup
);
64 ASSERT(BytesReturned
== 0);
69 DPRINT1("Unrecognized user-mode callback request\n");
75 if (LocalKmtHandle
!= INVALID_HANDLE_VALUE
)
76 CloseHandle(LocalKmtHandle
);
78 DPRINT("Callback handler dying! Error code %lu", Error
);
84 * @name KmtRunKernelTest
86 * Run the specified kernel-mode test part
89 * Name of the test to run
91 * @return Win32 error code as returned by DeviceIoControl
97 HANDLE CallbackThread
;
98 DWORD Error
= ERROR_SUCCESS
;
101 CallbackThread
= CreateThread(NULL
, 0, KmtUserCallbackThread
, NULL
, 0, NULL
);
103 if (!DeviceIoControl(KmtestHandle
, IOCTL_KMTEST_RUN_TEST
, (PVOID
)TestName
, (DWORD
)strlen(TestName
), NULL
, 0, &BytesRead
, NULL
))
106 if (CallbackThread
!= NULL
)
107 CloseHandle(CallbackThread
);
112 static WCHAR TestServiceName
[MAX_PATH
];
113 static SC_HANDLE TestServiceHandle
;
114 static HANDLE TestDeviceHandle
;
117 * @name KmtLoadDriver
119 * Load the specified special-purpose driver (create/start the service)
122 * Name of the driver service (Kmtest- prefix will be added automatically)
123 * @param RestartIfRunning
124 * TRUE to stop and restart the service if it is already running
128 IN PCWSTR ServiceName
,
129 IN BOOLEAN RestartIfRunning
)
131 DWORD Error
= ERROR_SUCCESS
;
132 WCHAR ServicePath
[MAX_PATH
];
134 StringCbCopyW(ServicePath
, sizeof(ServicePath
), ServiceName
);
135 StringCbCatW(ServicePath
, sizeof(ServicePath
), L
"_drv.sys");
137 StringCbCopyW(TestServiceName
, sizeof(TestServiceName
), L
"Kmtest-");
138 StringCbCatW(TestServiceName
, sizeof(TestServiceName
), ServiceName
);
140 Error
= KmtCreateAndStartService(TestServiceName
, ServicePath
, NULL
, &TestServiceHandle
, RestartIfRunning
);
150 * @name KmtUnloadDriver
152 * Unload special-purpose driver (stop the service)
155 KmtUnloadDriver(VOID
)
157 DWORD Error
= ERROR_SUCCESS
;
159 Error
= KmtStopService(TestServiceName
, &TestServiceHandle
);
169 * @name KmtOpenDriver
171 * Open special-purpose driver (acquire a device handle)
176 DWORD Error
= ERROR_SUCCESS
;
177 WCHAR DevicePath
[MAX_PATH
];
179 StringCbCopyW(DevicePath
, sizeof(DevicePath
), L
"\\\\.\\Global\\GLOBALROOT\\Device\\");
180 StringCbCatW(DevicePath
, sizeof(DevicePath
), TestServiceName
);
182 TestDeviceHandle
= CreateFile(DevicePath
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
183 if (TestDeviceHandle
== INVALID_HANDLE_VALUE
)
195 * @name KmtCloseDriver
197 * Close special-purpose driver (close device handle)
202 DWORD Error
= ERROR_SUCCESS
;
204 if (TestDeviceHandle
&& !CloseHandle(TestDeviceHandle
))
215 * @name KmtSendToDriver
217 * Send an I/O control message with no arguments to the driver opened with KmtOpenDriver
221 * @return Win32 error code as returned by DeviceIoControl
225 IN DWORD ControlCode
)
229 assert(ControlCode
< 0x400);
231 if (!DeviceIoControl(TestDeviceHandle
, KMT_MAKE_CODE(ControlCode
), NULL
, 0, NULL
, 0, &BytesRead
, NULL
))
232 return GetLastError();
234 return ERROR_SUCCESS
;
238 * @name KmtSendStringToDriver
240 * Send an I/O control message with a string argument to the driver opened with KmtOpenDriver
245 * @return Win32 error code as returned by DeviceIoControl
248 KmtSendStringToDriver(
249 IN DWORD ControlCode
,
254 assert(ControlCode
< 0x400);
256 if (!DeviceIoControl(TestDeviceHandle
, KMT_MAKE_CODE(ControlCode
), (PVOID
)String
, (DWORD
)strlen(String
), NULL
, 0, &BytesRead
, NULL
))
257 return GetLastError();
259 return ERROR_SUCCESS
;
263 * @name KmtSendWStringToDriver
265 * Send an I/O control message with a wide string argument to the driver opened with KmtOpenDriver
270 * @return Win32 error code as returned by DeviceIoControl
273 KmtSendWStringToDriver(
274 IN DWORD ControlCode
,
279 assert(ControlCode
< 0x400);
281 if (!DeviceIoControl(TestDeviceHandle
, KMT_MAKE_CODE(ControlCode
), (PVOID
)String
, (DWORD
)wcslen(String
) * sizeof(WCHAR
), NULL
, 0, &BytesRead
, NULL
))
282 return GetLastError();
284 return ERROR_SUCCESS
;
288 * @name KmtSendUlongToDriver
290 * Send an I/O control message with an integer argument to the driver opened with KmtOpenDriver
295 * @return Win32 error code as returned by DeviceIoControl
298 KmtSendUlongToDriver(
299 IN DWORD ControlCode
,
304 assert(ControlCode
< 0x400);
306 if (!DeviceIoControl(TestDeviceHandle
, KMT_MAKE_CODE(ControlCode
), &Value
, sizeof(Value
), NULL
, 0, &BytesRead
, NULL
))
307 return GetLastError();
309 return ERROR_SUCCESS
;
313 * @name KmtSendBufferToDriver
315 * Send an I/O control message with the specified arguments to the driver opened with KmtOpenDriver
322 * @return Win32 error code as returned by DeviceIoControl
325 KmtSendBufferToDriver(
326 IN DWORD ControlCode
,
327 IN OUT PVOID Buffer OPTIONAL
,
329 IN OUT PDWORD OutLength
)
332 assert(Buffer
|| (!InLength
&& !*OutLength
));
333 assert(ControlCode
< 0x400);
335 if (!DeviceIoControl(TestDeviceHandle
, KMT_MAKE_CODE(ControlCode
), Buffer
, InLength
, Buffer
, *OutLength
, OutLength
, NULL
))
336 return GetLastError();
338 return ERROR_SUCCESS
;