Author: tfaber
Date: Sun Jul 3 18:53:26 2011
New Revision: 52519
URL:
http://svn.reactos.org/svn/reactos?rev=52519&view=rev
Log:
[KMTESTS]
- rework the kmtest loader application to follow everything else's coding style and to
allow user-mode test parts
Added:
branches/GSoC_2011/KMTestSuite/kmtests/kmtest/support.c (with props)
branches/GSoC_2011/KMTestSuite/kmtests/kmtest/testlist.c (with props)
Modified:
branches/GSoC_2011/KMTestSuite/kmtests/CMakeLists.txt
branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_test.h
branches/GSoC_2011/KMTestSuite/kmtests/kmtest.rbuild
branches/GSoC_2011/KMTestSuite/kmtests/kmtest/kmtest.c
branches/GSoC_2011/KMTestSuite/kmtests/kmtest/kmtest.h
branches/GSoC_2011/KMTestSuite/kmtests/kmtest/service.c
Modified: branches/GSoC_2011/KMTestSuite/kmtests/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/C…
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/CMakeLists.txt [iso-8859-1] (original)
+++ branches/GSoC_2011/KMTestSuite/kmtests/CMakeLists.txt [iso-8859-1] Sun Jul 3 18:53:26
2011
@@ -48,6 +48,8 @@
list(APPEND KMTEST_SOURCE
kmtest/kmtest.c
kmtest/service.c
+ kmtest/support.c
+ kmtest/testlist.c
kmtest/kmtest.rc)
add_executable(kmtest ${KMTEST_SOURCE})
Modified: branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_test.h
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/i…
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_test.h [iso-8859-1] (original)
+++ branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_test.h [iso-8859-1] Sun Jul 3
18:53:26 2011
@@ -16,6 +16,7 @@
#include <stdarg.h>
typedef VOID KMT_TESTFUNC(VOID);
+typedef KMT_TESTFUNC *PKMT_TESTFUNC;
typedef struct
{
@@ -37,6 +38,17 @@
CHAR LogBuffer[ANYSIZE_ARRAY];
} 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;
#ifdef __GNUC__
@@ -47,13 +59,15 @@
#define START_TEST(name) VOID Test_##name(VOID)
+#ifndef KMT_STRINGIZE
#define KMT_STRINGIZE(x) #x
-#define ok(test, ...) ok_(test, __FILE__, __LINE__, __VA_ARGS__)
-#define trace(...) trace_( __FILE__, __LINE__, __VA_ARGS__)
+#endif /* !defined KMT_STRINGIZE */
+#define ok(test, ...) ok_(test, __FILE__, __LINE__, __VA_ARGS__)
+#define trace(...) trace_( __FILE__, __LINE__, __VA_ARGS__)
#define skip(test, ...) skip_(test, __FILE__, __LINE__, __VA_ARGS__)
-#define ok_(test, file, line, ...) KmtOk(test, file ":" KMT_STRINGIZE(line),
__VA_ARGS__)
-#define trace_(file, line, ...) KmtTrace( file ":" KMT_STRINGIZE(line),
__VA_ARGS__)
+#define ok_(test, file, line, ...) KmtOk(test, file ":"
KMT_STRINGIZE(line), __VA_ARGS__)
+#define trace_(file, line, ...) KmtTrace( file ":"
KMT_STRINGIZE(line), __VA_ARGS__)
#define skip_(test, file, line, ...) KmtSkip(test, file ":"
KMT_STRINGIZE(line), __VA_ARGS__)
VOID KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
KMT_FORMAT(ms_printf, 3, 0);
@@ -75,7 +89,9 @@
#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_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_wstr(value, expected) ok(!wcscmp(value, expected), #value " =
\"%ls\", expected \"%ls\"\n", value, expected)
Modified: branches/GSoC_2011/KMTestSuite/kmtests/kmtest.rbuild
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/k…
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/kmtest.rbuild [iso-8859-1] (original)
+++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest.rbuild [iso-8859-1] Sun Jul 3 18:53:26
2011
@@ -5,5 +5,7 @@
<directory name="kmtest">
<file>kmtest.c</file>
<file>service.c</file>
+ <file>support.c</file>
+ <file>testlist.c</file>
</directory>
</module>
Modified: branches/GSoC_2011/KMTestSuite/kmtests/kmtest/kmtest.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/k…
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/kmtest/kmtest.c [iso-8859-1] (original)
+++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest/kmtest.c [iso-8859-1] Sun Jul 3
18:53:26 2011
@@ -6,6 +6,7 @@
*/
#define UNICODE
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <strsafe.h>
@@ -19,186 +20,288 @@
#define KMT_DEFINE_TEST_FUNCTIONS
#include <kmt_test.h>
-#define LOGBUFFER_SIZE 65000
-
-static void OutputError(FILE *fp, DWORD error);
-static DWORD RunTest(char *testName);
-static DWORD ListTests(PSTR *testList);
-int __cdecl main(int argc, char **argv);
-
-static void OutputError(FILE *fp, DWORD error)
-{
- char *message;
+#define SERVICE_NAME L"Kmtest"
+#define SERVICE_PATH L"kmtest_drv.sys"
+
+#define LOGBUFFER_SIZE 65000
+#define RESULTBUFFER_SIZE FIELD_OFFSET(KMT_RESULTBUFFER, LogBuffer[LOGBUFFER_SIZE])
+
+static HANDLE KmtestHandle;
+PCSTR ErrorFileAndLine = "No 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)
+{
+ PSTR Message;
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))
- {
- fprintf(fp, "Could not retrieve error message (error 0x%08lx). Original
error: 0x%08lx\n", GetLastError(), error);
- }
-
- fprintf(fp, "%s\n", message);
-
- LocalFree(message);
-}
-
-static DWORD RunTest(char *testName)
-{
- DWORD error = ERROR_SUCCESS;
- HANDLE hDevice = INVALID_HANDLE_VALUE;
- DWORD bytesRead, bytesWritten;
+ NULL, Error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&Message, 0, NULL))
+ {
+ fprintf(stderr, "%s: Could not retrieve error message (error 0x%08lx).
Original error: 0x%08lx\n",
+ ErrorFileAndLine, GetLastError(), Error);
+ return;
+ }
+
+ fprintf(stderr, "%s: error 0x%08lx: %s\n", ErrorFileAndLine, Error,
Message);
+
+ LocalFree(Message);
+}
+
+/**
+ * @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;
+ CHAR Buffer[1024];
+ 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);
- if (!ResultBuffer)
- {
- error = GetLastError();
+ 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)
+ {
+ TestFunction();
goto cleanup;
}
-
- hDevice = CreateFile(KMTEST_DEVICE_PATH, GENERIC_READ | GENERIC_WRITE, 0,
- NULL, OPEN_EXISTING, 0, NULL);
-
- if (hDevice == INVALID_HANDLE_VALUE)
- {
- error = GetLastError();
+
+ // not found in user-mode test list, call driver
+ if (!DeviceIoControl(KmtestHandle, IOCTL_KMTEST_RUN_TEST, (PVOID)TestName,
strlen(TestName), NULL, 0, &BytesRead, NULL))
+ error_goto(Error, cleanup);
+
+cleanup:
+ OutputResult(TestName);
+
+ KmtFreeResultBuffer(ResultBuffer);
+
+ return Error;
+}
+
+/**
+ * @name main
+ *
+ * Program entry point
+ *
+ * @param ArgCount
+ * @param Arguments
+ *
+ * @return EXIT_SUCCESS on success, EXIT_FAILURE on failure
+ */
+int
+main(
+ int ArgCount,
+ char **Arguments)
+{
+ INT Status = EXIT_SUCCESS;
+ DWORD Error = ERROR_SUCCESS;
+ SC_HANDLE ServiceHandle;
+ PCSTR AppName = "kmtest.exe";
+ PCSTR TestName;
+
+ Error = KmtServiceInit();
+ if (Error)
goto cleanup;
- }
-
- if (!DeviceIoControl(hDevice, IOCTL_KMTEST_SET_RESULTBUFFER, ResultBuffer,
FIELD_OFFSET(KMT_RESULTBUFFER, LogBuffer[LOGBUFFER_SIZE]), NULL, 0, &bytesRead,
NULL))
- {
- error = GetLastError();
+
+ Error = KmtCreateAndStartService(SERVICE_NAME, SERVICE_PATH, L"ReactOS
Kernel-Mode Test Suite Driver", &ServiceHandle, FALSE);
+ if (Error)
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;
+
+ 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
+ {
+ TestName = Arguments[1];
+ if (!lstrcmpA(Arguments[1], "--list"))
+ Error = ListTests();
+ else
+ Error = RunTest(TestName);
}
cleanup:
- if (hDevice != INVALID_HANDLE_VALUE)
- CloseHandle(hDevice);
-
- if (ResultBuffer)
- KmtFreeResultBuffer(ResultBuffer);
-
- return error;
-}
-
-static DWORD ListTests(PSTR *testList)
-{
- DWORD error = ERROR_SUCCESS;
- HANDLE hDevice = INVALID_HANDLE_VALUE;
- DWORD bytesRead;
- PSTR buffer = NULL;
- DWORD bufferSize;
-
- if (!testList)
- {
- error = ERROR_INVALID_PARAMETER;
- goto cleanup;
- }
-
- hDevice = CreateFile(KMTEST_DEVICE_PATH, GENERIC_READ | GENERIC_WRITE, 0,
- NULL, OPEN_EXISTING, 0, NULL);
-
- if (hDevice == INVALID_HANDLE_VALUE)
- {
- error = GetLastError();
- goto cleanup;
- }
-
- bufferSize = 1024;
- 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:
- if (buffer && error)
- {
- HeapFree(GetProcessHeap(), 0, buffer);
- buffer = NULL;
- }
-
- if (hDevice != INVALID_HANDLE_VALUE)
- CloseHandle(hDevice);
-
- 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);
- }
+ if (KmtestHandle)
+ CloseHandle(KmtestHandle);
+
+ if (Error)
+ KmtServiceCleanup(TRUE);
else
- {
- char *testName = argv[1];
-
- if (argc > 2)
- fputs("Excess arguments ignored\n", stderr);
-
- if (!lstrcmpiA(testName, "create"))
- error = Service_Control(Service_Create);
- 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);
- }
-
- if (error)
- status = EXIT_FAILURE;
-
- return status;
-}
+ Error = KmtServiceCleanup(FALSE);
+
+ if (Error)
+ OutputError(Error);
+
+ if (Error)
+ Status = EXIT_FAILURE;
+
+ return Status;
+}
Modified: branches/GSoC_2011/KMTestSuite/kmtests/kmtest/kmtest.h
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/k…
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/kmtest/kmtest.h [iso-8859-1] (original)
+++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest/kmtest.h [iso-8859-1] Sun Jul 3
18:53:26 2011
@@ -8,16 +8,57 @@
#ifndef _KMTESTS_H_
#define _KMTESTS_H_
-#include <windows.h>
+extern PCSTR ErrorFileAndLine;
-/* service control functions */
-typedef DWORD SERVICE_FUNC(SC_HANDLE hManager);
+#ifndef KMT_STRINGIZE
+#define KMT_STRINGIZE(x) #x
+#endif /* !defined KMT_STRINGIZE */
-SERVICE_FUNC Service_Create;
-SERVICE_FUNC Service_Delete;
-SERVICE_FUNC Service_Start;
-SERVICE_FUNC Service_Stop;
+#define location(file, line) do { ErrorFileAndLine = file
":" KMT_STRINGIZE(line); } while (0)
+#define error_value(Error, value) do { location(__FILE__, __LINE__); Error
= value; } while (0)
+#define error(Error) error_value(Error, GetLastError())
+#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_ */
Modified: branches/GSoC_2011/KMTestSuite/kmtests/kmtest/service.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/k…
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/kmtest/service.c [iso-8859-1] (original)
+++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest/service.c [iso-8859-1] Sun Jul 3
18:53:26 2011
@@ -6,130 +6,308 @@
*/
#define UNICODE
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <strsafe.h>
+#include <assert.h>
+
#include "kmtest.h"
-#define SERVICE_NAME L"Kmtest"
-#define SERVICE_PATH L"\\kmtest_drv.sys"
-
-DWORD Service_Create(SC_HANDLE hScm)
-{
- DWORD error = ERROR_SUCCESS;
- SC_HANDLE hService = NULL;
- wchar_t driverPath[MAX_PATH];
+#define SERVICE_ACCESS (SERVICE_START | SERVICE_STOP | DELETE)
+
+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;
+
+ 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;
- if (!GetCurrentDirectory(sizeof driverPath / sizeof driverPath[0], driverPath)
- || FAILED(result = StringCbCat(driverPath, sizeof driverPath,
SERVICE_PATH)))
+ assert(ServiceHandle);
+ assert(ServiceName && ServicePath);
+
+ if (!GetCurrentDirectory(sizeof DriverPath / sizeof DriverPath[0], DriverPath))
+ error_goto(Error, cleanup);
+
+ if (DriverPath[wcslen(DriverPath) - 1] != L'\\')
{
- if (FAILED(result))
- error = result;
- else
- error = GetLastError();
- goto cleanup;
+ DriverPath[wcslen(DriverPath) + 1] = L'\0';
+ DriverPath[wcslen(DriverPath)] = L'\\';
}
- hService = CreateService(hScm, SERVICE_NAME, L"ReactOS Kernel-Mode Test Suite
Driver",
- SERVICE_START, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
- SERVICE_ERROR_NORMAL, driverPath, NULL, NULL, NULL, NULL,
NULL);
-
- if (!hService)
- error = GetLastError();
-
-cleanup:
- return error;
-}
-
-DWORD Service_Delete(SC_HANDLE hScm)
-{
- DWORD error = ERROR_SUCCESS;
- SC_HANDLE hService = NULL;
-
- hService = OpenService(hScm, SERVICE_NAME, DELETE);
-
- if (!hService)
- {
- error = GetLastError();
- goto cleanup;
- }
-
- if (!DeleteService(hService))
- error = GetLastError();
-
-cleanup:
- if (hService)
- CloseServiceHandle(hService);
-
- return error;
-}
-
-DWORD Service_Start(SC_HANDLE hScm)
-{
- DWORD error = ERROR_SUCCESS;
- SC_HANDLE hService = NULL;
-
- hService = OpenService(hScm, SERVICE_NAME, SERVICE_START);
-
- if (!hService)
- {
- error = GetLastError();
- goto cleanup;
- }
-
- if (!StartService(hService, 0, NULL))
- error = GetLastError();
-
-cleanup:
- if (hService)
- CloseServiceHandle(hService);
-
- return error;
-}
-
-DWORD Service_Stop(SC_HANDLE hScm)
-{
- DWORD error = ERROR_SUCCESS;
- SC_HANDLE hService = NULL;
- SERVICE_STATUS serviceStatus;
-
- hService = OpenService(hScm, SERVICE_NAME, SERVICE_STOP);
-
- if (!hService)
- {
- error = GetLastError();
- goto cleanup;
- }
-
- if (!ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus))
- error = GetLastError();
-
-cleanup:
- if (hService)
- CloseServiceHandle(hService);
-
- return error;
-}
-
-DWORD Service_Control(SERVICE_FUNC *Service_Func)
-{
- DWORD error = ERROR_SUCCESS;
- SC_HANDLE hScm = NULL;
-
- hScm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
-
- if (!hScm)
- {
- error = GetLastError();
- goto cleanup;
- }
-
- error = Service_Func(hScm);
-
-cleanup:
- if (hScm)
- CloseServiceHandle(hScm);
-
- return error;
-}
+ result = StringCbCat(DriverPath, sizeof DriverPath, ServicePath);
+ if (FAILED(result))
+ error_value_goto(Error, result, cleanup);
+
+ *ServiceHandle = CreateService(ScmHandle, ServiceName, DisplayName,
+ SERVICE_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
+ SERVICE_ERROR_NORMAL, DriverPath, NULL, NULL, NULL, NULL,
NULL);
+
+ if (!*ServiceHandle)
+ error_goto(Error, cleanup);
+
+cleanup:
+ return Error;
+}
+
+/**
+ * @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;
+
+ assert(ServiceHandle);
+ assert(ServiceName || *ServiceHandle);
+
+ if (!*ServiceHandle)
+ *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
+
+ if (!*ServiceHandle)
+ error_goto(Error, cleanup);
+
+ if (!StartService(*ServiceHandle, 0, NULL))
+ error_goto(Error, cleanup);
+
+cleanup:
+ return Error;
+}
+
+/**
+ * @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;
+
+ assert(ServiceHandle);
+
+ Error = KmtCreateService(ServiceName, ServicePath, DisplayName, ServiceHandle);
+
+ if (Error && Error != ERROR_SERVICE_EXISTS)
+ goto cleanup;
+
+ Error = KmtStartService(ServiceName, ServiceHandle);
+
+ 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:
+ assert(Error || *ServiceHandle);
+ return Error;
+}
+
+/**
+ * @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;
+ SERVICE_STATUS ServiceStatus;
+
+ assert(ServiceHandle);
+ assert(ServiceName || *ServiceHandle);
+
+ if (!*ServiceHandle)
+ *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
+
+ if (!*ServiceHandle)
+ error_goto(Error, cleanup);
+
+ if (!ControlService(*ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus))
+ error_goto(Error, cleanup);
+
+cleanup:
+ return Error;
+}
+
+/**
+ * @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;
+
+ assert(ServiceHandle);
+ assert(ServiceName || *ServiceHandle);
+
+ if (!*ServiceHandle)
+ *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
+
+ if (!*ServiceHandle)
+ error_goto(Error, cleanup);
+
+ if (!DeleteService(*ServiceHandle))
+ error_goto(Error, cleanup);
+
+ if (*ServiceHandle)
+ CloseServiceHandle(*ServiceHandle);
+
+cleanup:
+ 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;
+}
Added: branches/GSoC_2011/KMTestSuite/kmtests/kmtest/support.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/k…
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/kmtest/support.c (added)
+++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest/support.c [iso-8859-1] Sun Jul 3
18:53:26 2011
@@ -1,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(a)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;
+}
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/kmtest/support.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: branches/GSoC_2011/KMTestSuite/kmtests/kmtest/testlist.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/k…
==============================================================================
--- branches/GSoC_2011/KMTestSuite/kmtests/kmtest/testlist.c (added)
+++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest/testlist.c [iso-8859-1] Sun Jul 3
18:53:26 2011
@@ -1,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(a)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 },
+};
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/kmtest/testlist.c
------------------------------------------------------------------------------
svn:eol-style = native