mirror of
https://github.com/reactos/reactos.git
synced 2024-08-04 10:30:59 +00:00
[KMTESTS]
- use a shared memory buffer for storing test results to provide seamless communication between all test parts - Now user mode code can easily add messages to the buffer svn path=/branches/GSoC_2011/KMTestSuite/; revision=52216
This commit is contained in:
parent
1de7bf0885
commit
a6b4eba335
|
@ -23,6 +23,7 @@ add_library(kmtest_drv SHARED ${KMTEST_DRV_SOURCE})
|
||||||
set_module_type(kmtest_drv kernelmodedriver)
|
set_module_type(kmtest_drv kernelmodedriver)
|
||||||
target_link_libraries(kmtest_drv ${PSEH_LIB})
|
target_link_libraries(kmtest_drv ${PSEH_LIB})
|
||||||
add_importlibs(kmtest_drv ntoskrnl hal)
|
add_importlibs(kmtest_drv ntoskrnl hal)
|
||||||
|
set_property(TARGET kmtest_drv PROPERTY COMPILE_DEFINITIONS KMT_KERNEL_MODE)
|
||||||
|
|
||||||
add_cd_file(TARGET kmtest_drv DESTINATION reactos/system32/drivers FOR all)
|
add_cd_file(TARGET kmtest_drv DESTINATION reactos/system32/drivers FOR all)
|
||||||
|
|
||||||
|
@ -39,5 +40,6 @@ list(APPEND KMTEST_SOURCE
|
||||||
add_executable(kmtest ${KMTEST_SOURCE})
|
add_executable(kmtest ${KMTEST_SOURCE})
|
||||||
set_module_type(kmtest win32cui)
|
set_module_type(kmtest win32cui)
|
||||||
add_importlibs(kmtest advapi32 msvcrt kernel32)
|
add_importlibs(kmtest advapi32 msvcrt kernel32)
|
||||||
|
set_property(TARGET kmtest PROPERTY COMPILE_DEFINITIONS KMT_USER_MODE)
|
||||||
|
|
||||||
add_cd_file(TARGET kmtest DESTINATION reactos/bin FOR all)
|
add_cd_file(TARGET kmtest DESTINATION reactos/bin FOR all)
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#define IOCTL_KMTEST_RUN_TEST \
|
#define IOCTL_KMTEST_RUN_TEST \
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
|
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
|
||||||
|
|
||||||
|
#define IOCTL_KMTEST_SET_RESULTBUFFER \
|
||||||
|
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
|
||||||
|
|
||||||
#define KMTEST_DEVICE_NAME L"Kmtest"
|
#define KMTEST_DEVICE_NAME L"Kmtest"
|
||||||
#define KMTEST_DEVICE_PATH (L"\\\\.\\Global\\GLOBALROOT\\Device\\" KMTEST_DEVICE_NAME)
|
#define KMTEST_DEVICE_PATH (L"\\\\.\\Global\\GLOBALROOT\\Device\\" KMTEST_DEVICE_NAME)
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
#ifndef _KMTEST_TEST_H_
|
#ifndef _KMTEST_TEST_H_
|
||||||
#define _KMTEST_TEST_H_
|
#define _KMTEST_TEST_H_
|
||||||
|
|
||||||
#include <kmt_log.h>
|
|
||||||
|
|
||||||
typedef void KMT_TESTFUNC(void);
|
typedef void KMT_TESTFUNC(void);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -22,4 +20,60 @@ typedef const KMT_TEST CKMT_TEST, *PCKMT_TEST;
|
||||||
|
|
||||||
extern const KMT_TEST TestList[];
|
extern const KMT_TEST TestList[];
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
volatile LONG Successes;
|
||||||
|
volatile LONG Failures;
|
||||||
|
volatile LONG LogBufferLength;
|
||||||
|
LONG LogBufferMaxLength;
|
||||||
|
CHAR LogBuffer[ANYSIZE_ARRAY];
|
||||||
|
} KMT_RESULTBUFFER, *PKMT_RESULTBUFFER;
|
||||||
|
|
||||||
|
extern PKMT_RESULTBUFFER ResultBuffer;
|
||||||
|
|
||||||
|
#if defined KMT_DEFINE_TEST_FUNCTIONS
|
||||||
|
PKMT_RESULTBUFFER ResultBuffer = NULL;
|
||||||
|
|
||||||
|
#if defined KMT_USER_MODE
|
||||||
|
static PKMT_RESULTBUFFER KmtAllocateResultBuffer(SIZE_T LogBufferMaxLength)
|
||||||
|
{
|
||||||
|
PKMT_RESULTBUFFER Buffer = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(KMT_RESULTBUFFER, LogBuffer[LogBufferMaxLength]));
|
||||||
|
|
||||||
|
Buffer->Successes = 0;
|
||||||
|
Buffer->Failures = 0;
|
||||||
|
Buffer->LogBufferLength = 0;
|
||||||
|
Buffer->LogBufferMaxLength = LogBufferMaxLength;
|
||||||
|
|
||||||
|
return Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID KmtFreeResultBuffer(PKMT_RESULTBUFFER Buffer)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, Buffer);
|
||||||
|
}
|
||||||
|
#endif /* defined KMT_USER_MODE */
|
||||||
|
|
||||||
|
#define KmtMemCpy memcpy
|
||||||
|
|
||||||
|
static VOID KmtAddToLogBuffer(PKMT_RESULTBUFFER Buffer, PCSTR String, SIZE_T Length)
|
||||||
|
{
|
||||||
|
LONG OldLength;
|
||||||
|
LONG NewLength;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
OldLength = Buffer->LogBufferLength;
|
||||||
|
NewLength = OldLength + Length;
|
||||||
|
if (NewLength > Buffer->LogBufferMaxLength)
|
||||||
|
{
|
||||||
|
/* TODO: indicate failure somehow */
|
||||||
|
__debugbreak();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (InterlockedCompareExchange(&Buffer->LogBufferLength, NewLength, OldLength) != OldLength);
|
||||||
|
|
||||||
|
KmtMemCpy(&Buffer->LogBuffer[OldLength], String, Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined KMT_DEFINE_TEST_FUNCTIONS */
|
||||||
|
|
||||||
#endif /* !defined _KMTEST_TEST_H_ */
|
#endif /* !defined _KMTEST_TEST_H_ */
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<module name="kmtest" type="win32cui" installbase="system32" installname="kmtest.exe">
|
<module name="kmtest" type="win32cui" installbase="system32" installname="kmtest.exe">
|
||||||
<include base="kmtest">include</include>
|
<include base="kmtest">include</include>
|
||||||
<library>advapi32</library>
|
<library>advapi32</library>
|
||||||
|
<define name="KMT_USER_MODE" />
|
||||||
<directory name="kmtest">
|
<directory name="kmtest">
|
||||||
<file>kmtest.c</file>
|
<file>kmtest.c</file>
|
||||||
<file>service.c</file>
|
<file>service.c</file>
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
#include "kmtest.h"
|
#include "kmtest.h"
|
||||||
#include <winioctl.h>
|
#include <winioctl.h>
|
||||||
#include <kmt_public.h>
|
#include <kmt_public.h>
|
||||||
|
#define KMT_DEFINE_TEST_FUNCTIONS
|
||||||
|
#include <kmt_test.h>
|
||||||
|
|
||||||
|
#define LOGBUFFER_SIZE 65000
|
||||||
|
|
||||||
static void OutputError(FILE *fp, DWORD error);
|
static void OutputError(FILE *fp, DWORD error);
|
||||||
static DWORD RunTest(char *testName);
|
static DWORD RunTest(char *testName);
|
||||||
|
@ -40,9 +44,14 @@ static DWORD RunTest(char *testName)
|
||||||
{
|
{
|
||||||
DWORD error = ERROR_SUCCESS;
|
DWORD error = ERROR_SUCCESS;
|
||||||
HANDLE hDevice = INVALID_HANDLE_VALUE;
|
HANDLE hDevice = INVALID_HANDLE_VALUE;
|
||||||
DWORD bytesRead;
|
DWORD bytesRead, bytesWritten;
|
||||||
char buffer[1024];
|
|
||||||
BOOL ret;
|
ResultBuffer = KmtAllocateResultBuffer(LOGBUFFER_SIZE);
|
||||||
|
if (!ResultBuffer)
|
||||||
|
{
|
||||||
|
error = GetLastError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
hDevice = CreateFile(KMTEST_DEVICE_PATH, GENERIC_READ | GENERIC_WRITE, 0,
|
hDevice = CreateFile(KMTEST_DEVICE_PATH, GENERIC_READ | GENERIC_WRITE, 0,
|
||||||
NULL, OPEN_EXISTING, 0, NULL);
|
NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
@ -53,23 +62,19 @@ static DWORD RunTest(char *testName)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!DeviceIoControl(hDevice, IOCTL_KMTEST_SET_RESULTBUFFER, ResultBuffer, FIELD_OFFSET(KMT_RESULTBUFFER, LogBuffer[LOGBUFFER_SIZE]), NULL, 0, &bytesRead, NULL))
|
||||||
|
{
|
||||||
|
error = GetLastError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (!DeviceIoControl(hDevice, IOCTL_KMTEST_RUN_TEST, testName, strlen(testName), NULL, 0, &bytesRead, NULL))
|
if (!DeviceIoControl(hDevice, IOCTL_KMTEST_RUN_TEST, testName, strlen(testName), NULL, 0, &bytesRead, NULL))
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((ret = ReadFile(hDevice, buffer, sizeof buffer - 1, &bytesRead, NULL)) != 0)
|
if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), ResultBuffer->LogBuffer, ResultBuffer->LogBufferLength, &bytesWritten, NULL))
|
||||||
{
|
|
||||||
if (!bytesRead)
|
|
||||||
break;
|
|
||||||
|
|
||||||
assert(bytesRead < sizeof buffer);
|
|
||||||
buffer[bytesRead] = '\0';
|
|
||||||
|
|
||||||
fputs(buffer, stdout);
|
|
||||||
}
|
|
||||||
if (!ret)
|
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -79,6 +84,9 @@ cleanup:
|
||||||
if (hDevice != INVALID_HANDLE_VALUE)
|
if (hDevice != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle(hDevice);
|
CloseHandle(hDevice);
|
||||||
|
|
||||||
|
if (ResultBuffer)
|
||||||
|
KmtFreeResultBuffer(ResultBuffer);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<library>ntdll</library>
|
<library>ntdll</library>
|
||||||
<library>hal</library>
|
<library>hal</library>
|
||||||
<library>pseh</library>
|
<library>pseh</library>
|
||||||
|
<define name="KMT_KERNEL_MODE" />
|
||||||
<directory name="kmtest_drv">
|
<directory name="kmtest_drv">
|
||||||
<file>kmtest_drv.c</file>
|
<file>kmtest_drv.c</file>
|
||||||
<file>log.c</file>
|
<file>log.c</file>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <ntddk.h>
|
#include <ntddk.h>
|
||||||
#include <ntstrsafe.h>
|
#include <ntstrsafe.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <pseh/pseh2.h>
|
||||||
|
|
||||||
//#define NDEBUG
|
//#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
@ -19,9 +20,16 @@
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
DRIVER_INITIALIZE DriverEntry;
|
DRIVER_INITIALIZE DriverEntry;
|
||||||
static DRIVER_UNLOAD DriverUnload;
|
static DRIVER_UNLOAD DriverUnload;
|
||||||
static DRIVER_DISPATCH DriverCreateClose;
|
static DRIVER_DISPATCH DriverCreate;
|
||||||
|
static DRIVER_DISPATCH DriverClose;
|
||||||
static DRIVER_DISPATCH DriverIoControl;
|
static DRIVER_DISPATCH DriverIoControl;
|
||||||
static DRIVER_DISPATCH DriverRead;
|
|
||||||
|
/* Device Extension layout */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PKMT_RESULTBUFFER ResultBuffer;
|
||||||
|
PMDL Mdl;
|
||||||
|
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
static PDEVICE_OBJECT MainDeviceObject;
|
static PDEVICE_OBJECT MainDeviceObject;
|
||||||
|
@ -43,6 +51,8 @@ NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING Re
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
UNICODE_STRING DeviceName;
|
UNICODE_STRING DeviceName;
|
||||||
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER(RegistryPath);
|
UNREFERENCED_PARAMETER(RegistryPath);
|
||||||
|
@ -55,7 +65,8 @@ NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING Re
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\Kmtest");
|
RtlInitUnicodeString(&DeviceName, L"\\Device\\Kmtest");
|
||||||
Status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN,
|
Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &DeviceName,
|
||||||
|
FILE_DEVICE_UNKNOWN,
|
||||||
FILE_DEVICE_SECURE_OPEN | FILE_READ_ONLY_DEVICE,
|
FILE_DEVICE_SECURE_OPEN | FILE_READ_ONLY_DEVICE,
|
||||||
TRUE, &MainDeviceObject);
|
TRUE, &MainDeviceObject);
|
||||||
|
|
||||||
|
@ -64,13 +75,14 @@ NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING Re
|
||||||
|
|
||||||
DPRINT("DriverEntry. Created DeviceObject %p\n",
|
DPRINT("DriverEntry. Created DeviceObject %p\n",
|
||||||
MainDeviceObject);
|
MainDeviceObject);
|
||||||
MainDeviceObject->Flags |= DO_DIRECT_IO;
|
DeviceExtension = MainDeviceObject->DeviceExtension;
|
||||||
|
DeviceExtension->ResultBuffer = NULL;
|
||||||
|
DeviceExtension->Mdl = NULL;
|
||||||
|
|
||||||
DriverObject->DriverUnload = DriverUnload;
|
DriverObject->DriverUnload = DriverUnload;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverCreateClose;
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverCreate;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverCreateClose;
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverClose;
|
||||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverIoControl;
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverIoControl;
|
||||||
DriverObject->MajorFunction[IRP_MJ_READ] = DriverRead;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (MainDeviceObject && !NT_SUCCESS(Status))
|
if (MainDeviceObject && !NT_SUCCESS(Status))
|
||||||
|
@ -100,15 +112,21 @@ static VOID NTAPI DriverUnload(IN PDRIVER_OBJECT DriverObject)
|
||||||
DPRINT("DriverUnload\n");
|
DPRINT("DriverUnload\n");
|
||||||
|
|
||||||
if (MainDeviceObject)
|
if (MainDeviceObject)
|
||||||
|
{
|
||||||
|
PDEVICE_EXTENSION DeviceExtension = MainDeviceObject->DeviceExtension;
|
||||||
|
ASSERT(!DeviceExtension->Mdl);
|
||||||
|
ASSERT(!DeviceExtension->ResultBuffer);
|
||||||
|
ASSERT(!ResultBuffer);
|
||||||
IoDeleteDevice(MainDeviceObject);
|
IoDeleteDevice(MainDeviceObject);
|
||||||
|
}
|
||||||
|
|
||||||
LogFree();
|
LogFree();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name DriverCreateClose
|
* @name DriverCreate
|
||||||
*
|
*
|
||||||
* Driver Dispatch function for CreateFile/CloseHandle.
|
* Driver Dispatch function for CreateFile
|
||||||
*
|
*
|
||||||
* @param DeviceObject
|
* @param DeviceObject
|
||||||
* Device Object
|
* Device Object
|
||||||
|
@ -117,19 +135,66 @@ static VOID NTAPI DriverUnload(IN PDRIVER_OBJECT DriverObject)
|
||||||
*
|
*
|
||||||
* @return Status
|
* @return Status
|
||||||
*/
|
*/
|
||||||
static NTSTATUS NTAPI DriverCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
static NTSTATUS NTAPI DriverCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PIO_STACK_LOCATION IoStackLocation;
|
PIO_STACK_LOCATION IoStackLocation;
|
||||||
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
DPRINT("DriverCreateClose. Function=%s, DeviceObject=%p\n",
|
DPRINT("DriverCreate. DeviceObject=%p\n",
|
||||||
IoStackLocation->MajorFunction == IRP_MJ_CREATE ? "Create" : "Close",
|
|
||||||
DeviceObject);
|
DeviceObject);
|
||||||
|
|
||||||
|
DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(!DeviceExtension->Mdl);
|
||||||
|
ASSERT(!DeviceExtension->ResultBuffer);
|
||||||
|
ASSERT(!ResultBuffer);
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name DriverClose
|
||||||
|
*
|
||||||
|
* Driver Dispatch function for CloseHandle.
|
||||||
|
*
|
||||||
|
* @param DeviceObject
|
||||||
|
* Device Object
|
||||||
|
* @param Irp
|
||||||
|
* I/O request packet
|
||||||
|
*
|
||||||
|
* @return Status
|
||||||
|
*/
|
||||||
|
static NTSTATUS NTAPI DriverClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
||||||
|
{
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PIO_STACK_LOCATION IoStackLocation;
|
||||||
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
DPRINT("DriverClose. DeviceObject=%p\n",
|
||||||
|
DeviceObject);
|
||||||
|
|
||||||
|
DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
if (DeviceExtension->Mdl)
|
||||||
|
{
|
||||||
|
MmUnlockPages(DeviceExtension->Mdl);
|
||||||
|
IoFreeMdl(DeviceExtension->Mdl);
|
||||||
|
DeviceExtension->Mdl = NULL;
|
||||||
|
ResultBuffer = DeviceExtension->ResultBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
@ -223,6 +288,48 @@ static NTSTATUS NTAPI DriverIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Ir
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case IOCTL_KMTEST_SET_RESULTBUFFER:
|
||||||
|
{
|
||||||
|
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
DPRINT("DriverIoControl. IOCTL_KMTEST_SET_RESULTBUFFER, inlen=%lu, outlen=%lu\n",
|
||||||
|
IoStackLocation->Parameters.DeviceIoControl.InputBufferLength,
|
||||||
|
IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength);
|
||||||
|
|
||||||
|
if (DeviceExtension->Mdl)
|
||||||
|
{
|
||||||
|
MmUnlockPages(DeviceExtension->Mdl);
|
||||||
|
IoFreeMdl(DeviceExtension->Mdl);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceExtension->Mdl = IoAllocateMdl(IoStackLocation->Parameters.DeviceIoControl.Type3InputBuffer,
|
||||||
|
IoStackLocation->Parameters.DeviceIoControl.InputBufferLength,
|
||||||
|
FALSE, FALSE, NULL);
|
||||||
|
if (!DeviceExtension->Mdl)
|
||||||
|
{
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
MmProbeAndLockPages(DeviceExtension->Mdl, KernelMode, IoModifyAccess);
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
IoFreeMdl(DeviceExtension->Mdl);
|
||||||
|
DeviceExtension->Mdl = NULL;
|
||||||
|
break;
|
||||||
|
} _SEH2_END;
|
||||||
|
|
||||||
|
ResultBuffer = DeviceExtension->ResultBuffer = MmGetSystemAddressForMdlSafe(DeviceExtension->Mdl, NormalPagePriority);
|
||||||
|
|
||||||
|
DPRINT("DriverIoControl. ResultBuffer: %ld %ld %ld %ld\n",
|
||||||
|
ResultBuffer->Successes, ResultBuffer->Failures,
|
||||||
|
ResultBuffer->LogBufferLength, ResultBuffer->LogBufferMaxLength);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
DPRINT1("DriverIoControl. Invalid IoCtl code 0x%08X\n",
|
DPRINT1("DriverIoControl. Invalid IoCtl code 0x%08X\n",
|
||||||
IoStackLocation->Parameters.DeviceIoControl.IoControlCode);
|
IoStackLocation->Parameters.DeviceIoControl.IoControlCode);
|
||||||
|
@ -237,46 +344,3 @@ static NTSTATUS NTAPI DriverIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Ir
|
||||||
|
|
||||||
return Status;
|
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,14 +9,8 @@
|
||||||
#include <ntstrsafe.h>
|
#include <ntstrsafe.h>
|
||||||
|
|
||||||
#include <kmt_log.h>
|
#include <kmt_log.h>
|
||||||
|
#define KMT_DEFINE_TEST_FUNCTIONS
|
||||||
#define LOGBUFFER_MAX (1024UL * 1024)
|
#include <kmt_test.h>
|
||||||
static PCHAR LogBuffer;
|
|
||||||
static SIZE_T LogOffset;
|
|
||||||
|
|
||||||
#define LOG_TAG 'LtmK'
|
|
||||||
|
|
||||||
/* TODO: allow concurrent log buffer access */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name LogInit
|
* @name LogInit
|
||||||
|
@ -30,11 +24,6 @@ NTSTATUS LogInit(VOID)
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
LogBuffer = ExAllocatePoolWithTag(NonPagedPool, LOGBUFFER_MAX, LOG_TAG);
|
|
||||||
|
|
||||||
if (!LogBuffer)
|
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,8 +37,6 @@ NTSTATUS LogInit(VOID)
|
||||||
VOID LogFree(VOID)
|
VOID LogFree(VOID)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
ExFreePoolWithTag(LogBuffer, LOG_TAG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,10 +51,10 @@ VOID LogFree(VOID)
|
||||||
*/
|
*/
|
||||||
VOID LogPrint(IN PCSTR Message)
|
VOID LogPrint(IN PCSTR Message)
|
||||||
{
|
{
|
||||||
SIZE_T MessageLength = strlen(Message);
|
size_t MessageLength;
|
||||||
ASSERT(LogOffset + MessageLength + 1 < LOGBUFFER_MAX);
|
ASSERT(NT_SUCCESS(RtlStringCbLengthA(Message, 512, &MessageLength)));
|
||||||
RtlCopyMemory(&LogBuffer[LogOffset], Message, MessageLength + 1);
|
|
||||||
LogOffset += MessageLength;
|
KmtAddToLogBuffer(ResultBuffer, Message, MessageLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,47 +92,11 @@ VOID LogPrintF(IN PCSTR Format, ...)
|
||||||
*/
|
*/
|
||||||
VOID LogVPrintF(IN PCSTR Format, va_list Arguments)
|
VOID LogVPrintF(IN PCSTR Format, va_list Arguments)
|
||||||
{
|
{
|
||||||
CHAR Buffer[1024];
|
CHAR Buffer[512];
|
||||||
SIZE_T BufferLength;
|
|
||||||
/* TODO: make this work from any IRQL */
|
/* TODO: make this work from any IRQL */
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
RtlStringCbVPrintfA(Buffer, sizeof Buffer, Format, Arguments);
|
RtlStringCbVPrintfA(Buffer, sizeof Buffer, Format, Arguments);
|
||||||
|
|
||||||
BufferLength = strlen(Buffer);
|
LogPrint(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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* PROGRAMMER: Thomas Faber <thfabba@gmx.de>
|
* PROGRAMMER: Thomas Faber <thfabba@gmx.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <ntddk.h>
|
||||||
#include <kmt_test.h>
|
#include <kmt_test.h>
|
||||||
|
|
||||||
KMT_TESTFUNC Test_Example;
|
KMT_TESTFUNC Test_Example;
|
||||||
|
|
Loading…
Reference in a new issue