ReactOS 0.4.16-dev-1278-gd809cd0
kmtest.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4 * PURPOSE: Kernel-Mode Test Suite loader application
5 * COPYRIGHT: Copyright 2011-2018 Thomas Faber <thomas.faber@reactos.org>
6 */
7
8#define KMT_DEFINE_TEST_FUNCTIONS
9#include <kmt_test.h>
10
11#include "kmtest.h"
12#include <kmt_public.h>
13
14#include <assert.h>
15#include <stdio.h>
16#include <stdlib.h>
17
18#define SERVICE_NAME L"Kmtest"
19#define SERVICE_PATH L"kmtest_drv.sys"
20#define SERVICE_DESCRIPTION L"ReactOS Kernel-Mode Test Suite Driver"
21
22#define RESULTBUFFER_SIZE (1024 * 1024)
23
24typedef enum
25{
31
35
36static void OutputError(IN DWORD Error);
37static DWORD ListTests(IN BOOLEAN IncludeHidden);
41int __cdecl main(int ArgCount, char **Arguments);
42
51static
52void
55{
59 {
60 fprintf(stderr, "%s: Could not retrieve error message (error 0x%08lx). Original error: 0x%08lx\n",
62 return;
63 }
64
65 fprintf(stderr, "%s: error 0x%08lx: %s\n", ErrorFileAndLine, Error, Message);
66
68}
69
79static
80INT
82 IN PCSTR Str1,
83 IN PCSTR Str2)
84{
85 if (*Str1 == '-')
86 ++Str1;
87 if (*Str2 == '-')
88 ++Str2;
89 while (*Str1 && *Str1 == *Str2)
90 {
91 ++Str1;
92 ++Str2;
93 }
94 return *Str1 - *Str2;
95}
96
109static
110DWORD
112 IN BOOLEAN IncludeHidden)
113{
115 PSTR Buffer = NULL;
116 DWORD BufferSize = 1024;
120 PCSTR NextTestName;
121
122 puts("Valid test names:");
123
124 // get test list from driver
125 while (TRUE)
126 {
128 if (!Buffer)
130
133 if (BytesRead < BufferSize)
134 break;
135
137 BufferSize *= 2;
138 }
139
140 // output test list plus user-mode tests
142 while (TestEntry->TestName || *TestName)
143 {
144 if (!TestEntry->TestName)
145 {
146 NextTestName = TestName;
147 TestName += strlen(TestName) + 1;
148 }
149 else if (!*TestName)
150 {
151 NextTestName = TestEntry->TestName;
152 ++TestEntry;
153 }
154 else
155 {
157
158 if (Result == 0)
159 {
160 NextTestName = TestEntry->TestName;
161 TestName += strlen(TestName) + 1;
162 ++TestEntry;
163 }
164 else if (Result < 0)
165 {
166 NextTestName = TestEntry->TestName;
167 ++TestEntry;
168 }
169 else
170 {
171 NextTestName = TestName;
172 TestName += strlen(TestName) + 1;
173 }
174 }
175
176 if (IncludeHidden && NextTestName[0] == '-')
177 ++NextTestName;
178
179 if (NextTestName[0] != '-')
180 printf(" %s\n", NextTestName);
181 }
182
183cleanup:
184 if (Buffer)
186
187 return Error;
188}
189
200static
204{
206
207 for (TestEntry = TestList; TestEntry->TestName; ++TestEntry)
208 {
209 PCSTR TestEntryName = TestEntry->TestName;
210
211 // skip leading '-' if present
212 if (*TestEntryName == '-')
213 ++TestEntryName;
214
215 if (!lstrcmpA(TestEntryName, TestName))
216 break;
217 }
218
219 return TestEntry->TestFunction;
220}
221
232static
233DWORD
236{
239 DWORD LogBufferLength;
240 DWORD Offset = 0;
241 /* A console window can't handle a single
242 * huge block of data, so split it up */
243 const DWORD BlockSize = 8 * 1024;
244
245 KmtFinishTest(TestName);
246
247 LogBufferLength = ResultBuffer->LogBufferLength;
248 for (Offset = 0; Offset < LogBufferLength; Offset += BlockSize)
249 {
250 DWORD Length = min(LogBufferLength - Offset, BlockSize);
252 error(Error);
253 }
254
255 return Error;
256}
257
268static
269DWORD
272{
276
277 assert(TestName != NULL);
278
279 if (!ResultBuffer)
280 {
282 if (!ResultBuffer)
286 }
287
288 // check test list
290
291 if (TestFunction)
292 {
293 TestFunction();
294 goto cleanup;
295 }
296
297 // not found in user-mode test list, call driver
299
300cleanup:
301 if (!Error)
303
304 return Error;
305}
306
317int
319 int ArgCount,
320 char **Arguments)
321{
324 PCSTR AppName = "kmtest.exe";
327 BOOLEAN ShowHidden = FALSE;
328
330 if (Error)
331 goto cleanup;
332
333 if (ArgCount >= 1)
334 AppName = Arguments[0];
335
336 if (ArgCount <= 1)
337 {
338 printf("Usage: %s <test_name> - run the specified test (creates/starts the driver(s) as appropriate)\n", AppName);
339 printf(" %s --list - list available tests\n", AppName);
340 printf(" %s --list-all - list available tests, including hidden\n", AppName);
341 printf(" %s <create|delete|start|stop> - manage the kmtest driver\n\n", AppName);
343 }
344 else
345 {
346 TestName = Arguments[1];
347 if (!lstrcmpA(TestName, "create"))
349 else if (!lstrcmpA(TestName, "delete"))
351 else if (!lstrcmpA(TestName, "start"))
353 else if (!lstrcmpA(TestName, "stop"))
355
356 else if (!lstrcmpA(TestName, "--list"))
358 else if (!lstrcmpA(TestName, "--list-all"))
360 else
362 }
363
364 if (Operation)
365 {
367 if (Error)
368 goto cleanup;
369
373
374 switch (Operation)
375 {
377 ShowHidden = TRUE;
378 /* fall through */
379 case KMT_LIST_TESTS:
380 Error = ListTests(ShowHidden);
381 break;
382 case KMT_RUN_TEST:
384 break;
385 default:
386 assert(FALSE);
387 }
388 }
389
390cleanup:
391 if (KmtestHandle)
393
394 if (ResultBuffer)
396
398
399 if (Error)
401 else
403
404 if (Error)
405 {
407
409 }
410
411 return Status;
412}
DWORD KmtStartService(IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:217
static KSTART_ROUTINE RunTest
Definition: NpfsConnect.c:238
unsigned char BOOLEAN
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define __cdecl
Definition: accygwin.h:79
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
BOOL Error
Definition: chkdsk.c:66
Definition: bufpool.h:45
int puts(const char *string)
Definition: crtsupp.c:23
#define BufferSize
Definition: mmc.h:75
static CHAR AppName[MAX_PATH]
Definition: dem.c:252
#define ERROR_SUCCESS
Definition: deptool.c:10
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define GENERIC_READ
Definition: compat.h:135
#define HeapFree(x, y, z)
Definition: compat.h:735
static void cleanup(void)
Definition: main.c:1335
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
DWORD WINAPI FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:483
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4195
static const WCHAR Message[]
Definition: register.c:74
#define assert(x)
Definition: debug.h:53
int main()
Definition: test.c:6
unsigned long DWORD
Definition: ntddk_ex.h:95
FP_OP Operation
Definition: fpcontrol.c:150
#define printf
Definition: freeldr.h:97
Status
Definition: gdiplustypes.h:25
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
#define EXIT_FAILURE
Definition: jerror.c:33
#define IOCTL_KMTEST_GET_TESTS
Definition: kmt_public.h:13
#define KMTEST_DEVICE_PATH
Definition: kmt_public.h:35
#define IOCTL_KMTEST_SET_RESULTBUFFER
Definition: kmt_public.h:19
KMT_TESTFUNC * PKMT_TESTFUNC
Definition: kmt_test.h:22
PKMT_RESULTBUFFER ResultBuffer
static VOID KmtFreeResultBuffer(PKMT_RESULTBUFFER Buffer)
Definition: kmt_test_user.h:30
static PKMT_RESULTBUFFER KmtAllocateResultBuffer(SIZE_T ResultBufferSize)
Definition: kmt_test_user.h:15
static DWORD ListTests(IN BOOLEAN IncludeHidden)
Definition: kmtest.c:111
static void OutputError(IN DWORD Error)
Definition: kmtest.c:53
#define RESULTBUFFER_SIZE
Definition: kmtest.c:22
KMT_OPERATION
Definition: kmtest.c:25
@ KMT_RUN_TEST
Definition: kmtest.c:29
@ KMT_LIST_TESTS
Definition: kmtest.c:27
@ KMT_LIST_ALL_TESTS
Definition: kmtest.c:28
@ KMT_DO_NOTHING
Definition: kmtest.c:26
#define SERVICE_NAME
Definition: kmtest.c:18
PCSTR ErrorFileAndLine
Definition: kmtest.c:34
static DWORD OutputResult(IN PCSTR TestName)
Definition: kmtest.c:234
HANDLE KmtestHandle
Definition: kmtest.c:32
static INT CompareTestNames(IN PCSTR Str1, IN PCSTR Str2)
Definition: kmtest.c:81
#define SERVICE_PATH
Definition: kmtest.c:19
SC_HANDLE KmtestServiceHandle
Definition: kmtest.c:33
DWORD KmtServiceCleanup(BOOLEAN IgnoreErrors)
Definition: service.c:64
DWORD KmtServiceInit(VOID)
Definition: service.c:40
DWORD KmtCloseService(IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:392
#define error_goto(Error, label)
Definition: kmtest.h:21
DWORD KmtDeleteService(IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:356
DWORD KmtCreateService(IN PCWSTR ServiceName, IN PCWSTR ServicePath, IN PCWSTR DisplayName OPTIONAL, OUT SC_HANDLE *ServiceHandle)
Definition: service.c:92
DWORD KmtStopService(IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:315
DWORD KmtCreateAndStartService(IN PCWSTR ServiceName, IN PCWSTR ServicePath, IN PCWSTR DisplayName OPTIONAL, OUT SC_HANDLE *ServiceHandle, IN BOOLEAN RestartIfRunning)
Definition: service.c:262
#define error(str)
Definition: mkdosfs.c:1605
static void TestEntry(const ENTRY *pEntry)
WCHAR TestName[MAX_PATH]
Definition: main.cpp:13
#define min(a, b)
Definition: monoChain.cc:55
#define GENERIC_WRITE
Definition: nt_native.h:90
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define EXIT_SUCCESS
Definition: rdjpgcom.c:55
void TestFunction()
#define LANG_NEUTRAL
Definition: nls.h:22
#define MAKELANGID(p, s)
Definition: nls.h:15
#define SUBLANG_DEFAULT
Definition: nls.h:168
CHAR LogBuffer[ANYSIZE_ARRAY]
Definition: kmt_test.h:41
volatile LONG LogBufferLength
Definition: kmt_test.h:39
DWORD KmtRunKernelTest(IN PCSTR TestName)
Definition: support.c:95
EH_STD::__list__< TestClass, eh_allocator(TestClass) > TestList
Definition: test_list.cpp:31
char * PSTR
Definition: typedefs.h:51
int32_t INT
Definition: typedefs.h:58
const char * PCSTR
Definition: typedefs.h:52
#define IN
Definition: typedefs.h:39
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesWritten
Definition: wdfiotarget.h:960
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
#define STD_OUTPUT_HANDLE
Definition: winbase.h:301
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FORMAT_MESSAGE_IGNORE_INSERTS
Definition: winbase.h:453
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:456
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:452
#define CreateFile
Definition: winbase.h:3790
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
char * LPSTR
Definition: xmlstorage.h:182