Author: tfaber Date: Fri Jun 10 05:34:00 2011 New Revision: 52168
URL: http://svn.reactos.org/svn/reactos?rev=52168&view=rev Log: [KMTESTS] - add basic driver that can list/run tests and log messages
Added: branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_log.h (with props) branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_test.h (with props) branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/ (with props) branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv.rbuild (with props) branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/kmtest_drv.c (with props) branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/kmtest_drv.rc (with props) branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/log.c (with props) branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/testlist.c (with props) Modified: branches/GSoC_2011/KMTestSuite/kmtests/CMakeLists.txt branches/GSoC_2011/KMTestSuite/kmtests/directory.rbuild
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] Fri Jun 10 05:34:00 2011 @@ -1,6 +1,32 @@ include_directories( include)
+# +# subdirectories containing special-purpose drivers +# +#add_subdirectory(something) + +# +# kmtest_drv.sys driver +# +list(APPEND KMTEST_DRV_SOURCE + kmtest_drv/kmtest_drv.c + kmtest_drv/log.c + kmtest_drv/testlist.c + + kmtest_drv/kmtest_drv.rc) + +add_library(kmtest_drv SHARED ${KMTEST_DRV_SOURCE}) + +set_module_type(kmtest_drv kernelmodedriver) +target_link_libraries(kmtest_drv ${PSEH_LIB}) +add_importlibs(kmtest_drv ntoskrnl hal) + +add_cd_file(TARGET kmtest_drv DESTINATION reactos/system32/drivers FOR all) + +# +# kmtest.exe loader application +# set_rc_compiler()
add_definitions(-D_DLL -D__USE_CRTIMP)
Modified: branches/GSoC_2011/KMTestSuite/kmtests/directory.rbuild URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/di... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/directory.rbuild [iso-8859-1] (original) +++ branches/GSoC_2011/KMTestSuite/kmtests/directory.rbuild [iso-8859-1] Fri Jun 10 05:34:00 2011 @@ -5,4 +5,5 @@ <xi:include href="something/something_drv.rbuild" /> </directory>--> <xi:include href="kmtest.rbuild" /> + <xi:include href="kmtest_drv.rbuild" /> </group>
Added: branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_log.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/in... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_log.h (added) +++ branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_log.h [iso-8859-1] Fri Jun 10 05:34:00 2011 @@ -1,0 +1,21 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Kernel-Mode Test Suite Driver logging function declarations + * PROGRAMMER: Thomas Faber thfabba@gmx.de + */ + +#ifndef _KMTEST_LOG_H_ +#define _KMTEST_LOG_H_ + +#include <ntddk.h> + +NTSTATUS LogInit(VOID); +VOID LogFree(VOID); + +VOID LogPrint(IN PCSTR Message); +VOID LogPrintF(IN PCSTR Format, ...); +VOID LogVPrintF(IN PCSTR Format, va_list Arguments); +SIZE_T LogRead(OUT PVOID Buffer, IN SIZE_T BufferSize); + +#endif /* !defined _KMTEST_LOG_H_ */
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_log.h ------------------------------------------------------------------------------ svn:eol-style = native
Added: 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 (added) +++ branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_test.h [iso-8859-1] Fri Jun 10 05:34:00 2011 @@ -1,0 +1,25 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Kernel-Mode Test Suite test declarations + * PROGRAMMER: Thomas Faber thfabba@gmx.de + */ + +#ifndef _KMTEST_TEST_H_ +#define _KMTEST_TEST_H_ + +#include <kmt_log.h> + +typedef void KMT_TESTFUNC(void); + +typedef struct +{ + const char *TestName; + KMT_TESTFUNC *TestFunction; +} KMT_TEST, *PKMT_TEST; + +typedef const KMT_TEST CKMT_TEST, *PCKMT_TEST; + +extern const KMT_TEST TestList[]; + +#endif /* !defined _KMTEST_TEST_H_ */
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/include/kmt_test.h ------------------------------------------------------------------------------ svn:eol-style = native
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/ ------------------------------------------------------------------------------ --- bugtraq:logregex (added) +++ bugtraq:logregex Fri Jun 10 05:34:00 2011 @@ -1,0 +1,2 @@ +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+)
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/ ------------------------------------------------------------------------------ bugtraq:message = See issue #%BUGID% for more details.
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/ ------------------------------------------------------------------------------ bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/ ------------------------------------------------------------------------------ tsvn:logminsize = 10
Added: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv.rbuild URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/km... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv.rbuild (added) +++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv.rbuild [iso-8859-1] Fri Jun 10 05:34:00 2011 @@ -1,0 +1,12 @@ +<module name="kmtest_drv" type="kernelmodedriver" installbase="system32/drivers" installname="kmtest_drv.sys"> + <include base="kmtest_drv">include</include> + <library>ntoskrnl</library> + <library>ntdll</library> + <library>hal</library> + <library>pseh</library> + <directory name="kmtest_drv"> + <file>kmtest_drv.c</file> + <file>log.c</file> + <file>testlist.c</file> + </directory> +</module>
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv.rbuild ------------------------------------------------------------------------------ svn:eol-style = native
Added: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/kmtest_drv.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/km... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/kmtest_drv.c (added) +++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/kmtest_drv.c [iso-8859-1] Fri Jun 10 05:34:00 2011 @@ -1,0 +1,282 @@ +/* + * 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 + */ + +#include <ntddk.h> +#include <ntstrsafe.h> +#include <limits.h> + +//#define NDEBUG +#include <debug.h> + +#include <kmt_public.h> +#include <kmt_log.h> +#include <kmt_test.h> + +/* Prototypes */ +DRIVER_INITIALIZE DriverEntry; +static DRIVER_UNLOAD DriverUnload; +static DRIVER_DISPATCH DriverCreateClose; +static DRIVER_DISPATCH DriverIoControl; +static DRIVER_DISPATCH DriverRead; + +/* Globals */ +static PDEVICE_OBJECT MainDeviceObject; + +/* Entry */ +/** + * @name DriverEntry + * + * Driver Entry point. + * + * @param DriverObject + * Driver Object + * @param RegistryPath + * Driver Registry Path + * + * @return Status + */ +NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) +{ + NTSTATUS Status = STATUS_SUCCESS; + UNICODE_STRING DeviceName; + PAGED_CODE(); + + UNREFERENCED_PARAMETER(RegistryPath); + + DPRINT("DriverEntry\n"); + + Status = LogInit(); + + if (!NT_SUCCESS(Status)) + goto cleanup; + + RtlInitUnicodeString(&DeviceName, L"\Device\Kmtest"); + Status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN | FILE_READ_ONLY_DEVICE, + TRUE, &MainDeviceObject); + + if (!NT_SUCCESS(Status)) + goto cleanup; + + DPRINT("DriverEntry. Created DeviceObject %p\n", + MainDeviceObject); + MainDeviceObject->Flags |= DO_DIRECT_IO; + + DriverObject->DriverUnload = DriverUnload; + DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverCreateClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverCreateClose; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverIoControl; + DriverObject->MajorFunction[IRP_MJ_READ] = DriverRead; + +cleanup: + if (MainDeviceObject && !NT_SUCCESS(Status)) + { + IoDeleteDevice(MainDeviceObject); + MainDeviceObject = NULL; + } + + return Status; +} + +/* Dispatch functions */ +/** + * @name DriverUnload + * + * Driver cleanup funtion. + * + * @param DriverObject + * Driver Object + */ +static VOID NTAPI DriverUnload(IN PDRIVER_OBJECT DriverObject) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverObject); + + DPRINT("DriverUnload\n"); + + if (MainDeviceObject) + IoDeleteDevice(MainDeviceObject); + + LogFree(); +} + +/** + * @name DriverCreateClose + * + * Driver Dispatch function for CreateFile/CloseHandle. + * + * @param DeviceObject + * Device Object + * @param Irp + * I/O request packet + * + * @return Status + */ +static NTSTATUS NTAPI DriverCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +{ + NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION IoStackLocation; + + PAGED_CODE(); + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + DPRINT("DriverCreateClose. Function=%s, DeviceObject=%p\n", + IoStackLocation->MajorFunction == IRP_MJ_CREATE ? "Create" : "Close", + DeviceObject); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; +} + +/** + * @name DriverIoControl + * + * Driver Dispatch function for DeviceIoControl. + * + * @param DeviceObject + * Device Object + * @param Irp + * I/O request packet + * + * @return Status + */ +static NTSTATUS NTAPI DriverIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +{ + NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION IoStackLocation; + ULONG Length = 0; + + PAGED_CODE(); + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + DPRINT("DriverIoControl. Code=0x%08X, DeviceObject=%p\n", + IoStackLocation->Parameters.DeviceIoControl.IoControlCode, + DeviceObject); + + switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_KMTEST_GET_TESTS: + { + PCKMT_TEST TestEntry; + LPSTR OutputBuffer = Irp->AssociatedIrp.SystemBuffer; + size_t Remaining = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength; + + DPRINT("DriverIoControl. IOCTL_KMTEST_GET_TESTS, outlen=%lu\n", + IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength); + + for (TestEntry = TestList; TestEntry->TestName; ++TestEntry) + { + RtlStringCbCopyExA(OutputBuffer, Remaining, TestEntry->TestName, &OutputBuffer, &Remaining, 0); + if (Remaining) + { + *OutputBuffer++ = '\0'; + --Remaining; + } + } + if (Remaining) + { + *OutputBuffer++ = '\0'; + --Remaining; + } + Length = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength - Remaining; + break; + } + case IOCTL_KMTEST_RUN_TEST: + { + ANSI_STRING TestName; + PCKMT_TEST TestEntry; + + DPRINT("DriverIoControl. IOCTL_KMTEST_RUN_TEST, inlen=%lu, outlen=%lu\n", + IoStackLocation->Parameters.DeviceIoControl.InputBufferLength, + IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength); + TestName.Length = TestName.MaximumLength = (USHORT)min(IoStackLocation->Parameters.DeviceIoControl.InputBufferLength, USHRT_MAX); + TestName.Buffer = Irp->AssociatedIrp.SystemBuffer; + DPRINT("DriverIoControl. Run test: %Z\n", &TestName); + + for (TestEntry = TestList; TestEntry->TestName; ++TestEntry) + { + ANSI_STRING EntryName; + RtlInitAnsiString(&EntryName, TestEntry->TestName); + + if (!RtlCompareString(&TestName, &EntryName, FALSE)) + { + DPRINT1("DriverIoControl. Starting test %Z\n", &EntryName); + TestEntry->TestFunction(); + DPRINT1("DriverIoControl. Finished test %Z\n", &EntryName); + break; + } + } + + if (!TestEntry->TestName) + Status = STATUS_OBJECT_NAME_INVALID; + + break; + } + default: + DPRINT1("DriverIoControl. Invalid IoCtl code 0x%08X\n", + IoStackLocation->Parameters.DeviceIoControl.IoControlCode); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Length; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; +} + +/** + * @name DriverRead + * + * Driver Dispatch function for ReadFile. + * + * @param DeviceObject + * Device Object + * @param Irp + * I/O request packet + * + * @return Status + */ +static NTSTATUS NTAPI DriverRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +{ + NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION IoStackLocation; + PVOID ReadBuffer; + SIZE_T Length; + + PAGED_CODE(); + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + DPRINT("DriverRead. Offset=%I64u, Length=%lu, DeviceObject=%p\n", + IoStackLocation->Parameters.Read.ByteOffset.QuadPart, + IoStackLocation->Parameters.Read.Length, + DeviceObject); + + ReadBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); + + Length = LogRead(ReadBuffer, IoStackLocation->Parameters.Read.Length); + + DPRINT("DriverRead. Length of data read: %lu\n", + Length); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Length; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; +}
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/kmtest_drv.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/kmtest_drv.rc URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/km... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/kmtest_drv.rc (added) +++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/kmtest_drv.rc [iso-8859-1] Fri Jun 10 05:34:00 2011 @@ -1,0 +1,15 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Kernel-Mode Test Suite Driver Resource File + * PROGRAMMER: Thomas Faber thfabba@gmx.de + */ + +#include <windows.h> + +#define REACTOS_FILETYPE VFT_DRV +#define REACTOS_FILESUBTYPE VFT2_DRV_SYSTEM +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Kernel-Mode Test Suite Driver\0" +#define REACTOS_STR_INTERNAL_NAME "kmtest.sys\0" +#define REACTOS_STR_ORIGINAL_FILENAME "kmtest.sys\0" +#include <reactos/version.rc>
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/kmtest_drv.rc ------------------------------------------------------------------------------ svn:eol-style = native
Added: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/log.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/km... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/log.c (added) +++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/log.c [iso-8859-1] Fri Jun 10 05:34:00 2011 @@ -1,0 +1,151 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Kernel-Mode Test Suite Driver logging functions + * PROGRAMMER: Thomas Faber thfabba@gmx.de + */ + +#include <ntddk.h> +#include <ntstrsafe.h> + +#include <kmt_log.h> + +#define LOGBUFFER_MAX (1024UL * 1024) +static PCHAR LogBuffer; +static SIZE_T LogOffset; + +#define LOG_TAG 'LtmK' + +/* TODO: allow concurrent log buffer access */ + +/** + * @name LogInit + * + * Initialize logging mechanism. Call from DriverEntry. + * + * @return Status + */ +NTSTATUS LogInit(VOID) +{ + NTSTATUS Status = STATUS_SUCCESS; + PAGED_CODE(); + + LogBuffer = ExAllocatePoolWithTag(NonPagedPool, LOGBUFFER_MAX, LOG_TAG); + + if (!LogBuffer) + Status = STATUS_INSUFFICIENT_RESOURCES; + + return Status; +} + +/** + * @name LogFree + * + * Clean up logging mechanism. Call from Unload. + * + * @return None + */ +VOID LogFree(VOID) +{ + PAGED_CODE(); + + ExFreePoolWithTag(LogBuffer, LOG_TAG); +} + +/** + * @name LogPrint + * + * Print a log message. + * + * @param Message + * Ansi string to be logged + * + * @return None + */ +VOID LogPrint(IN PCSTR Message) +{ + SIZE_T MessageLength = strlen(Message); + ASSERT(LogOffset + MessageLength + 1 < LOGBUFFER_MAX); + RtlCopyMemory(&LogBuffer[LogOffset], Message, MessageLength + 1); + LogOffset += MessageLength; +} + +/** + * @name LogPrintF + * + * Print a formatted log message. + * + * @param Format + * printf-like format string + * @param ... + * Arguments corresponding to the format + * + * @return None + */ +VOID LogPrintF(IN PCSTR Format, ...) +{ + va_list Arguments; + PAGED_CODE(); + va_start(Arguments, Format); + LogVPrintF(Format, Arguments); + va_end(Arguments); +} + +/** + * @name LogVPrintF + * + * Print a formatted log message. + * + * @param Format + * printf-like format string + * @param Arguments + * Arguments corresponding to the format + * + * @return None + */ +VOID LogVPrintF(IN PCSTR Format, va_list Arguments) +{ + CHAR Buffer[1024]; + SIZE_T BufferLength; + /* TODO: make this work from any IRQL */ + PAGED_CODE(); + + RtlStringCbVPrintfA(Buffer, sizeof Buffer, Format, Arguments); + + BufferLength = strlen(Buffer); + ASSERT(LogOffset + BufferLength + 1 < LOGBUFFER_MAX); + RtlCopyMemory(&LogBuffer[LogOffset], Buffer, BufferLength + 1); + LogOffset += BufferLength; +} + +/** + * @name LogRead + * + * Retrieve data from the log buffer. + * + * @param Buffer + * Buffer to copy log data to + * @param BufferSize + * Maximum number of bytes to copy + * + * @return Number of bytes copied + */ +SIZE_T LogRead(OUT PVOID Buffer, IN SIZE_T BufferSize) +{ + SIZE_T Size; + PAGED_CODE(); + + Size = min(BufferSize, LogOffset); + RtlCopyMemory(Buffer, LogBuffer, Size); + + if (BufferSize < LogOffset) + { + SIZE_T SizeLeft = LogOffset - BufferSize; + RtlMoveMemory(LogBuffer, &LogBuffer[LogOffset], SizeLeft); + LogOffset = SizeLeft; + } + else + LogOffset = 0; + + return Size; +}
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/log.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/testlist.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/km... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/testlist.c (added) +++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/testlist.c [iso-8859-1] Fri Jun 10 05:34:00 2011 @@ -1,0 +1,14 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Kernel-Mode Test Suite Driver test list + * PROGRAMMER: Thomas Faber thfabba@gmx.de + */ + +#include <stddef.h> +#include <kmt_test.h> + +const KMT_TEST TestList[] = +{ + { NULL, NULL } +};
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/testlist.c ------------------------------------------------------------------------------ svn:eol-style = native