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/CM... ============================================================================== --- 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/in... ============================================================================== --- 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/km... ============================================================================== --- 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/km... ============================================================================== --- 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/km... ============================================================================== --- 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/km... ============================================================================== --- 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/km... ============================================================================== --- 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@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/km... ============================================================================== --- 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@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