mirror of
https://github.com/reactos/reactos.git
synced 2025-06-14 23:29:50 +00:00
[KMTESTS]
- rework the kmtest loader application to follow everything else's coding style and to allow user-mode test parts svn path=/branches/GSoC_2011/KMTestSuite/; revision=52519
This commit is contained in:
parent
991bc0e366
commit
459f4ac630
8 changed files with 803 additions and 238 deletions
|
@ -48,6 +48,8 @@ set_rc_compiler()
|
||||||
list(APPEND KMTEST_SOURCE
|
list(APPEND KMTEST_SOURCE
|
||||||
kmtest/kmtest.c
|
kmtest/kmtest.c
|
||||||
kmtest/service.c
|
kmtest/service.c
|
||||||
|
kmtest/support.c
|
||||||
|
kmtest/testlist.c
|
||||||
kmtest/kmtest.rc)
|
kmtest/kmtest.rc)
|
||||||
|
|
||||||
add_executable(kmtest ${KMTEST_SOURCE})
|
add_executable(kmtest ${KMTEST_SOURCE})
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
typedef VOID KMT_TESTFUNC(VOID);
|
typedef VOID KMT_TESTFUNC(VOID);
|
||||||
|
typedef KMT_TESTFUNC *PKMT_TESTFUNC;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -37,6 +38,17 @@ typedef struct
|
||||||
CHAR LogBuffer[ANYSIZE_ARRAY];
|
CHAR LogBuffer[ANYSIZE_ARRAY];
|
||||||
} KMT_RESULTBUFFER, *PKMT_RESULTBUFFER;
|
} KMT_RESULTBUFFER, *PKMT_RESULTBUFFER;
|
||||||
|
|
||||||
|
#if defined KMT_USER_MODE
|
||||||
|
VOID KmtLoadDriver(IN PCWSTR ServiceName, IN BOOLEAN RestartIfRunning);
|
||||||
|
VOID KmtUnloadDriver(VOID);
|
||||||
|
VOID KmtOpenDriver(VOID);
|
||||||
|
VOID KmtCloseDriver(VOID);
|
||||||
|
|
||||||
|
DWORD KmtSendToDriver(IN DWORD ControlCode);
|
||||||
|
DWORD KmtSendStringToDriver(IN DWORD ControlCode, IN PCSTR String);
|
||||||
|
DWORD KmtSendBufferToDriver(IN DWORD ControlCode, IN OUT PVOID Buffer, IN DWORD Length);
|
||||||
|
#endif /* defined KMT_USER_MODE */
|
||||||
|
|
||||||
extern PKMT_RESULTBUFFER ResultBuffer;
|
extern PKMT_RESULTBUFFER ResultBuffer;
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
@ -47,7 +59,9 @@ extern PKMT_RESULTBUFFER ResultBuffer;
|
||||||
|
|
||||||
#define START_TEST(name) VOID Test_##name(VOID)
|
#define START_TEST(name) VOID Test_##name(VOID)
|
||||||
|
|
||||||
|
#ifndef KMT_STRINGIZE
|
||||||
#define KMT_STRINGIZE(x) #x
|
#define KMT_STRINGIZE(x) #x
|
||||||
|
#endif /* !defined KMT_STRINGIZE */
|
||||||
#define ok(test, ...) ok_(test, __FILE__, __LINE__, __VA_ARGS__)
|
#define ok(test, ...) ok_(test, __FILE__, __LINE__, __VA_ARGS__)
|
||||||
#define trace(...) trace_( __FILE__, __LINE__, __VA_ARGS__)
|
#define trace(...) trace_( __FILE__, __LINE__, __VA_ARGS__)
|
||||||
#define skip(test, ...) skip_(test, __FILE__, __LINE__, __VA_ARGS__)
|
#define skip(test, ...) skip_(test, __FILE__, __LINE__, __VA_ARGS__)
|
||||||
|
@ -75,7 +89,9 @@ BOOLEAN KmtSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, ...)
|
||||||
#define ok_eq_hex(value, expected) ok_eq_print(value, expected, "0x%08lx")
|
#define ok_eq_hex(value, expected) ok_eq_print(value, expected, "0x%08lx")
|
||||||
#define ok_bool_true(value, desc) ok((value) == TRUE, desc " FALSE, expected TRUE\n")
|
#define ok_bool_true(value, desc) ok((value) == TRUE, desc " FALSE, expected TRUE\n")
|
||||||
#define ok_bool_false(value, desc) ok((value) == FALSE, desc " TRUE, expected FALSE\n")
|
#define ok_bool_false(value, desc) ok((value) == FALSE, desc " TRUE, expected FALSE\n")
|
||||||
#define ok_eq_bool(value, expected) ok((value) == (expected), #value " = %s, expected %s\n", (value) ? "TRUE" : "FALSE", (expected) ? "TRUE" : "FALSE")
|
#define ok_eq_bool(value, expected) ok((value) == (expected), #value " = %s, expected %s\n", \
|
||||||
|
(value) ? "TRUE" : "FALSE", \
|
||||||
|
(expected) ? "TRUE" : "FALSE")
|
||||||
#define ok_eq_str(value, expected) ok(!strcmp(value, expected), #value " = \"%s\", expected \"%s\"\n", value, expected)
|
#define ok_eq_str(value, expected) ok(!strcmp(value, expected), #value " = \"%s\", expected \"%s\"\n", value, expected)
|
||||||
#define ok_eq_wstr(value, expected) ok(!wcscmp(value, expected), #value " = \"%ls\", expected \"%ls\"\n", value, expected)
|
#define ok_eq_wstr(value, expected) ok(!wcscmp(value, expected), #value " = \"%ls\", expected \"%ls\"\n", value, expected)
|
||||||
|
|
||||||
|
|
|
@ -5,5 +5,7 @@
|
||||||
<directory name="kmtest">
|
<directory name="kmtest">
|
||||||
<file>kmtest.c</file>
|
<file>kmtest.c</file>
|
||||||
<file>service.c</file>
|
<file>service.c</file>
|
||||||
|
<file>support.c</file>
|
||||||
|
<file>testlist.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
</module>
|
</module>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
|
|
||||||
|
@ -19,186 +20,288 @@
|
||||||
#define KMT_DEFINE_TEST_FUNCTIONS
|
#define KMT_DEFINE_TEST_FUNCTIONS
|
||||||
#include <kmt_test.h>
|
#include <kmt_test.h>
|
||||||
|
|
||||||
|
#define SERVICE_NAME L"Kmtest"
|
||||||
|
#define SERVICE_PATH L"kmtest_drv.sys"
|
||||||
|
|
||||||
#define LOGBUFFER_SIZE 65000
|
#define LOGBUFFER_SIZE 65000
|
||||||
|
#define RESULTBUFFER_SIZE FIELD_OFFSET(KMT_RESULTBUFFER, LogBuffer[LOGBUFFER_SIZE])
|
||||||
|
|
||||||
static void OutputError(FILE *fp, DWORD error);
|
static HANDLE KmtestHandle;
|
||||||
static DWORD RunTest(char *testName);
|
PCSTR ErrorFileAndLine = "No error";
|
||||||
static DWORD ListTests(PSTR *testList);
|
|
||||||
int __cdecl main(int argc, char **argv);
|
|
||||||
|
|
||||||
static void OutputError(FILE *fp, DWORD error)
|
static void OutputError(DWORD Error);
|
||||||
|
static DWORD ListTests(VOID);
|
||||||
|
static PKMT_TESTFUNC FindTest(PCSTR TestName);
|
||||||
|
static DWORD OutputResult(PCSTR TestName);
|
||||||
|
static DWORD RunTest(PCSTR TestName);
|
||||||
|
int __cdecl main(int ArgCount, char **Arguments);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name OutputError
|
||||||
|
*
|
||||||
|
* Output an error message to the console.
|
||||||
|
*
|
||||||
|
* @param Error
|
||||||
|
* Win32 error code
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
OutputError(
|
||||||
|
DWORD Error)
|
||||||
{
|
{
|
||||||
char *message;
|
PSTR Message;
|
||||||
if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||||
NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&message, 0, NULL))
|
NULL, Error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&Message, 0, NULL))
|
||||||
{
|
{
|
||||||
fprintf(fp, "Could not retrieve error message (error 0x%08lx). Original error: 0x%08lx\n", GetLastError(), error);
|
fprintf(stderr, "%s: Could not retrieve error message (error 0x%08lx). Original error: 0x%08lx\n",
|
||||||
|
ErrorFileAndLine, GetLastError(), Error);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "%s\n", message);
|
fprintf(stderr, "%s: error 0x%08lx: %s\n", ErrorFileAndLine, Error, Message);
|
||||||
|
|
||||||
LocalFree(message);
|
LocalFree(Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD RunTest(char *testName)
|
/**
|
||||||
|
* @name ListTests
|
||||||
|
*
|
||||||
|
* Output the list of tests to the console.
|
||||||
|
* The list will comprise tests as listed by the driver
|
||||||
|
* in addition to user-mode tests in TestList.
|
||||||
|
*
|
||||||
|
* @return Win32 error code
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
DWORD
|
||||||
|
ListTests(VOID)
|
||||||
{
|
{
|
||||||
DWORD error = ERROR_SUCCESS;
|
DWORD Error = ERROR_SUCCESS;
|
||||||
HANDLE hDevice = INVALID_HANDLE_VALUE;
|
CHAR Buffer[1024];
|
||||||
DWORD bytesRead, bytesWritten;
|
DWORD BytesRead;
|
||||||
|
PCSTR TestName = Buffer;
|
||||||
|
PCKMT_TEST TestEntry = TestList;
|
||||||
|
PCSTR NextTestName;
|
||||||
|
|
||||||
|
puts("Valid test names:");
|
||||||
|
|
||||||
|
// get test list from driver
|
||||||
|
if (!DeviceIoControl(KmtestHandle, IOCTL_KMTEST_GET_TESTS, NULL, 0, Buffer, sizeof Buffer, &BytesRead, NULL))
|
||||||
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
|
// output test list plus user-mode tests
|
||||||
|
while (TestEntry->TestName || *TestName)
|
||||||
|
{
|
||||||
|
// tests starting with a '-' should not be listed
|
||||||
|
while (TestEntry->TestName && *TestEntry->TestName == '-')
|
||||||
|
++TestEntry;
|
||||||
|
|
||||||
|
if (!TestEntry->TestName)
|
||||||
|
{
|
||||||
|
NextTestName = TestName;
|
||||||
|
TestName += strlen(TestName) + 1;
|
||||||
|
}
|
||||||
|
else if (!*TestName)
|
||||||
|
{
|
||||||
|
NextTestName = TestEntry->TestName;
|
||||||
|
++TestEntry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int Result = strcmp(TestEntry->TestName, TestName);
|
||||||
|
|
||||||
|
if (Result == 0)
|
||||||
|
{
|
||||||
|
NextTestName = TestEntry->TestName;
|
||||||
|
TestName += strlen(TestName) + 1;
|
||||||
|
++TestEntry;
|
||||||
|
}
|
||||||
|
else if (Result < 0)
|
||||||
|
{
|
||||||
|
NextTestName = TestEntry->TestName;
|
||||||
|
++TestEntry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NextTestName = TestName;
|
||||||
|
TestName += strlen(TestName) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(" %s\n", NextTestName);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name FindTest
|
||||||
|
*
|
||||||
|
* Find a test in TestList by name.
|
||||||
|
*
|
||||||
|
* @param TestName
|
||||||
|
* Name of the test to look for. Case sensitive
|
||||||
|
*
|
||||||
|
* @return pointer to test function, or NULL if not found
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
PKMT_TESTFUNC
|
||||||
|
FindTest(
|
||||||
|
PCSTR TestName)
|
||||||
|
{
|
||||||
|
PCKMT_TEST TestEntry = TestList;
|
||||||
|
|
||||||
|
for (TestEntry = TestList; TestEntry->TestName; ++TestEntry)
|
||||||
|
{
|
||||||
|
PCSTR TestEntryName = TestEntry->TestName;
|
||||||
|
|
||||||
|
// skip leading '-' if present
|
||||||
|
if (*TestEntryName == '-')
|
||||||
|
++TestEntryName;
|
||||||
|
|
||||||
|
if (!lstrcmpA(TestEntryName, TestName))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TestEntry->TestFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name OutputResult
|
||||||
|
*
|
||||||
|
* Output the test results in ResultBuffer to the console.
|
||||||
|
*
|
||||||
|
* @param TestName
|
||||||
|
* Name of the test whose result is to be printed
|
||||||
|
*
|
||||||
|
* @return Win32 error code
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
DWORD
|
||||||
|
OutputResult(
|
||||||
|
PCSTR TestName)
|
||||||
|
{
|
||||||
|
DWORD Error = ERROR_SUCCESS;
|
||||||
|
DWORD BytesWritten;
|
||||||
|
|
||||||
|
KmtFinishTest(TestName);
|
||||||
|
|
||||||
|
if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), ResultBuffer->LogBuffer, ResultBuffer->LogBufferLength, &BytesWritten, NULL))
|
||||||
|
Error = GetLastError();
|
||||||
|
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name RunTest
|
||||||
|
*
|
||||||
|
* Run the named test and output its results.
|
||||||
|
*
|
||||||
|
* @param TestName
|
||||||
|
* Name of the test to run. Case sensitive
|
||||||
|
*
|
||||||
|
* @return Win32 error code
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
DWORD
|
||||||
|
RunTest(
|
||||||
|
PCSTR TestName)
|
||||||
|
{
|
||||||
|
DWORD Error = ERROR_SUCCESS;
|
||||||
|
PKMT_TESTFUNC TestFunction;
|
||||||
|
DWORD BytesRead;
|
||||||
|
|
||||||
ResultBuffer = KmtAllocateResultBuffer(LOGBUFFER_SIZE);
|
ResultBuffer = KmtAllocateResultBuffer(LOGBUFFER_SIZE);
|
||||||
if (!ResultBuffer)
|
if (!DeviceIoControl(KmtestHandle, IOCTL_KMTEST_SET_RESULTBUFFER, ResultBuffer, RESULTBUFFER_SIZE, NULL, 0, &BytesRead, NULL))
|
||||||
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
|
// check test list
|
||||||
|
TestFunction = FindTest(TestName);
|
||||||
|
|
||||||
|
if (TestFunction)
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
TestFunction();
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
hDevice = CreateFile(KMTEST_DEVICE_PATH, GENERIC_READ | GENERIC_WRITE, 0,
|
// not found in user-mode test list, call driver
|
||||||
NULL, OPEN_EXISTING, 0, NULL);
|
if (!DeviceIoControl(KmtestHandle, IOCTL_KMTEST_RUN_TEST, (PVOID)TestName, strlen(TestName), NULL, 0, &BytesRead, NULL))
|
||||||
|
error_goto(Error, cleanup);
|
||||||
if (hDevice == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
error = GetLastError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DeviceIoControl(hDevice, IOCTL_KMTEST_SET_RESULTBUFFER, ResultBuffer, FIELD_OFFSET(KMT_RESULTBUFFER, LogBuffer[LOGBUFFER_SIZE]), NULL, 0, &bytesRead, NULL))
|
|
||||||
{
|
|
||||||
error = GetLastError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DeviceIoControl(hDevice, IOCTL_KMTEST_RUN_TEST, testName, strlen(testName), NULL, 0, &bytesRead, NULL))
|
|
||||||
{
|
|
||||||
error = GetLastError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
KmtFinishTest(testName);
|
|
||||||
|
|
||||||
if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), ResultBuffer->LogBuffer, ResultBuffer->LogBufferLength, &bytesWritten, NULL))
|
|
||||||
{
|
|
||||||
error = GetLastError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (hDevice != INVALID_HANDLE_VALUE)
|
OutputResult(TestName);
|
||||||
CloseHandle(hDevice);
|
|
||||||
|
|
||||||
if (ResultBuffer)
|
|
||||||
KmtFreeResultBuffer(ResultBuffer);
|
KmtFreeResultBuffer(ResultBuffer);
|
||||||
|
|
||||||
return error;
|
return Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD ListTests(PSTR *testList)
|
/**
|
||||||
|
* @name main
|
||||||
|
*
|
||||||
|
* Program entry point
|
||||||
|
*
|
||||||
|
* @param ArgCount
|
||||||
|
* @param Arguments
|
||||||
|
*
|
||||||
|
* @return EXIT_SUCCESS on success, EXIT_FAILURE on failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
main(
|
||||||
|
int ArgCount,
|
||||||
|
char **Arguments)
|
||||||
{
|
{
|
||||||
DWORD error = ERROR_SUCCESS;
|
INT Status = EXIT_SUCCESS;
|
||||||
HANDLE hDevice = INVALID_HANDLE_VALUE;
|
DWORD Error = ERROR_SUCCESS;
|
||||||
DWORD bytesRead;
|
SC_HANDLE ServiceHandle;
|
||||||
PSTR buffer = NULL;
|
PCSTR AppName = "kmtest.exe";
|
||||||
DWORD bufferSize;
|
PCSTR TestName;
|
||||||
|
|
||||||
if (!testList)
|
Error = KmtServiceInit();
|
||||||
{
|
if (Error)
|
||||||
error = ERROR_INVALID_PARAMETER;
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
Error = KmtCreateAndStartService(SERVICE_NAME, SERVICE_PATH, L"ReactOS Kernel-Mode Test Suite Driver", &ServiceHandle, FALSE);
|
||||||
|
if (Error)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
KmtestHandle = CreateFile(KMTEST_DEVICE_PATH, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
if (KmtestHandle == INVALID_HANDLE_VALUE)
|
||||||
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
|
if (ArgCount >= 1)
|
||||||
|
AppName = Arguments[0];
|
||||||
|
|
||||||
|
if (ArgCount <= 1)
|
||||||
|
{
|
||||||
|
printf("Usage: %s <test_name> - run the specified test\n", AppName);
|
||||||
|
printf(" %s --list - list available tests\n", AppName);
|
||||||
|
printf(" %s <create|delete|start|stop> - manage the kmtest driver\n\n", AppName);
|
||||||
|
Error = ListTests();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
hDevice = CreateFile(KMTEST_DEVICE_PATH, GENERIC_READ | GENERIC_WRITE, 0,
|
|
||||||
NULL, OPEN_EXISTING, 0, NULL);
|
|
||||||
|
|
||||||
if (hDevice == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
TestName = Arguments[1];
|
||||||
goto cleanup;
|
if (!lstrcmpA(Arguments[1], "--list"))
|
||||||
}
|
Error = ListTests();
|
||||||
|
else
|
||||||
bufferSize = 1024;
|
Error = RunTest(TestName);
|
||||||
buffer = HeapAlloc(GetProcessHeap(), 0, bufferSize);
|
|
||||||
if (!buffer)
|
|
||||||
{
|
|
||||||
error = GetLastError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DeviceIoControl(hDevice, IOCTL_KMTEST_GET_TESTS, NULL, 0, buffer, bufferSize, &bytesRead, NULL))
|
|
||||||
{
|
|
||||||
error = GetLastError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (buffer && error)
|
if (KmtestHandle)
|
||||||
{
|
CloseHandle(KmtestHandle);
|
||||||
HeapFree(GetProcessHeap(), 0, buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hDevice != INVALID_HANDLE_VALUE)
|
if (Error)
|
||||||
CloseHandle(hDevice);
|
KmtServiceCleanup(TRUE);
|
||||||
|
|
||||||
if (testList)
|
|
||||||
*testList = buffer;
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __cdecl main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int status = EXIT_SUCCESS;
|
|
||||||
DWORD error;
|
|
||||||
|
|
||||||
if (argc <= 1)
|
|
||||||
{
|
|
||||||
/* no arguments: show usage and list tests */
|
|
||||||
char *programName = argc == 0 ? "kmtest" : argv[0];
|
|
||||||
char *testNames, *testName;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
printf("Usage: %s test_name\n", programName);
|
|
||||||
printf(" %s <Create|Start|Stop|Delete>\n", programName);
|
|
||||||
puts("\nValid test names:");
|
|
||||||
|
|
||||||
error = ListTests(&testNames);
|
|
||||||
testName = testNames;
|
|
||||||
|
|
||||||
while ((len = strlen(testName)) != 0)
|
|
||||||
{
|
|
||||||
printf(" %s\n", testName);
|
|
||||||
testName += len + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: user-mode test parts */
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
OutputError(stdout, error);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
Error = KmtServiceCleanup(FALSE);
|
||||||
char *testName = argv[1];
|
|
||||||
|
|
||||||
if (argc > 2)
|
if (Error)
|
||||||
fputs("Excess arguments ignored\n", stderr);
|
OutputError(Error);
|
||||||
|
|
||||||
if (!lstrcmpiA(testName, "create"))
|
if (Error)
|
||||||
error = Service_Control(Service_Create);
|
Status = EXIT_FAILURE;
|
||||||
else if (!lstrcmpiA(testName, "delete"))
|
|
||||||
error = Service_Control(Service_Delete);
|
|
||||||
else if (!lstrcmpiA(testName, "start"))
|
|
||||||
error = Service_Control(Service_Start);
|
|
||||||
else if (!lstrcmpiA(testName, "stop"))
|
|
||||||
error = Service_Control(Service_Stop);
|
|
||||||
else
|
|
||||||
/* TODO: user-mode test parts */
|
|
||||||
error = RunTest(testName);
|
|
||||||
|
|
||||||
OutputError(stdout, error);
|
return Status;
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
status = EXIT_FAILURE;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,16 +8,57 @@
|
||||||
#ifndef _KMTESTS_H_
|
#ifndef _KMTESTS_H_
|
||||||
#define _KMTESTS_H_
|
#define _KMTESTS_H_
|
||||||
|
|
||||||
#include <windows.h>
|
extern PCSTR ErrorFileAndLine;
|
||||||
|
|
||||||
/* service control functions */
|
#ifndef KMT_STRINGIZE
|
||||||
typedef DWORD SERVICE_FUNC(SC_HANDLE hManager);
|
#define KMT_STRINGIZE(x) #x
|
||||||
|
#endif /* !defined KMT_STRINGIZE */
|
||||||
|
|
||||||
SERVICE_FUNC Service_Create;
|
#define location(file, line) do { ErrorFileAndLine = file ":" KMT_STRINGIZE(line); } while (0)
|
||||||
SERVICE_FUNC Service_Delete;
|
#define error_value(Error, value) do { location(__FILE__, __LINE__); Error = value; } while (0)
|
||||||
SERVICE_FUNC Service_Start;
|
#define error(Error) error_value(Error, GetLastError())
|
||||||
SERVICE_FUNC Service_Stop;
|
#define error_goto(Error, label) do { error(Error); goto label; } while (0)
|
||||||
|
#define error_value_goto(Error, value, label) do { error_value(Error, value); goto label; } while (0)
|
||||||
|
|
||||||
DWORD Service_Control(SERVICE_FUNC *Service_Func);
|
/* service management functions */
|
||||||
|
DWORD
|
||||||
|
KmtServiceInit(VOID);
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
KmtServiceCleanup(
|
||||||
|
BOOLEAN IgnoreErrors);
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
KmtCreateService(
|
||||||
|
IN PCWSTR ServiceName,
|
||||||
|
IN PCWSTR ServicePath,
|
||||||
|
IN PCWSTR DisplayName OPTIONAL,
|
||||||
|
OUT SC_HANDLE *ServiceHandle);
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
KmtStartService(
|
||||||
|
IN PCWSTR ServiceName OPTIONAL,
|
||||||
|
IN OUT SC_HANDLE *ServiceHandle);
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
KmtCreateAndStartService(
|
||||||
|
IN PCWSTR ServiceName,
|
||||||
|
IN PCWSTR ServicePath,
|
||||||
|
IN PCWSTR DisplayName OPTIONAL,
|
||||||
|
OUT SC_HANDLE *ServiceHandle,
|
||||||
|
IN BOOLEAN RestartIfRunning);
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
KmtStopService(
|
||||||
|
IN PCWSTR ServiceName OPTIONAL,
|
||||||
|
IN OUT SC_HANDLE *ServiceHandle);
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
KmtDeleteService(
|
||||||
|
IN PCWSTR ServiceName OPTIONAL,
|
||||||
|
IN OUT SC_HANDLE *ServiceHandle);
|
||||||
|
|
||||||
|
DWORD KmtCloseService(
|
||||||
|
IN OUT SC_HANDLE *ServiceHandle);
|
||||||
|
|
||||||
#endif /* !defined _KMTESTS_H_ */
|
#endif /* !defined _KMTESTS_H_ */
|
||||||
|
|
|
@ -6,130 +6,308 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "kmtest.h"
|
#include "kmtest.h"
|
||||||
|
|
||||||
#define SERVICE_NAME L"Kmtest"
|
#define SERVICE_ACCESS (SERVICE_START | SERVICE_STOP | DELETE)
|
||||||
#define SERVICE_PATH L"\\kmtest_drv.sys"
|
|
||||||
|
|
||||||
DWORD Service_Create(SC_HANDLE hScm)
|
static SC_HANDLE ScmHandle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name KmtServiceInit
|
||||||
|
*
|
||||||
|
* Initialize service management routines (by opening the service control manager)
|
||||||
|
*
|
||||||
|
* @return Win32 error code
|
||||||
|
*/
|
||||||
|
DWORD
|
||||||
|
KmtServiceInit(VOID)
|
||||||
{
|
{
|
||||||
DWORD error = ERROR_SUCCESS;
|
DWORD Error = ERROR_SUCCESS;
|
||||||
SC_HANDLE hService = NULL;
|
|
||||||
wchar_t driverPath[MAX_PATH];
|
assert(!ScmHandle);
|
||||||
|
|
||||||
|
ScmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
|
||||||
|
if (!ScmHandle)
|
||||||
|
error(Error);
|
||||||
|
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name KmtServiceCleanup
|
||||||
|
*
|
||||||
|
* Clean up resources used by service management routines.
|
||||||
|
*
|
||||||
|
* @param IgnoreErrors
|
||||||
|
* If TRUE, the function will never set ErrorLineAndFile, and always return ERROR_SUCCESS
|
||||||
|
*
|
||||||
|
* @return Win32 error code
|
||||||
|
*/
|
||||||
|
DWORD
|
||||||
|
KmtServiceCleanup(
|
||||||
|
BOOLEAN IgnoreErrors)
|
||||||
|
{
|
||||||
|
DWORD Error = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (ScmHandle && !CloseServiceHandle(ScmHandle) && !IgnoreErrors)
|
||||||
|
error(Error);
|
||||||
|
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name KmtCreateService
|
||||||
|
*
|
||||||
|
* Create the specified driver service and return a handle to it
|
||||||
|
*
|
||||||
|
* @param ServiceName
|
||||||
|
* Name of the service to create
|
||||||
|
* @param ServicePath
|
||||||
|
* File name of the driver, relative to the current directory
|
||||||
|
* @param DisplayName
|
||||||
|
* Service display name
|
||||||
|
* @param ServiceHandle
|
||||||
|
* Pointer to a variable to receive the handle to the service
|
||||||
|
*
|
||||||
|
* @return Win32 error code
|
||||||
|
*/
|
||||||
|
DWORD
|
||||||
|
KmtCreateService(
|
||||||
|
IN PCWSTR ServiceName,
|
||||||
|
IN PCWSTR ServicePath,
|
||||||
|
IN PCWSTR DisplayName OPTIONAL,
|
||||||
|
OUT SC_HANDLE *ServiceHandle)
|
||||||
|
{
|
||||||
|
DWORD Error = ERROR_SUCCESS;
|
||||||
|
WCHAR DriverPath[MAX_PATH];
|
||||||
HRESULT result = S_OK;
|
HRESULT result = S_OK;
|
||||||
|
|
||||||
if (!GetCurrentDirectory(sizeof driverPath / sizeof driverPath[0], driverPath)
|
assert(ServiceHandle);
|
||||||
|| FAILED(result = StringCbCat(driverPath, sizeof driverPath, SERVICE_PATH)))
|
assert(ServiceName && ServicePath);
|
||||||
|
|
||||||
|
if (!GetCurrentDirectory(sizeof DriverPath / sizeof DriverPath[0], DriverPath))
|
||||||
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
|
if (DriverPath[wcslen(DriverPath) - 1] != L'\\')
|
||||||
{
|
{
|
||||||
|
DriverPath[wcslen(DriverPath) + 1] = L'\0';
|
||||||
|
DriverPath[wcslen(DriverPath)] = L'\\';
|
||||||
|
}
|
||||||
|
|
||||||
|
result = StringCbCat(DriverPath, sizeof DriverPath, ServicePath);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
error = result;
|
error_value_goto(Error, result, cleanup);
|
||||||
else
|
|
||||||
error = GetLastError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
hService = CreateService(hScm, SERVICE_NAME, L"ReactOS Kernel-Mode Test Suite Driver",
|
*ServiceHandle = CreateService(ScmHandle, ServiceName, DisplayName,
|
||||||
SERVICE_START, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
|
SERVICE_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
|
||||||
SERVICE_ERROR_NORMAL, driverPath, NULL, NULL, NULL, NULL, NULL);
|
SERVICE_ERROR_NORMAL, DriverPath, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (!hService)
|
if (!*ServiceHandle)
|
||||||
error = GetLastError();
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
return error;
|
return Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD Service_Delete(SC_HANDLE hScm)
|
/**
|
||||||
|
* @name KmtStartService
|
||||||
|
*
|
||||||
|
* Start the specified driver service by handle or name (and return a handle to it)
|
||||||
|
*
|
||||||
|
* @param ServiceName
|
||||||
|
* If *ServiceHandle is NULL, name of the service to start
|
||||||
|
* @param ServiceHandle
|
||||||
|
* Pointer to a variable containing the service handle,
|
||||||
|
* or NULL (in which case it will be filled with a handle to the service)
|
||||||
|
*
|
||||||
|
* @return Win32 error code
|
||||||
|
*/
|
||||||
|
DWORD
|
||||||
|
KmtStartService(
|
||||||
|
IN PCWSTR ServiceName OPTIONAL,
|
||||||
|
IN OUT SC_HANDLE *ServiceHandle)
|
||||||
{
|
{
|
||||||
DWORD error = ERROR_SUCCESS;
|
DWORD Error = ERROR_SUCCESS;
|
||||||
SC_HANDLE hService = NULL;
|
|
||||||
|
|
||||||
hService = OpenService(hScm, SERVICE_NAME, DELETE);
|
assert(ServiceHandle);
|
||||||
|
assert(ServiceName || *ServiceHandle);
|
||||||
|
|
||||||
if (!hService)
|
if (!*ServiceHandle)
|
||||||
{
|
*ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
|
||||||
error = GetLastError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DeleteService(hService))
|
if (!*ServiceHandle)
|
||||||
error = GetLastError();
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
|
if (!StartService(*ServiceHandle, 0, NULL))
|
||||||
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (hService)
|
return Error;
|
||||||
CloseServiceHandle(hService);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD Service_Start(SC_HANDLE hScm)
|
/**
|
||||||
|
* @name KmtCreateAndStartService
|
||||||
|
*
|
||||||
|
* Create and start the specified driver service and return a handle to it
|
||||||
|
*
|
||||||
|
* @param ServiceName
|
||||||
|
* Name of the service to create
|
||||||
|
* @param ServicePath
|
||||||
|
* File name of the driver, relative to the current directory
|
||||||
|
* @param DisplayName
|
||||||
|
* Service display name
|
||||||
|
* @param ServiceHandle
|
||||||
|
* Pointer to a variable to receive the handle to the service
|
||||||
|
* @param RestartIfRunning
|
||||||
|
* TRUE to stop and restart the service if it is already running
|
||||||
|
*
|
||||||
|
* @return Win32 error code
|
||||||
|
*/
|
||||||
|
DWORD
|
||||||
|
KmtCreateAndStartService(
|
||||||
|
IN PCWSTR ServiceName,
|
||||||
|
IN PCWSTR ServicePath,
|
||||||
|
IN PCWSTR DisplayName OPTIONAL,
|
||||||
|
OUT SC_HANDLE *ServiceHandle,
|
||||||
|
IN BOOLEAN RestartIfRunning)
|
||||||
{
|
{
|
||||||
DWORD error = ERROR_SUCCESS;
|
DWORD Error = ERROR_SUCCESS;
|
||||||
SC_HANDLE hService = NULL;
|
|
||||||
|
|
||||||
hService = OpenService(hScm, SERVICE_NAME, SERVICE_START);
|
assert(ServiceHandle);
|
||||||
|
|
||||||
if (!hService)
|
Error = KmtCreateService(ServiceName, ServicePath, DisplayName, ServiceHandle);
|
||||||
{
|
|
||||||
error = GetLastError();
|
if (Error && Error != ERROR_SERVICE_EXISTS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
|
|
||||||
if (!StartService(hService, 0, NULL))
|
Error = KmtStartService(ServiceName, ServiceHandle);
|
||||||
error = GetLastError();
|
|
||||||
|
if (Error != ERROR_SERVICE_ALREADY_RUNNING)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
Error = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (!RestartIfRunning)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
Error = KmtStopService(ServiceName, ServiceHandle);
|
||||||
|
if (Error)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
Error = KmtStartService(ServiceName, ServiceHandle);
|
||||||
|
if (Error)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (hService)
|
assert(Error || *ServiceHandle);
|
||||||
CloseServiceHandle(hService);
|
return Error;
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD Service_Stop(SC_HANDLE hScm)
|
/**
|
||||||
|
* @name KmtStopService
|
||||||
|
*
|
||||||
|
* Stop the specified driver service by handle or name (and return a handle to it)
|
||||||
|
*
|
||||||
|
* @param ServiceName
|
||||||
|
* If *ServiceHandle is NULL, name of the service to stop
|
||||||
|
* @param ServiceHandle
|
||||||
|
* Pointer to a variable containing the service handle,
|
||||||
|
* or NULL (in which case it will be filled with a handle to the service)
|
||||||
|
*
|
||||||
|
* @return Win32 error code
|
||||||
|
*/
|
||||||
|
DWORD
|
||||||
|
KmtStopService(
|
||||||
|
IN PCWSTR ServiceName OPTIONAL,
|
||||||
|
IN OUT SC_HANDLE *ServiceHandle)
|
||||||
{
|
{
|
||||||
DWORD error = ERROR_SUCCESS;
|
DWORD Error = ERROR_SUCCESS;
|
||||||
SC_HANDLE hService = NULL;
|
SERVICE_STATUS ServiceStatus;
|
||||||
SERVICE_STATUS serviceStatus;
|
|
||||||
|
|
||||||
hService = OpenService(hScm, SERVICE_NAME, SERVICE_STOP);
|
assert(ServiceHandle);
|
||||||
|
assert(ServiceName || *ServiceHandle);
|
||||||
|
|
||||||
if (!hService)
|
if (!*ServiceHandle)
|
||||||
{
|
*ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
|
||||||
error = GetLastError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus))
|
if (!*ServiceHandle)
|
||||||
error = GetLastError();
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
|
if (!ControlService(*ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus))
|
||||||
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (hService)
|
return Error;
|
||||||
CloseServiceHandle(hService);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD Service_Control(SERVICE_FUNC *Service_Func)
|
/**
|
||||||
|
* @name KmtDeleteService
|
||||||
|
*
|
||||||
|
* Delete the specified driver service by handle or name (and return a handle to it)
|
||||||
|
*
|
||||||
|
* @param ServiceName
|
||||||
|
* If *ServiceHandle is NULL, name of the service to delete
|
||||||
|
* @param ServiceHandle
|
||||||
|
* Pointer to a variable containing the service handle.
|
||||||
|
* Will be set to NULL on success
|
||||||
|
*
|
||||||
|
* @return Win32 error code
|
||||||
|
*/
|
||||||
|
DWORD
|
||||||
|
KmtDeleteService(
|
||||||
|
IN PCWSTR ServiceName OPTIONAL,
|
||||||
|
IN OUT SC_HANDLE *ServiceHandle)
|
||||||
{
|
{
|
||||||
DWORD error = ERROR_SUCCESS;
|
DWORD Error = ERROR_SUCCESS;
|
||||||
SC_HANDLE hScm = NULL;
|
|
||||||
|
|
||||||
hScm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
|
assert(ServiceHandle);
|
||||||
|
assert(ServiceName || *ServiceHandle);
|
||||||
|
|
||||||
if (!hScm)
|
if (!*ServiceHandle)
|
||||||
{
|
*ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
|
||||||
error = GetLastError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = Service_Func(hScm);
|
if (!*ServiceHandle)
|
||||||
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
|
if (!DeleteService(*ServiceHandle))
|
||||||
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
|
if (*ServiceHandle)
|
||||||
|
CloseServiceHandle(*ServiceHandle);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (hScm)
|
return Error;
|
||||||
CloseServiceHandle(hScm);
|
}
|
||||||
|
|
||||||
return error;
|
/**
|
||||||
|
* @name KmtCloseService
|
||||||
|
*
|
||||||
|
* Close the specified driver service handle
|
||||||
|
*
|
||||||
|
* @param ServiceHandle
|
||||||
|
* Pointer to a variable containing the service handle.
|
||||||
|
* Will be set to NULL on success
|
||||||
|
*
|
||||||
|
* @return Win32 error code
|
||||||
|
*/
|
||||||
|
DWORD KmtCloseService(
|
||||||
|
IN OUT SC_HANDLE *ServiceHandle)
|
||||||
|
{
|
||||||
|
DWORD Error = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
assert(ServiceHandle);
|
||||||
|
|
||||||
|
if (*ServiceHandle && !CloseServiceHandle(*ServiceHandle))
|
||||||
|
error_goto(Error, cleanup);
|
||||||
|
|
||||||
|
*ServiceHandle = NULL;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
return Error;
|
||||||
}
|
}
|
||||||
|
|
197
kmtests/kmtest/support.c
Normal file
197
kmtests/kmtest/support.c
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define UNICODE
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <strsafe.h>
|
||||||
|
|
||||||
|
#include "kmtest.h"
|
||||||
|
#include <kmt_test.h>
|
||||||
|
#include <kmt_public.h>
|
||||||
|
|
||||||
|
/* pseudo-tests */
|
||||||
|
START_TEST(Create)
|
||||||
|
{
|
||||||
|
// nothing to do here. All tests start the service if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(Delete)
|
||||||
|
{
|
||||||
|
// TODO: delete kmtest service
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(Start)
|
||||||
|
{
|
||||||
|
// nothing to do here. All tests start the service
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(Stop)
|
||||||
|
{
|
||||||
|
// TODO: stop kmtest service
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test support functions for special-purpose drivers */
|
||||||
|
|
||||||
|
static WCHAR TestServiceName[MAX_PATH];
|
||||||
|
static SC_HANDLE TestServiceHandle;
|
||||||
|
static HANDLE TestDeviceHandle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name KmtLoadDriver
|
||||||
|
*
|
||||||
|
* Load the specified special-purpose driver (create/start the service)
|
||||||
|
*
|
||||||
|
* @param ServiceName
|
||||||
|
* Name of the driver service (Kmtest- prefix will be added automatically)
|
||||||
|
* @param RestartIfRunning
|
||||||
|
* TRUE to stop and restart the service if it is already running
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
KmtLoadDriver(
|
||||||
|
IN PCWSTR ServiceName,
|
||||||
|
IN BOOLEAN RestartIfRunning)
|
||||||
|
{
|
||||||
|
DWORD Error = ERROR_SUCCESS;
|
||||||
|
WCHAR ServicePath[MAX_PATH];
|
||||||
|
|
||||||
|
StringCbCopy(ServicePath, sizeof ServicePath, ServiceName);
|
||||||
|
StringCbCat(ServicePath, sizeof ServicePath, L"_drv.sys");
|
||||||
|
|
||||||
|
StringCbCopy(TestServiceName, sizeof TestServiceName, L"Kmtest-");
|
||||||
|
StringCbCat(TestServiceName, sizeof TestServiceName, ServiceName);
|
||||||
|
|
||||||
|
Error = KmtCreateAndStartService(TestServiceName, ServicePath, NULL, &TestServiceHandle, RestartIfRunning);
|
||||||
|
|
||||||
|
if (Error)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name KmtUnloadDriver
|
||||||
|
*
|
||||||
|
* Unload special-purpose driver (stop the service)
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
KmtUnloadDriver(VOID)
|
||||||
|
{
|
||||||
|
DWORD Error = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
Error = KmtStopService(TestServiceName, &TestServiceHandle);
|
||||||
|
|
||||||
|
if (Error)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name KmtOpenDriver
|
||||||
|
*
|
||||||
|
* Open special-purpose driver (acquire a device handle)
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
KmtOpenDriver(VOID)
|
||||||
|
{
|
||||||
|
DWORD Error = ERROR_SUCCESS;
|
||||||
|
WCHAR DevicePath[MAX_PATH];
|
||||||
|
|
||||||
|
StringCbCopy(DevicePath, sizeof DevicePath, L"\\\\.\\Global\\GLOBALROOT\\Device\\");
|
||||||
|
StringCbCat(DevicePath, sizeof DevicePath, TestServiceName);
|
||||||
|
|
||||||
|
TestDeviceHandle = CreateFile(KMTEST_DEVICE_PATH, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
if (TestDeviceHandle == INVALID_HANDLE_VALUE)
|
||||||
|
error(Error);
|
||||||
|
|
||||||
|
if (Error)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name KmtCloseDriver
|
||||||
|
*
|
||||||
|
* Close special-purpose driver (close device handle)
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
KmtCloseDriver(VOID)
|
||||||
|
{
|
||||||
|
DWORD Error = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (TestDeviceHandle && !CloseHandle(TestDeviceHandle))
|
||||||
|
error(Error);
|
||||||
|
|
||||||
|
if (Error)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: check if these will be useful */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name KmtSendToDriver
|
||||||
|
*
|
||||||
|
* Unload special-purpose driver (stop the service)
|
||||||
|
*
|
||||||
|
* @param ControlCode
|
||||||
|
*
|
||||||
|
* @return Win32 error code as returned by DeviceIoControl
|
||||||
|
*/
|
||||||
|
DWORD
|
||||||
|
KmtSendToDriver(
|
||||||
|
IN DWORD ControlCode)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name KmtSendStringToDriver
|
||||||
|
*
|
||||||
|
* Unload special-purpose driver (stop the service)
|
||||||
|
*
|
||||||
|
* @param ControlCode
|
||||||
|
* @param String
|
||||||
|
*
|
||||||
|
* @return Win32 error code as returned by DeviceIoControl
|
||||||
|
*/
|
||||||
|
DWORD
|
||||||
|
KmtSendStringToDriver(
|
||||||
|
IN DWORD ControlCode,
|
||||||
|
IN PCSTR String)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name KmtSendBufferToDriver
|
||||||
|
*
|
||||||
|
* @param ControlCode
|
||||||
|
* @param Buffer
|
||||||
|
* @param Length
|
||||||
|
*
|
||||||
|
* @return Win32 error code as returned by DeviceIoControl
|
||||||
|
*/
|
||||||
|
DWORD
|
||||||
|
KmtSendBufferToDriver(
|
||||||
|
IN DWORD ControlCode,
|
||||||
|
IN OUT PVOID Buffer,
|
||||||
|
IN DWORD Length)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||||
|
}
|
26
kmtests/kmtest/testlist.c
Normal file
26
kmtests/kmtest/testlist.c
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS kernel-mode tests
|
||||||
|
* LICENSE: GPLv2+ - See COPYING in the top level directory
|
||||||
|
* PURPOSE: Kernel-Mode Test Suite user-mode test list
|
||||||
|
* PROGRAMMER: Thomas Faber <thfabba@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define UNICODE
|
||||||
|
#include <windows.h>
|
||||||
|
#include <kmt_test.h>
|
||||||
|
|
||||||
|
VOID Test_Create(VOID);
|
||||||
|
VOID Test_Delete(VOID);
|
||||||
|
VOID Test_Start(VOID);
|
||||||
|
VOID Test_Stop(VOID);
|
||||||
|
|
||||||
|
/* tests with a leading '-' will not be listed */
|
||||||
|
const KMT_TEST TestList[] =
|
||||||
|
{
|
||||||
|
{ "-create", Test_Create },
|
||||||
|
{ "-delete", Test_Delete },
|
||||||
|
{ "-start", Test_Start },
|
||||||
|
{ "-stop", Test_Stop, },
|
||||||
|
{ NULL, NULL },
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue