2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Loader Application
5 * PROGRAMMER: Thomas Faber <thfabba@gmx.de>
9 #define WIN32_LEAN_AND_MEAN
19 #include <kmt_public.h>
20 #define KMT_DEFINE_TEST_FUNCTIONS
23 #define SERVICE_NAME L"Kmtest"
24 #define SERVICE_PATH L"kmtest_drv.sys"
25 #define SERVICE_DESCRIPTION L"ReactOS Kernel-Mode Test Suite Driver"
27 #define RESULTBUFFER_SIZE (1024 * 1024)
38 SC_HANDLE KmtestServiceHandle
;
39 PCSTR ErrorFileAndLine
= "No error";
41 static void OutputError(IN DWORD Error
);
42 static DWORD
ListTests(IN BOOLEAN IncludeHidden
);
43 static PKMT_TESTFUNC
FindTest(IN PCSTR TestName
);
44 static DWORD
OutputResult(IN PCSTR TestName
);
45 static DWORD
RunTest(IN PCSTR TestName
);
46 int __cdecl
main(int ArgCount
, char **Arguments
);
51 * Output an error message to the console.
62 if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_ALLOCATE_BUFFER
,
63 NULL
, Error
, MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), (LPSTR
)&Message
, 0, NULL
))
65 fprintf(stderr
, "%s: Could not retrieve error message (error 0x%08lx). Original error: 0x%08lx\n",
66 ErrorFileAndLine
, GetLastError(), Error
);
70 fprintf(stderr
, "%s: error 0x%08lx: %s\n", ErrorFileAndLine
, Error
, Message
);
76 * @name CompareTestNames
78 * strcmp that skips a leading '-' on either string if present
94 while (*Str1
&& *Str1
== *Str2
)
105 * Output the list of tests to the console.
106 * The list will comprise tests as listed by the driver
107 * in addition to user-mode tests in TestList.
109 * @param IncludeHidden
110 * TRUE to include "hidden" tests prefixed with a '-'
112 * @return Win32 error code
117 IN BOOLEAN IncludeHidden
)
119 DWORD Error
= ERROR_SUCCESS
;
122 PCSTR TestName
= Buffer
;
123 PCKMT_TEST TestEntry
= TestList
;
126 puts("Valid test names:");
128 // get test list from driver
129 if (!DeviceIoControl(KmtestHandle
, IOCTL_KMTEST_GET_TESTS
, NULL
, 0, Buffer
, sizeof Buffer
, &BytesRead
, NULL
))
130 error_goto(Error
, cleanup
);
132 // output test list plus user-mode tests
133 while (TestEntry
->TestName
|| *TestName
)
135 if (!TestEntry
->TestName
)
137 NextTestName
= TestName
;
138 TestName
+= strlen(TestName
) + 1;
142 NextTestName
= TestEntry
->TestName
;
147 INT Result
= CompareTestNames(TestEntry
->TestName
, TestName
);
151 NextTestName
= TestEntry
->TestName
;
152 TestName
+= strlen(TestName
) + 1;
157 NextTestName
= TestEntry
->TestName
;
162 NextTestName
= TestName
;
163 TestName
+= strlen(TestName
) + 1;
167 if (IncludeHidden
&& NextTestName
[0] == '-')
170 if (NextTestName
[0] != '-')
171 printf(" %s\n", NextTestName
);
181 * Find a test in TestList by name.
184 * Name of the test to look for. Case sensitive
186 * @return pointer to test function, or NULL if not found
193 PCKMT_TEST TestEntry
= TestList
;
195 for (TestEntry
= TestList
; TestEntry
->TestName
; ++TestEntry
)
197 PCSTR TestEntryName
= TestEntry
->TestName
;
199 // skip leading '-' if present
200 if (*TestEntryName
== '-')
203 if (!lstrcmpA(TestEntryName
, TestName
))
207 return TestEntry
->TestFunction
;
213 * Output the test results in ResultBuffer to the console.
216 * Name of the test whose result is to be printed
218 * @return Win32 error code
225 DWORD Error
= ERROR_SUCCESS
;
228 KmtFinishTest(TestName
);
230 if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE
), ResultBuffer
->LogBuffer
, ResultBuffer
->LogBufferLength
, &BytesWritten
, NULL
))
239 * Run the named test and output its results.
242 * Name of the test to run. Case sensitive
244 * @return Win32 error code
251 DWORD Error
= ERROR_SUCCESS
;
252 PKMT_TESTFUNC TestFunction
;
255 assert(TestName
!= NULL
);
259 ResultBuffer
= KmtAllocateResultBuffer(RESULTBUFFER_SIZE
);
261 error_goto(Error
, cleanup
);
262 if (!DeviceIoControl(KmtestHandle
, IOCTL_KMTEST_SET_RESULTBUFFER
, ResultBuffer
, RESULTBUFFER_SIZE
, NULL
, 0, &BytesRead
, NULL
))
263 error_goto(Error
, cleanup
);
267 TestFunction
= FindTest(TestName
);
275 // not found in user-mode test list, call driver
276 Error
= KmtRunKernelTest(TestName
);
280 Error
= OutputResult(TestName
);
288 * Program entry point
293 * @return EXIT_SUCCESS on success, EXIT_FAILURE on failure
300 INT Status
= EXIT_SUCCESS
;
301 DWORD Error
= ERROR_SUCCESS
;
302 PCSTR AppName
= "kmtest.exe";
303 PCSTR TestName
= NULL
;
304 KMT_OPERATION Operation
= KMT_DO_NOTHING
;
305 BOOLEAN ShowHidden
= FALSE
;
307 Error
= KmtServiceInit();
312 AppName
= Arguments
[0];
316 printf("Usage: %s <test_name> - run the specified test (creates/starts the driver(s) as appropriate)\n", AppName
);
317 printf(" %s --list - list available tests\n", AppName
);
318 printf(" %s --list-all - list available tests, including hidden\n", AppName
);
319 printf(" %s <create|delete|start|stop> - manage the kmtest driver\n\n", AppName
);
320 Operation
= KMT_LIST_TESTS
;
324 TestName
= Arguments
[1];
325 if (!lstrcmpA(TestName
, "create"))
326 Error
= KmtCreateService(SERVICE_NAME
, SERVICE_PATH
, SERVICE_DESCRIPTION
, &KmtestServiceHandle
);
327 else if (!lstrcmpA(TestName
, "delete"))
328 Error
= KmtDeleteService(SERVICE_NAME
, &KmtestServiceHandle
);
329 else if (!lstrcmpA(TestName
, "start"))
330 Error
= KmtStartService(SERVICE_NAME
, &KmtestServiceHandle
);
331 else if (!lstrcmpA(TestName
, "stop"))
332 Error
= KmtStopService(SERVICE_NAME
, &KmtestServiceHandle
);
334 else if (!lstrcmpA(TestName
, "--list"))
335 Operation
= KMT_LIST_TESTS
;
336 else if (!lstrcmpA(TestName
, "--list-all"))
337 Operation
= KMT_LIST_ALL_TESTS
;
339 Operation
= KMT_RUN_TEST
;
344 Error
= KmtCreateAndStartService(SERVICE_NAME
, SERVICE_PATH
, SERVICE_DESCRIPTION
, &KmtestServiceHandle
, FALSE
);
348 KmtestHandle
= CreateFile(KMTEST_DEVICE_PATH
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
349 if (KmtestHandle
== INVALID_HANDLE_VALUE
)
350 error_goto(Error
, cleanup
);
354 case KMT_LIST_ALL_TESTS
:
358 Error
= ListTests(ShowHidden
);
361 Error
= RunTest(TestName
);
370 CloseHandle(KmtestHandle
);
373 KmtFreeResultBuffer(ResultBuffer
);
375 KmtCloseService(&KmtestServiceHandle
);
378 KmtServiceCleanup(TRUE
);
380 Error
= KmtServiceCleanup(FALSE
);
386 Status
= EXIT_FAILURE
;