[KMTESTS]

- prepare the device object for being opened multiple times (required for communication with special-purpose drivers)
- more verbose DPRINTs
- implement utility functions for app<->driver communication
- misc fixes

svn path=/branches/GSoC_2011/KMTestSuite/; revision=52541
This commit is contained in:
Thomas Faber 2011-07-04 19:47:49 +00:00
parent 459f4ac630
commit bf054095df
4 changed files with 93 additions and 42 deletions

View file

@ -38,7 +38,14 @@ typedef struct
CHAR LogBuffer[ANYSIZE_ARRAY];
} KMT_RESULTBUFFER, *PKMT_RESULTBUFFER;
#if defined KMT_USER_MODE
#ifdef KMT_KERNEL_MODE
/* Device Extension layout */
typedef struct
{
PKMT_RESULTBUFFER ResultBuffer;
PMDL Mdl;
} KMT_DEVICE_EXTENSION, *PKMT_DEVICE_EXTENSION;
#elif defined KMT_USER_MODE
VOID KmtLoadDriver(IN PCWSTR ServiceName, IN BOOLEAN RestartIfRunning);
VOID KmtUnloadDriver(VOID);
VOID KmtOpenDriver(VOID);
@ -46,7 +53,7 @@ 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);
DWORD KmtSendBufferToDriver(IN DWORD ControlCode, IN OUT PVOID Buffer, IN OUT PDWORD Length);
#endif /* defined KMT_USER_MODE */
extern PKMT_RESULTBUFFER ResultBuffer;
@ -95,6 +102,11 @@ BOOLEAN KmtSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, ...)
#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)
#define KMT_MAKE_CODE(ControlCode) CTL_CODE(FILE_DEVICE_UNKNOWN, \
0xA00 + (ControlCode), \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#if defined KMT_DEFINE_TEST_FUNCTIONS
PKMT_RESULTBUFFER ResultBuffer = NULL;
@ -123,6 +135,9 @@ static VOID KmtAddToLogBuffer(PKMT_RESULTBUFFER Buffer, PCSTR String, SIZE_T Len
LONG OldLength;
LONG NewLength;
if (!Buffer)
return;
do
{
OldLength = Buffer->LogBufferLength;
@ -199,6 +214,9 @@ VOID KmtFinishTest(PCSTR TestName)
CHAR MessageBuffer[512];
SIZE_T MessageLength;
if (!ResultBuffer)
return;
MessageLength = KmtXSNPrintF(MessageBuffer, sizeof MessageBuffer, NULL, NULL,
"%s: %ld tests executed (0 marked as todo, %ld failures), %ld skipped.\n",
TestName,
@ -213,6 +231,9 @@ VOID KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
CHAR MessageBuffer[512];
SIZE_T MessageLength;
if (!ResultBuffer)
return;
if (Condition)
{
InterlockedIncrement(&ResultBuffer->Successes);
@ -261,6 +282,9 @@ BOOLEAN KmtVSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Argumen
CHAR MessageBuffer[512];
SIZE_T MessageLength;
if (!ResultBuffer)
return !Condition;
if (!Condition)
{
InterlockedIncrement(&ResultBuffer->Skipped);

View file

@ -9,13 +9,13 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <strsafe.h>
#include <winioctl.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "kmtest.h"
#include <winioctl.h>
#include <kmt_public.h>
#define KMT_DEFINE_TEST_FUNCTIONS
#include <kmt_test.h>
@ -187,7 +187,7 @@ OutputResult(
KmtFinishTest(TestName);
if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), ResultBuffer->LogBuffer, ResultBuffer->LogBufferLength, &BytesWritten, NULL))
Error = GetLastError();
error(Error);
return Error;
}
@ -229,7 +229,8 @@ RunTest(
error_goto(Error, cleanup);
cleanup:
OutputResult(TestName);
if (!Error)
OutputResult(TestName);
KmtFreeResultBuffer(ResultBuffer);

View file

@ -9,20 +9,26 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <strsafe.h>
#include <winioctl.h>
#include <assert.h>
#include "kmtest.h"
#include <kmt_test.h>
#include <kmt_public.h>
#include <kmt_test.h>
/* pseudo-tests */
START_TEST(Create)
{
// nothing to do here. All tests start the service if needed
// nothing to do here. All tests create the service if needed
}
START_TEST(Delete)
{
// TODO: delete kmtest service
SC_HANDLE Handle = NULL;
DWORD Error = KmtDeleteService(L"Kmtest", &Handle);
ok_eq_hex(Error, (DWORD)ERROR_SUCCESS);
}
START_TEST(Start)
@ -32,7 +38,14 @@ START_TEST(Start)
START_TEST(Stop)
{
// TODO: stop kmtest service
// TODO: requiring the service to be started for this is... bad,
// especially when it's marked for deletion and won't start ;)
SC_HANDLE Handle = NULL;
DWORD Error = KmtStopService(L"Kmtest", &Handle);
ok_eq_hex(Error, (DWORD)ERROR_SUCCESS);
Error = KmtCloseService(&Handle);
ok_eq_hex(Error, (DWORD)ERROR_SUCCESS);
}
/* test support functions for special-purpose drivers */
@ -107,7 +120,7 @@ KmtOpenDriver(VOID)
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);
TestDeviceHandle = CreateFile(DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (TestDeviceHandle == INVALID_HANDLE_VALUE)
error(Error);
@ -139,8 +152,6 @@ KmtCloseDriver(VOID)
}
}
/* TODO: check if these will be useful */
/**
* @name KmtSendToDriver
*
@ -154,8 +165,12 @@ DWORD
KmtSendToDriver(
IN DWORD ControlCode)
{
// TODO
return ERROR_CALL_NOT_IMPLEMENTED;
DWORD BytesRead;
if (!DeviceIoControl(TestDeviceHandle, KMT_MAKE_CODE(ControlCode), NULL, 0, NULL, 0, &BytesRead, NULL))
return GetLastError();
return ERROR_SUCCESS;
}
/**
@ -173,8 +188,12 @@ KmtSendStringToDriver(
IN DWORD ControlCode,
IN PCSTR String)
{
// TODO
return ERROR_CALL_NOT_IMPLEMENTED;
DWORD BytesRead;
if (!DeviceIoControl(TestDeviceHandle, KMT_MAKE_CODE(ControlCode), (PVOID)String, strlen(String), NULL, 0, &BytesRead, NULL))
return GetLastError();
return ERROR_SUCCESS;
}
/**
@ -190,8 +209,12 @@ DWORD
KmtSendBufferToDriver(
IN DWORD ControlCode,
IN OUT PVOID Buffer,
IN DWORD Length)
IN OUT PDWORD Length)
{
// TODO
return ERROR_CALL_NOT_IMPLEMENTED;
assert(Length);
if (!DeviceIoControl(TestDeviceHandle, KMT_MAKE_CODE(ControlCode), Buffer, *Length, NULL, 0, Length, NULL))
return GetLastError();
return ERROR_SUCCESS;
}

View file

@ -24,13 +24,6 @@ static DRIVER_DISPATCH DriverCreate;
static DRIVER_DISPATCH DriverClose;
static DRIVER_DISPATCH DriverIoControl;
/* Device Extension layout */
typedef struct
{
PKMT_RESULTBUFFER ResultBuffer;
PMDL Mdl;
} KMT_DEVICE_EXTENSION, *PKMT_DEVICE_EXTENSION;
/* Globals */
static PDEVICE_OBJECT MainDeviceObject;
@ -68,13 +61,13 @@ DriverEntry(
&DeviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN | FILE_READ_ONLY_DEVICE,
TRUE, &MainDeviceObject);
FALSE, &MainDeviceObject);
if (!NT_SUCCESS(Status))
goto cleanup;
DPRINT("DriverEntry. Created DeviceObject %p\n",
MainDeviceObject);
DPRINT("DriverEntry. Created DeviceObject %p. DeviceExtension %p\n",
MainDeviceObject, MainDeviceObject->DeviceExtension);
DeviceExtension = MainDeviceObject->DeviceExtension;
DeviceExtension->ResultBuffer = NULL;
DeviceExtension->Mdl = NULL;
@ -146,19 +139,14 @@ DriverCreate(
{
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IoStackLocation;
PKMT_DEVICE_EXTENSION DeviceExtension;
PAGED_CODE();
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
DPRINT("DriverCreate. DeviceObject=%p\n",
DeviceObject);
DeviceExtension = DeviceObject->DeviceExtension;
ASSERT(!DeviceExtension->Mdl);
ASSERT(!DeviceExtension->ResultBuffer);
ASSERT(!ResultBuffer);
DPRINT("DriverCreate. DeviceObject=%p, RequestorMode=%d, FileObject=%p, FsContext=%p, FsContext2=%p\n",
DeviceObject, Irp->RequestorMode, IoStackLocation->FileObject,
IoStackLocation->FileObject->FsContext, IoStackLocation->FileObject->FsContext2);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
@ -195,17 +183,23 @@ DriverClose(
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
DPRINT("DriverClose. DeviceObject=%p\n",
DeviceObject);
DPRINT("DriverClose. DeviceObject=%p, RequestorMode=%d, FileObject=%p, FsContext=%p, FsContext2=%p\n",
DeviceObject, Irp->RequestorMode, IoStackLocation->FileObject,
IoStackLocation->FileObject->FsContext, IoStackLocation->FileObject->FsContext2);
ASSERT(IoStackLocation->FileObject->FsContext2 == NULL);
DeviceExtension = DeviceObject->DeviceExtension;
if (DeviceExtension->Mdl)
if (DeviceExtension->Mdl && IoStackLocation->FileObject->FsContext == DeviceExtension->Mdl)
{
MmUnlockPages(DeviceExtension->Mdl);
IoFreeMdl(DeviceExtension->Mdl);
DeviceExtension->Mdl = NULL;
ResultBuffer = DeviceExtension->ResultBuffer = NULL;
}
else
{
ASSERT(IoStackLocation->FileObject->FsContext == NULL);
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
@ -242,9 +236,10 @@ DriverIoControl(
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
DPRINT("DriverIoControl. Code=0x%08X, DeviceObject=%p\n",
DPRINT("DriverIoControl. Code=0x%08X, DeviceObject=%p, FileObject=%p, FsContext=%p, FsContext2=%p\n",
IoStackLocation->Parameters.DeviceIoControl.IoControlCode,
DeviceObject);
DeviceObject, IoStackLocation->FileObject,
IoStackLocation->FileObject->FsContext, IoStackLocation->FileObject->FsContext2);
switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
{
@ -315,8 +310,15 @@ DriverIoControl(
if (DeviceExtension->Mdl)
{
if (IoStackLocation->FileObject->FsContext != DeviceExtension->Mdl)
{
Status = STATUS_ACCESS_DENIED;
break;
}
MmUnlockPages(DeviceExtension->Mdl);
IoFreeMdl(DeviceExtension->Mdl);
IoStackLocation->FileObject->FsContext = NULL;
ResultBuffer = DeviceExtension->ResultBuffer = NULL;
}
DeviceExtension->Mdl = IoAllocateMdl(IoStackLocation->Parameters.DeviceIoControl.Type3InputBuffer,
@ -341,6 +343,7 @@ DriverIoControl(
} _SEH2_END;
ResultBuffer = DeviceExtension->ResultBuffer = MmGetSystemAddressForMdlSafe(DeviceExtension->Mdl, NormalPagePriority);
IoStackLocation->FileObject->FsContext = DeviceExtension->Mdl;
DPRINT("DriverIoControl. ResultBuffer: %ld %ld %ld %ld\n",
ResultBuffer->Successes, ResultBuffer->Failures,