2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Driver
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
11 #include <kmt_public.h>
16 extern HANDLE KmtestHandle
;
19 * @name KmtUserCallbackThread
21 * Thread routine which awaits callback requests from kernel-mode
23 * @return Win32 error code
27 KmtUserCallbackThread(
30 DWORD Error
= ERROR_SUCCESS
;
31 /* TODO: RequestPacket? */
32 KMT_CALLBACK_REQUEST_PACKET RequestPacket
;
33 KMT_RESPONSE Response
;
35 HANDLE LocalKmtHandle
;
37 UNREFERENCED_PARAMETER(Parameter
);
39 /* concurrent IoCtls on the same (non-overlapped) handle aren't possible,
40 * so open a separate one.
41 * For more info http://www.osronline.com/showthread.cfm?link=230782 */
42 LocalKmtHandle
= CreateFile(KMTEST_DEVICE_PATH
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
43 if (LocalKmtHandle
== INVALID_HANDLE_VALUE
)
44 error_goto(Error
, cleanup
);
48 if (!DeviceIoControl(LocalKmtHandle
, IOCTL_KMTEST_USERMODE_AWAIT_REQ
, NULL
, 0, &RequestPacket
, sizeof(RequestPacket
), &BytesReturned
, NULL
))
49 error_goto(Error
, cleanup
);
50 ASSERT(BytesReturned
== sizeof(RequestPacket
));
52 switch (RequestPacket
.OperationClass
)
54 case QueryVirtualMemory
:
56 SIZE_T InfoBufferSize
= VirtualQuery(RequestPacket
.Parameters
, &Response
.MemInfo
, sizeof(Response
.MemInfo
));
57 /* FIXME: an error is a valid result. That should go as a response to kernel mode instead of terminating the thread */
58 if (InfoBufferSize
== 0)
59 error_goto(Error
, cleanup
);
61 if (!DeviceIoControl(LocalKmtHandle
, IOCTL_KMTEST_USERMODE_SEND_RESPONSE
, &RequestPacket
.RequestId
, sizeof(RequestPacket
.RequestId
), &Response
, sizeof(Response
), &BytesReturned
, NULL
))
62 error_goto(Error
, cleanup
);
63 ASSERT(BytesReturned
== 0);
68 DPRINT1("Unrecognized user-mode callback request\n");
74 if (LocalKmtHandle
!= INVALID_HANDLE_VALUE
)
75 CloseHandle(LocalKmtHandle
);
77 DPRINT("Callback handler dying! Error code %lu", Error
);
83 * @name KmtRunKernelTest
85 * Run the specified kernel-mode test part
88 * Name of the test to run
90 * @return Win32 error code as returned by DeviceIoControl
96 HANDLE CallbackThread
;
97 DWORD Error
= ERROR_SUCCESS
;
100 CallbackThread
= CreateThread(NULL
, 0, KmtUserCallbackThread
, NULL
, 0, NULL
);
102 if (!DeviceIoControl(KmtestHandle
, IOCTL_KMTEST_RUN_TEST
, (PVOID
)TestName
, (DWORD
)strlen(TestName
), NULL
, 0, &BytesRead
, NULL
))
105 if (CallbackThread
!= NULL
)
106 CloseHandle(CallbackThread
);
111 static WCHAR TestServiceName
[MAX_PATH
];
112 static SC_HANDLE TestServiceHandle
;
113 static HANDLE TestDeviceHandle
;
116 * @name KmtLoadDriver
118 * Load the specified special-purpose driver (create/start the service)
121 * Name of the driver service (Kmtest- prefix will be added automatically)
122 * @param RestartIfRunning
123 * TRUE to stop and restart the service if it is already running
127 IN PCWSTR ServiceName
,
128 IN BOOLEAN RestartIfRunning
)
130 DWORD Error
= ERROR_SUCCESS
;
131 WCHAR ServicePath
[MAX_PATH
];
133 StringCbCopy(ServicePath
, sizeof ServicePath
, ServiceName
);
134 StringCbCat(ServicePath
, sizeof ServicePath
, L
"_drv.sys");
136 StringCbCopy(TestServiceName
, sizeof TestServiceName
, L
"Kmtest-");
137 StringCbCat(TestServiceName
, sizeof TestServiceName
, ServiceName
);
139 Error
= KmtCreateAndStartService(TestServiceName
, ServicePath
, NULL
, &TestServiceHandle
, RestartIfRunning
);
149 * @name KmtUnloadDriver
151 * Unload special-purpose driver (stop the service)
154 KmtUnloadDriver(VOID
)
156 DWORD Error
= ERROR_SUCCESS
;
158 Error
= KmtStopService(TestServiceName
, &TestServiceHandle
);
168 * @name KmtOpenDriver
170 * Open special-purpose driver (acquire a device handle)
175 DWORD Error
= ERROR_SUCCESS
;
176 WCHAR DevicePath
[MAX_PATH
];
178 StringCbCopy(DevicePath
, sizeof DevicePath
, L
"\\\\.\\Global\\GLOBALROOT\\Device\\");
179 StringCbCat(DevicePath
, sizeof DevicePath
, TestServiceName
);
181 TestDeviceHandle
= CreateFile(DevicePath
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
182 if (TestDeviceHandle
== INVALID_HANDLE_VALUE
)
194 * @name KmtCloseDriver
196 * Close special-purpose driver (close device handle)
201 DWORD Error
= ERROR_SUCCESS
;
203 if (TestDeviceHandle
&& !CloseHandle(TestDeviceHandle
))
214 * @name KmtSendToDriver
216 * Unload special-purpose driver (stop the service)
220 * @return Win32 error code as returned by DeviceIoControl
224 IN DWORD ControlCode
)
228 assert(ControlCode
< 0x400);
230 if (!DeviceIoControl(TestDeviceHandle
, KMT_MAKE_CODE(ControlCode
), NULL
, 0, NULL
, 0, &BytesRead
, NULL
))
231 return GetLastError();
233 return ERROR_SUCCESS
;
237 * @name KmtSendStringToDriver
239 * Unload special-purpose driver (stop the service)
244 * @return Win32 error code as returned by DeviceIoControl
247 KmtSendStringToDriver(
248 IN DWORD ControlCode
,
253 assert(ControlCode
< 0x400);
255 if (!DeviceIoControl(TestDeviceHandle
, KMT_MAKE_CODE(ControlCode
), (PVOID
)String
, (DWORD
)strlen(String
), NULL
, 0, &BytesRead
, NULL
))
256 return GetLastError();
258 return ERROR_SUCCESS
;
262 * @name KmtSendStringToDriver
264 * Unload special-purpose driver (stop the service)
269 * @return Win32 error code as returned by DeviceIoControl
272 KmtSendWStringToDriver(
273 IN DWORD ControlCode
,
278 assert(ControlCode
< 0x400);
280 if (!DeviceIoControl(TestDeviceHandle
, KMT_MAKE_CODE(ControlCode
), (PVOID
)String
, (DWORD
)wcslen(String
) * sizeof(WCHAR
), NULL
, 0, &BytesRead
, NULL
))
281 return GetLastError();
283 return ERROR_SUCCESS
;
287 * @name KmtSendBufferToDriver
294 * @return Win32 error code as returned by DeviceIoControl
297 KmtSendBufferToDriver(
298 IN DWORD ControlCode
,
299 IN OUT PVOID Buffer OPTIONAL
,
301 IN OUT PDWORD OutLength
)
304 assert(Buffer
|| (!InLength
&& !*OutLength
));
305 assert(ControlCode
< 0x400);
307 if (!DeviceIoControl(TestDeviceHandle
, KMT_MAKE_CODE(ControlCode
), Buffer
, InLength
, Buffer
, *OutLength
, OutLength
, NULL
))
308 return GetLastError();
310 return ERROR_SUCCESS
;