* PROJECT: ReactOS kernel-mode tests
* LICENSE: GPLv2+ - See COPYING in the top level directory
* PURPOSE: Kernel-Mode Test Suite Driver
- * PROGRAMMER: Thomas Faber <thfabba@gmx.de>
+ * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
*/
#include <kmt_test.h>
#include <kmt_public.h>
#include <assert.h>
+#include <debug.h>
extern HANDLE KmtestHandle;
+/**
+ * @name KmtUserCallbackThread
+ *
+ * Thread routine which awaits callback requests from kernel-mode
+ *
+ * @return Win32 error code
+ */
+DWORD
+WINAPI
+KmtUserCallbackThread(
+ PVOID Parameter)
+{
+ DWORD Error = ERROR_SUCCESS;
+ /* TODO: RequestPacket? */
+ KMT_CALLBACK_REQUEST_PACKET RequestPacket;
+ KMT_RESPONSE Response;
+ DWORD BytesReturned;
+ HANDLE LocalKmtHandle;
+
+ UNREFERENCED_PARAMETER(Parameter);
+
+ /* concurrent IoCtls on the same (non-overlapped) handle aren't possible,
+ * so open a separate one.
+ * For more info http://www.osronline.com/showthread.cfm?link=230782 */
+ LocalKmtHandle = CreateFile(KMTEST_DEVICE_PATH, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (LocalKmtHandle == INVALID_HANDLE_VALUE)
+ error_goto(Error, cleanup);
+
+ while (1)
+ {
+ if (!DeviceIoControl(LocalKmtHandle, IOCTL_KMTEST_USERMODE_AWAIT_REQ, NULL, 0, &RequestPacket, sizeof(RequestPacket), &BytesReturned, NULL))
+ error_goto(Error, cleanup);
+ ASSERT(BytesReturned == sizeof(RequestPacket));
+
+ switch (RequestPacket.OperationClass)
+ {
+ case QueryVirtualMemory:
+ {
+ SIZE_T InfoBufferSize = VirtualQuery(RequestPacket.Parameters, &Response.MemInfo, sizeof(Response.MemInfo));
+ /* FIXME: an error is a valid result. That should go as a response to kernel mode instead of terminating the thread */
+ if (InfoBufferSize == 0)
+ error_goto(Error, cleanup);
+
+ if (!DeviceIoControl(LocalKmtHandle, IOCTL_KMTEST_USERMODE_SEND_RESPONSE, &RequestPacket.RequestId, sizeof(RequestPacket.RequestId), &Response, sizeof(Response), &BytesReturned, NULL))
+ error_goto(Error, cleanup);
+ ASSERT(BytesReturned == 0);
+
+ break;
+ }
+ default:
+ DPRINT1("Unrecognized user-mode callback request\n");
+ break;
+ }
+ }
+
+cleanup:
+ if (LocalKmtHandle != INVALID_HANDLE_VALUE)
+ CloseHandle(LocalKmtHandle);
+
+ DPRINT("Callback handler dying! Error code %lu", Error);
+ return Error;
+}
+
+
/**
* @name KmtRunKernelTest
*
KmtRunKernelTest(
IN PCSTR TestName)
{
+ HANDLE CallbackThread;
DWORD Error = ERROR_SUCCESS;
DWORD BytesRead;
+ CallbackThread = CreateThread(NULL, 0, KmtUserCallbackThread, NULL, 0, NULL);
+
if (!DeviceIoControl(KmtestHandle, IOCTL_KMTEST_RUN_TEST, (PVOID)TestName, (DWORD)strlen(TestName), NULL, 0, &BytesRead, NULL))
error(Error);
+ if (CallbackThread != NULL)
+ CloseHandle(CallbackThread);
+
return Error;
}
return ERROR_SUCCESS;
}
+/**
+ * @name KmtSendStringToDriver
+ *
+ * Unload special-purpose driver (stop the service)
+ *
+ * @param ControlCode
+ * @param String
+ *
+ * @return Win32 error code as returned by DeviceIoControl
+ */
+DWORD
+KmtSendWStringToDriver(
+ IN DWORD ControlCode,
+ IN PCWSTR String)
+{
+ DWORD BytesRead;
+
+ assert(ControlCode < 0x400);
+
+ if (!DeviceIoControl(TestDeviceHandle, KMT_MAKE_CODE(ControlCode), (PVOID)String, (DWORD)wcslen(String) * sizeof(WCHAR), NULL, 0, &BytesRead, NULL))
+ return GetLastError();
+
+ return ERROR_SUCCESS;
+}
+
/**
* @name KmtSendBufferToDriver
*