mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
[KMTESTS]
- add simple loader application that can list/run tests from a driver via DeviceIoControl, and prints output to the console svn path=/branches/GSoC_2011/KMTestSuite/; revision=52157
This commit is contained in:
parent
9e143d5955
commit
22216d2eb7
11 changed files with 442 additions and 3 deletions
|
@ -3,6 +3,7 @@ add_subdirectory(apitests)
|
|||
#add_subdirectory(dibtests)
|
||||
add_subdirectory(drivers)
|
||||
#add_subdirectory(dxtest)
|
||||
add_subdirectory(kmtests)
|
||||
#add_subdirectory(regtests)
|
||||
add_subdirectory(rosautotest)
|
||||
add_subdirectory(tests)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE group SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<directory name="apitests">
|
||||
<xi:include href="apitests/directory.rbuild" />
|
||||
</directory>
|
||||
<directory name="drivers">
|
||||
<xi:include href="drivers/directory.rbuild" />
|
||||
</directory>
|
||||
|
@ -10,6 +13,9 @@
|
|||
<directory name="dxtest">
|
||||
<xi:include href="dxtest/directory.rbuild" />
|
||||
</directory>
|
||||
<directory name="kmtests">
|
||||
<xi:include href="kmtests/directory.rbuild" />
|
||||
</directory>
|
||||
<directory name="regtests">
|
||||
<xi:include href="regtests/directory.rbuild" />
|
||||
</directory>
|
||||
|
@ -25,7 +31,4 @@
|
|||
<directory name="winetests">
|
||||
<xi:include href="winetests/directory.rbuild" />
|
||||
</directory>
|
||||
<directory name="apitests">
|
||||
<xi:include href="apitests/directory.rbuild" />
|
||||
</directory>
|
||||
</group>
|
||||
|
|
17
kmtests/CMakeLists.txt
Normal file
17
kmtests/CMakeLists.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
include_directories(
|
||||
include)
|
||||
|
||||
set_rc_compiler()
|
||||
|
||||
add_definitions(-D_DLL -D__USE_CRTIMP)
|
||||
|
||||
list(APPEND KMTEST_SOURCE
|
||||
kmtest/kmtest.c
|
||||
kmtest/service.c
|
||||
kmtest/kmtest.rc)
|
||||
|
||||
add_executable(kmtest ${KMTEST_SOURCE})
|
||||
set_module_type(kmtest win32cui)
|
||||
add_importlibs(kmtest advapi32 msvcrt kernel32)
|
||||
|
||||
add_cd_file(TARGET kmtest DESTINATION reactos/bin FOR all)
|
8
kmtests/directory.rbuild
Normal file
8
kmtests/directory.rbuild
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE group SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<!--<directory name="something">
|
||||
<xi:include href="something/something_drv.rbuild" />
|
||||
</directory>-->
|
||||
<xi:include href="kmtest.rbuild" />
|
||||
</group>
|
20
kmtests/include/kmt_public.h
Normal file
20
kmtests/include/kmt_public.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PROJECT: ReactOS kernel-mode tests
|
||||
* LICENSE: GPLv2+ - See COPYING in the top level directory
|
||||
* PURPOSE: Kernel-Mode Test Suite public declarations
|
||||
* PROGRAMMER: Thomas Faber <thfabba@gmx.de>
|
||||
*/
|
||||
|
||||
#ifndef _KMTEST_PUBLIC_H_
|
||||
#define _KMTEST_PUBLIC_H_
|
||||
|
||||
#define IOCTL_KMTEST_GET_TESTS \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_READ_DATA)
|
||||
|
||||
#define IOCTL_KMTEST_RUN_TEST \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
|
||||
|
||||
#define KMTEST_DEVICE_NAME L"Kmtest"
|
||||
#define KMTEST_DEVICE_PATH (L"\\\\.\\Global\\GLOBALROOT\\Device\\" KMTEST_DEVICE_NAME)
|
||||
|
||||
#endif /* !defined _KMTEST_PUBLIC_H_ */
|
8
kmtests/kmtest.rbuild
Normal file
8
kmtests/kmtest.rbuild
Normal file
|
@ -0,0 +1,8 @@
|
|||
<module name="kmtest" type="win32cui" installbase="system32" installname="kmtest.exe">
|
||||
<include base="kmtest">include</include>
|
||||
<library>advapi32</library>
|
||||
<directory name="kmtest">
|
||||
<file>kmtest.c</file>
|
||||
<file>service.c</file>
|
||||
</directory>
|
||||
</module>
|
197
kmtests/kmtest/kmtest.c
Normal file
197
kmtests/kmtest/kmtest.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 Loader Application
|
||||
* PROGRAMMER: Thomas Faber <thfabba@gmx.de>
|
||||
*/
|
||||
|
||||
#define UNICODE
|
||||
#include <windows.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "kmtest.h"
|
||||
#include <winioctl.h>
|
||||
#include <kmt_public.h>
|
||||
|
||||
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;
|
||||
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;
|
||||
char buffer[1024];
|
||||
BOOL ret;
|
||||
|
||||
hDevice = CreateFile(KMTEST_DEVICE_PATH, GENERIC_READ | GENERIC_WRITE, 0,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
error = GetLastError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!DeviceIoControl(hDevice, IOCTL_KMTEST_RUN_TEST, testName, strlen(testName), NULL, 0, &bytesRead, NULL))
|
||||
{
|
||||
error = GetLastError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while ((ret = ReadFile(hDevice, buffer, sizeof buffer - 1, &bytesRead, NULL)) != 0)
|
||||
{
|
||||
if (!bytesRead)
|
||||
break;
|
||||
|
||||
assert(bytesRead < sizeof buffer);
|
||||
buffer[bytesRead] = '\0';
|
||||
|
||||
fputs(buffer, stdout);
|
||||
}
|
||||
if (!ret)
|
||||
{
|
||||
error = GetLastError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (hDevice != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hDevice);
|
||||
|
||||
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);
|
||||
puts("\nValid test names:");
|
||||
puts(" Create");
|
||||
puts(" Start");
|
||||
puts(" Stop");
|
||||
puts(" Delete");
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
12
kmtests/kmtest/kmtest.exe.manifest
Normal file
12
kmtests/kmtest/kmtest.exe.manifest
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity version="1.0.0.0" processorArchitecture="x86" name="kmtest"/>
|
||||
<description>ReactOS Kernel-Mode Test Suite Loader Application</description>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
23
kmtests/kmtest/kmtest.h
Normal file
23
kmtests/kmtest/kmtest.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* PROJECT: ReactOS kernel-mode tests
|
||||
* LICENSE: GPLv2+ - See COPYING in the top level directory
|
||||
* PURPOSE: Kernel-Mode Test Suite Loader Application
|
||||
* PROGRAMMER: Thomas Faber <thfabba@gmx.de>
|
||||
*/
|
||||
|
||||
#ifndef _KMTESTS_H_
|
||||
#define _KMTESTS_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* service control functions */
|
||||
typedef DWORD SERVICE_FUNC(SC_HANDLE hManager);
|
||||
|
||||
SERVICE_FUNC Service_Create;
|
||||
SERVICE_FUNC Service_Delete;
|
||||
SERVICE_FUNC Service_Start;
|
||||
SERVICE_FUNC Service_Stop;
|
||||
|
||||
DWORD Service_Control(SERVICE_FUNC *Service_Func);
|
||||
|
||||
#endif /* !defined _KMTESTS_H_ */
|
15
kmtests/kmtest/kmtest.rc
Normal file
15
kmtests/kmtest/kmtest.rc
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* PROJECT: ReactOS kernel-mode tests
|
||||
* LICENSE: GPLv2+ - See COPYING in the top level directory
|
||||
* PURPOSE: Kernel-Mode Test Suite Loader Resource File
|
||||
* PROGRAMMER: Thomas Faber <thfabba@gmx.de>
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Kernel-Mode Test Suite Loader Application\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "kmtest.exe\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "kmtest.exe\0"
|
||||
#include <reactos/version.rc>
|
||||
|
||||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST DISCARDABLE PURE "kmtest/kmtest.exe.manifest"
|
135
kmtests/kmtest/service.c
Normal file
135
kmtests/kmtest/service.c
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* PROJECT: ReactOS kernel-mode tests
|
||||
* LICENSE: GPLv2+ - See COPYING in the top level directory
|
||||
* PURPOSE: Kernel-Mode Test Suite Loader service control functions
|
||||
* PROGRAMMER: Thomas Faber <thfabba@gmx.de>
|
||||
*/
|
||||
|
||||
#define UNICODE
|
||||
#include <windows.h>
|
||||
#include <strsafe.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];
|
||||
HRESULT result = S_OK;
|
||||
|
||||
if (!GetCurrentDirectory(sizeof driverPath / sizeof driverPath[0], driverPath)
|
||||
|| FAILED(result = StringCbCat(driverPath, sizeof driverPath, SERVICE_PATH)))
|
||||
{
|
||||
if (FAILED(result))
|
||||
error = result;
|
||||
else
|
||||
error = GetLastError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
Loading…
Reference in a new issue