[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]; CHAR LogBuffer[ANYSIZE_ARRAY];
} KMT_RESULTBUFFER, *PKMT_RESULTBUFFER; } 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 KmtLoadDriver(IN PCWSTR ServiceName, IN BOOLEAN RestartIfRunning);
VOID KmtUnloadDriver(VOID); VOID KmtUnloadDriver(VOID);
VOID KmtOpenDriver(VOID); VOID KmtOpenDriver(VOID);
@ -46,7 +53,7 @@ VOID KmtCloseDriver(VOID);
DWORD KmtSendToDriver(IN DWORD ControlCode); DWORD KmtSendToDriver(IN DWORD ControlCode);
DWORD KmtSendStringToDriver(IN DWORD ControlCode, IN PCSTR String); 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 */ #endif /* defined KMT_USER_MODE */
extern PKMT_RESULTBUFFER ResultBuffer; 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_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 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 #if defined KMT_DEFINE_TEST_FUNCTIONS
PKMT_RESULTBUFFER ResultBuffer = NULL; PKMT_RESULTBUFFER ResultBuffer = NULL;
@ -123,6 +135,9 @@ static VOID KmtAddToLogBuffer(PKMT_RESULTBUFFER Buffer, PCSTR String, SIZE_T Len
LONG OldLength; LONG OldLength;
LONG NewLength; LONG NewLength;
if (!Buffer)
return;
do do
{ {
OldLength = Buffer->LogBufferLength; OldLength = Buffer->LogBufferLength;
@ -199,6 +214,9 @@ VOID KmtFinishTest(PCSTR TestName)
CHAR MessageBuffer[512]; CHAR MessageBuffer[512];
SIZE_T MessageLength; SIZE_T MessageLength;
if (!ResultBuffer)
return;
MessageLength = KmtXSNPrintF(MessageBuffer, sizeof MessageBuffer, NULL, NULL, MessageLength = KmtXSNPrintF(MessageBuffer, sizeof MessageBuffer, NULL, NULL,
"%s: %ld tests executed (0 marked as todo, %ld failures), %ld skipped.\n", "%s: %ld tests executed (0 marked as todo, %ld failures), %ld skipped.\n",
TestName, TestName,
@ -213,6 +231,9 @@ VOID KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
CHAR MessageBuffer[512]; CHAR MessageBuffer[512];
SIZE_T MessageLength; SIZE_T MessageLength;
if (!ResultBuffer)
return;
if (Condition) if (Condition)
{ {
InterlockedIncrement(&ResultBuffer->Successes); InterlockedIncrement(&ResultBuffer->Successes);
@ -261,6 +282,9 @@ BOOLEAN KmtVSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Argumen
CHAR MessageBuffer[512]; CHAR MessageBuffer[512];
SIZE_T MessageLength; SIZE_T MessageLength;
if (!ResultBuffer)
return !Condition;
if (!Condition) if (!Condition)
{ {
InterlockedIncrement(&ResultBuffer->Skipped); InterlockedIncrement(&ResultBuffer->Skipped);

View file

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

View file

@ -9,20 +9,26 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include <strsafe.h> #include <strsafe.h>
#include <winioctl.h>
#include <assert.h>
#include "kmtest.h" #include "kmtest.h"
#include <kmt_test.h>
#include <kmt_public.h> #include <kmt_public.h>
#include <kmt_test.h>
/* pseudo-tests */ /* pseudo-tests */
START_TEST(Create) 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) 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) START_TEST(Start)
@ -32,7 +38,14 @@ START_TEST(Start)
START_TEST(Stop) 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 */ /* test support functions for special-purpose drivers */
@ -107,7 +120,7 @@ KmtOpenDriver(VOID)
StringCbCopy(DevicePath, sizeof DevicePath, L"\\\\.\\Global\\GLOBALROOT\\Device\\"); StringCbCopy(DevicePath, sizeof DevicePath, L"\\\\.\\Global\\GLOBALROOT\\Device\\");
StringCbCat(DevicePath, sizeof DevicePath, TestServiceName); 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) if (TestDeviceHandle == INVALID_HANDLE_VALUE)
error(Error); error(Error);
@ -139,8 +152,6 @@ KmtCloseDriver(VOID)
} }
} }
/* TODO: check if these will be useful */
/** /**
* @name KmtSendToDriver * @name KmtSendToDriver
* *
@ -154,8 +165,12 @@ DWORD
KmtSendToDriver( KmtSendToDriver(
IN DWORD ControlCode) IN DWORD ControlCode)
{ {
// TODO DWORD BytesRead;
return ERROR_CALL_NOT_IMPLEMENTED;
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 DWORD ControlCode,
IN PCSTR String) IN PCSTR String)
{ {
// TODO DWORD BytesRead;
return ERROR_CALL_NOT_IMPLEMENTED;
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( KmtSendBufferToDriver(
IN DWORD ControlCode, IN DWORD ControlCode,
IN OUT PVOID Buffer, IN OUT PVOID Buffer,
IN DWORD Length) IN OUT PDWORD Length)
{ {
// TODO assert(Length);
return ERROR_CALL_NOT_IMPLEMENTED;
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 DriverClose;
static DRIVER_DISPATCH DriverIoControl; static DRIVER_DISPATCH DriverIoControl;
/* Device Extension layout */
typedef struct
{
PKMT_RESULTBUFFER ResultBuffer;
PMDL Mdl;
} KMT_DEVICE_EXTENSION, *PKMT_DEVICE_EXTENSION;
/* Globals */ /* Globals */
static PDEVICE_OBJECT MainDeviceObject; static PDEVICE_OBJECT MainDeviceObject;
@ -68,13 +61,13 @@ DriverEntry(
&DeviceName, &DeviceName,
FILE_DEVICE_UNKNOWN, FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN | FILE_READ_ONLY_DEVICE, FILE_DEVICE_SECURE_OPEN | FILE_READ_ONLY_DEVICE,
TRUE, &MainDeviceObject); FALSE, &MainDeviceObject);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
goto cleanup; goto cleanup;
DPRINT("DriverEntry. Created DeviceObject %p\n", DPRINT("DriverEntry. Created DeviceObject %p. DeviceExtension %p\n",
MainDeviceObject); MainDeviceObject, MainDeviceObject->DeviceExtension);
DeviceExtension = MainDeviceObject->DeviceExtension; DeviceExtension = MainDeviceObject->DeviceExtension;
DeviceExtension->ResultBuffer = NULL; DeviceExtension->ResultBuffer = NULL;
DeviceExtension->Mdl = NULL; DeviceExtension->Mdl = NULL;
@ -146,19 +139,14 @@ DriverCreate(
{ {
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IoStackLocation; PIO_STACK_LOCATION IoStackLocation;
PKMT_DEVICE_EXTENSION DeviceExtension;
PAGED_CODE(); PAGED_CODE();
IoStackLocation = IoGetCurrentIrpStackLocation(Irp); IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
DPRINT("DriverCreate. DeviceObject=%p\n", DPRINT("DriverCreate. DeviceObject=%p, RequestorMode=%d, FileObject=%p, FsContext=%p, FsContext2=%p\n",
DeviceObject); DeviceObject, Irp->RequestorMode, IoStackLocation->FileObject,
IoStackLocation->FileObject->FsContext, IoStackLocation->FileObject->FsContext2);
DeviceExtension = DeviceObject->DeviceExtension;
ASSERT(!DeviceExtension->Mdl);
ASSERT(!DeviceExtension->ResultBuffer);
ASSERT(!ResultBuffer);
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
@ -195,17 +183,23 @@ DriverClose(
IoStackLocation = IoGetCurrentIrpStackLocation(Irp); IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
DPRINT("DriverClose. DeviceObject=%p\n", DPRINT("DriverClose. DeviceObject=%p, RequestorMode=%d, FileObject=%p, FsContext=%p, FsContext2=%p\n",
DeviceObject); DeviceObject, Irp->RequestorMode, IoStackLocation->FileObject,
IoStackLocation->FileObject->FsContext, IoStackLocation->FileObject->FsContext2);
ASSERT(IoStackLocation->FileObject->FsContext2 == NULL);
DeviceExtension = DeviceObject->DeviceExtension; DeviceExtension = DeviceObject->DeviceExtension;
if (DeviceExtension->Mdl) if (DeviceExtension->Mdl && IoStackLocation->FileObject->FsContext == DeviceExtension->Mdl)
{ {
MmUnlockPages(DeviceExtension->Mdl); MmUnlockPages(DeviceExtension->Mdl);
IoFreeMdl(DeviceExtension->Mdl); IoFreeMdl(DeviceExtension->Mdl);
DeviceExtension->Mdl = NULL; DeviceExtension->Mdl = NULL;
ResultBuffer = DeviceExtension->ResultBuffer = NULL; ResultBuffer = DeviceExtension->ResultBuffer = NULL;
} }
else
{
ASSERT(IoStackLocation->FileObject->FsContext == NULL);
}
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
@ -242,9 +236,10 @@ DriverIoControl(
IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 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, IoStackLocation->Parameters.DeviceIoControl.IoControlCode,
DeviceObject); DeviceObject, IoStackLocation->FileObject,
IoStackLocation->FileObject->FsContext, IoStackLocation->FileObject->FsContext2);
switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode) switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
{ {
@ -315,8 +310,15 @@ DriverIoControl(
if (DeviceExtension->Mdl) if (DeviceExtension->Mdl)
{ {
if (IoStackLocation->FileObject->FsContext != DeviceExtension->Mdl)
{
Status = STATUS_ACCESS_DENIED;
break;
}
MmUnlockPages(DeviceExtension->Mdl); MmUnlockPages(DeviceExtension->Mdl);
IoFreeMdl(DeviceExtension->Mdl); IoFreeMdl(DeviceExtension->Mdl);
IoStackLocation->FileObject->FsContext = NULL;
ResultBuffer = DeviceExtension->ResultBuffer = NULL;
} }
DeviceExtension->Mdl = IoAllocateMdl(IoStackLocation->Parameters.DeviceIoControl.Type3InputBuffer, DeviceExtension->Mdl = IoAllocateMdl(IoStackLocation->Parameters.DeviceIoControl.Type3InputBuffer,
@ -341,6 +343,7 @@ DriverIoControl(
} _SEH2_END; } _SEH2_END;
ResultBuffer = DeviceExtension->ResultBuffer = MmGetSystemAddressForMdlSafe(DeviceExtension->Mdl, NormalPagePriority); ResultBuffer = DeviceExtension->ResultBuffer = MmGetSystemAddressForMdlSafe(DeviceExtension->Mdl, NormalPagePriority);
IoStackLocation->FileObject->FsContext = DeviceExtension->Mdl;
DPRINT("DriverIoControl. ResultBuffer: %ld %ld %ld %ld\n", DPRINT("DriverIoControl. ResultBuffer: %ld %ld %ld %ld\n",
ResultBuffer->Successes, ResultBuffer->Failures, ResultBuffer->Successes, ResultBuffer->Failures,