- FinishTest: Modify DbgPrint to match format of winetests.

- Added basic tests for DriverObject, DeviceObject and Loading/Unloading of drivers.
- Added kmtestassist to be used for testing Attached DeviceObject.
- Added CreateLowerDeviceRegistryKey to manually create volatile registry entry for kmtestassist driver.
- More tests still need to be implemented and still need a user mode application to control kmtest.

svn path=/trunk/; revision=41381
This commit is contained in:
Michael Martin 2009-06-11 14:13:11 +00:00
parent 978fcad8fb
commit 75946e1764
9 changed files with 877 additions and 5 deletions

View file

@ -7,6 +7,9 @@
<directory name="kmtest">
<xi:include href="kmtest/kmtest.rbuild" />
</directory>
<directory name="kmtest">
<xi:include href="kmtest/kmtestassist.rbuild" />
</directory>
<directory name="memtest">
<xi:include href="memtest/memtest.rbuild" />
</directory>

View file

@ -0,0 +1,266 @@
/*
* Driver Regression Tests
*
* Copyright 2009 Michael Martin <martinmnet@hotmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; see the file COPYING.LIB.
* If not, write to the Free Software Foundation,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* INCLUDES *******************************************************************/
#include "kmtest.h"
#include <ddk/ntddk.h>
#include <ddk/ntifs.h>
#include "ntddser.h"
#include "ntndk.h"
VOID LowerDeviceKernelAPITest(PDEVICE_OBJECT DeviceObject, BOOLEAN UnLoading)
{
PDEVICE_OBJECT RetObject;
RetObject = IoGetLowerDeviceObject(DeviceObject);
if (UnLoading)
{
ok(RetObject == 0,
"Expected no Lower DeviceObject, got %p", RetObject);
}
else
{
ok(RetObject == AttachDeviceObject,
"Expected an Attached DeviceObject %p, got %p", AttachDeviceObject, RetObject);
}
if (RetObject)
{
ObDereferenceObject(RetObject);
}
RetObject = IoGetDeviceAttachmentBaseRef(DeviceObject);
ok(RetObject == DeviceObject,
"Expected an Attached DeviceObject %p, got %p", DeviceObject, RetObject);
if (RetObject)
{
ObDereferenceObject(RetObject);
}
}
VOID DeviceCreatedTest(PDEVICE_OBJECT DeviceObject, BOOLEAN ExclusiveAccess)
{
PEXTENDED_DEVOBJ_EXTENSION extdev;
/*Check the device object members */
ok(DeviceObject->Type==3, "Expected Type = 3, got %x", DeviceObject->Type);
ok(DeviceObject->Size = 0xb8, "Expected Size = 0xba, got %x", DeviceObject->Size);
ok(DeviceObject->ReferenceCount == 0, "Expected ReferenceCount = 0, got %lu",
DeviceObject->ReferenceCount);
ok(DeviceObject->DriverObject == ThisDriverObject,
"Expected DriverObject member to match this DriverObject %p, got %p",
ThisDriverObject, DeviceObject->DriverObject);
ok(DeviceObject->NextDevice == NULL, "Expected NextDevice to be NULL, got %p", DeviceObject->NextDevice);
ok(DeviceObject->AttachedDevice == NULL, "Expected AttachDevice to be NULL, got %p", DeviceObject->AttachedDevice);
ok(DeviceObject->Characteristics == 0, "Expected Characteristics to be 0");
if (ExclusiveAccess)
{
ok((DeviceObject->Flags == (DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING | DO_EXCLUSIVE)),
"Expected Flags DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING | DO_EXCLUSIVE, got %lu", DeviceObject->Flags);
}
else
{
ok((DeviceObject->Flags == (DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING)),
"Expected Flags DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING, got %lu", DeviceObject->Flags);
}
ok(DeviceObject->DeviceType == FILE_DEVICE_UNKNOWN,
"Expected DeviceType to match creation parameter FILE_DEVICE_UNKNWOWN, got %lu",
DeviceObject->DeviceType);
ok(DeviceObject->ActiveThreadCount == 0, "Expected ActiveThreadCount = 0, got %lu\n", DeviceObject->ActiveThreadCount);
/*Check the extended extension */
extdev = (PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension;
ok(extdev->ExtensionFlags == 0, "Expected Extended ExtensionFlags to be 0, got %lu", extdev->ExtensionFlags);
ok (extdev->Type == 13, "Expected Type of 13, got %d", extdev->Type);
ok (extdev->Size == 0, "Expected Size of 0, got %d", extdev->Size);
ok (extdev->DeviceObject == DeviceObject, "Expected DeviceOject to match newly created device %p, got %p",
DeviceObject, extdev->DeviceObject);
ok(extdev->AttachedTo == NULL, "Expected AttachTo to be NULL, got %p", extdev->AttachedTo);
ok(extdev->StartIoCount == 0, "Expected StartIoCount = 0, got %lu", extdev->StartIoCount);
ok(extdev->StartIoKey == 0, "Expected StartIoKey = 0, got %lu", extdev->StartIoKey);
ok(extdev->StartIoFlags == 0, "Expected StartIoFlags = 0, got %lu", extdev->StartIoFlags);
}
VOID DeviceDeletionTest(PDEVICE_OBJECT DeviceObject, BOOLEAN Lower)
{
PEXTENDED_DEVOBJ_EXTENSION extdev;
/*Check the device object members */
ok(DeviceObject->Type==3, "Expected Type = 3, got %d", DeviceObject->Type);
ok(DeviceObject->Size = 0xb8, "Expected Size = 0xba, got %d", DeviceObject->Size);
ok(DeviceObject->ReferenceCount == 0, "Expected ReferenceCount = 0, got %lu",
DeviceObject->ReferenceCount);
if (!Lower)
{
ok(DeviceObject->DriverObject == ThisDriverObject,
"Expected DriverObject member to match this DriverObject %p, got %p",
ThisDriverObject, DeviceObject->DriverObject);
}
ok(DeviceObject->NextDevice == NULL, "Expected NextDevice to be NULL, got %p", DeviceObject->NextDevice);
if (Lower)
{
ok(DeviceObject->AttachedDevice == MainDeviceObject,
"Expected AttachDevice to be %p, got %p", MainDeviceObject, DeviceObject->AttachedDevice);
}
else
{
ok(DeviceObject->AttachedDevice == NULL, "Expected AttachDevice to be NULL, got %p", DeviceObject->AttachedDevice);
}
ok(DeviceObject->Flags ==FILE_VIRTUAL_VOLUME,
"Expected Flags FILE_VIRTUAL_VOLUME, got %lu", DeviceObject->Flags);
ok(DeviceObject->DeviceType == FILE_DEVICE_UNKNOWN,
"Expected DeviceType to match creation parameter FILE_DEVICE_UNKNWOWN, got %lu",
DeviceObject->DeviceType);
ok(DeviceObject->ActiveThreadCount == 0, "Expected ActiveThreadCount = 0, got %lu\n", DeviceObject->ActiveThreadCount);
/*Check the extended extension */
extdev = (PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension;
ok(extdev->ExtensionFlags == DOE_UNLOAD_PENDING,
"Expected Extended ExtensionFlags to be DOE_UNLOAD_PENDING, got %lu", extdev->ExtensionFlags);
ok (extdev->Type == 13, "Expected Type of 13, got %d", extdev->Type);
ok (extdev->Size == 0, "Expected Size of 0, got %d", extdev->Size);
ok (extdev->DeviceObject == DeviceObject, "Expected DeviceOject to match newly created device %p, got %p",
DeviceObject, extdev->DeviceObject);
if (Lower)
{
/* Skip this for now */
//ok(extdev->AttachedTo == MainDeviceObject, "Expected AttachTo to %p, got %p", MainDeviceObject, extdev->AttachedTo);
}
else
{
ok(extdev->AttachedTo == NULL, "Expected AttachTo to be NULL, got %p", extdev->AttachedTo);
}
ok(extdev->StartIoCount == 0, "Expected StartIoCount = 0, got %lu", extdev->StartIoCount);
ok(extdev->StartIoKey == 0, "Expected StartIoKey = 0, got %lu", extdev->StartIoKey);
ok(extdev->StartIoFlags == 0, "Expected StartIoFlags = 0, got %lu", extdev->StartIoFlags);
}
VOID DeviceCreateDeleteTest(PDRIVER_OBJECT DriverObject)
{
NTSTATUS Status;
UNICODE_STRING DeviceString;
UNICODE_STRING DosDeviceString;
PDEVICE_OBJECT DeviceObject;
/* Create using wrong directory */
RtlInitUnicodeString(&DeviceString, L"\\Device1\\Kmtest");
Status = IoCreateDevice(DriverObject,
0,
&DeviceString,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&DeviceObject);
ok(Status == STATUS_OBJECT_PATH_NOT_FOUND, "Expected STATUS_OBJECT_PATH_NOT_FOUND, got 0x%lX", Status);
/* Create using correct params with exlusice access */
RtlInitUnicodeString(&DeviceString, L"\\Device\\Kmtest");
Status = IoCreateDevice(DriverObject,
0,
&DeviceString,
FILE_DEVICE_UNKNOWN,
0,
TRUE,
&DeviceObject);
ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX", Status);
DeviceCreatedTest(DeviceObject, TRUE);
/* Delete the device */
if (NT_SUCCESS(Status))
{
IoDeleteDevice(DeviceObject);
ok(DriverObject->DeviceObject == 0, "Expected DriverObject->DeviceObject to be NULL, got %p",
DriverObject->DeviceObject);
}
/* Create using correct params with exlusice access */
Status = IoCreateDevice(DriverObject,
0,
&DeviceString,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&DeviceObject);
ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX", Status);
DeviceCreatedTest(DeviceObject, FALSE);
/* Delete the device */
if (NT_SUCCESS(Status))
{
IoDeleteDevice(DeviceObject);
ok(DriverObject->DeviceObject == 0, "Expected DriverObject->DeviceObject to be NULL, got %p",
DriverObject->DeviceObject);
}
/* Recreate device */
Status = IoCreateDevice(DriverObject,
0,
&DeviceString,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&DeviceObject);
ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX", Status);
RtlInitUnicodeString(&DosDeviceString, L"\\DosDevices\\kmtest");
Status = IoCreateSymbolicLink(&DosDeviceString, &DeviceString);
if (!NT_SUCCESS(Status))
{
/* Delete device object if not successful */
IoDeleteDevice(DeviceObject);
return;
}
MainDeviceObject = DeviceObject;
return;
}
BOOLEAN AttachDeviceTest(PDEVICE_OBJECT DeviceObject, PWCHAR NewDriverRegPath)
{
NTSTATUS Status;
UNICODE_STRING LowerDeviceName;
RtlInitUnicodeString(&LowerDeviceName, NewDriverRegPath);
Status = IoAttachDevice(DeviceObject, &LowerDeviceName, &AttachDeviceObject);
/* TODO: Add more tests */
return TRUE;
}
BOOLEAN DetachDeviceTest(PDEVICE_OBJECT AttachedDevice)
{
IoDetachDevice(AttachedDevice);
/* TODO: Add more tests */
return TRUE;
}

View file

@ -0,0 +1,141 @@
/*
* Driver Regression Tests
*
* Copyright 2009 Michael Martin <martinmnet@hotmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; see the file COPYING.LIB.
* If not, write to the Free Software Foundation,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* INCLUDES *******************************************************************/
#include "kmtest.h"
#include <ddk/ntddk.h>
#include <ddk/ntifs.h>
VOID DriverObjectTest(PDRIVER_OBJECT DriverObject, int DriverStatus)
{
BOOLEAN CheckThisDispatchRoutine;
PVOID FirstMajorFunc;
int i;
ok(DriverObject->Size == sizeof(DRIVER_OBJECT), "Size does not match, got %x",DriverObject->Size);
ok(DriverObject->Type == 4, "Type does not match 4. got %d",DriverObject->Type);
if (DriverStatus == 0)
{
ok(DriverObject->DeviceObject == NULL, "Expected DeviceObject pointer to be 0, got %p",
DriverObject->DeviceObject);
ok (DriverObject->Flags == DRVO_LEGACY_DRIVER,
"Expected Flags to be DRVO_LEGACY_DRIVER, got %lu",
DriverObject->Flags);
}
else if (DriverStatus == 1)
{
ok(DriverObject->DeviceObject != NULL, "Expected DeviceObject pointer to non null");
ok (DriverObject->Flags == (DRVO_LEGACY_DRIVER | DRVO_INITIALIZED),
"Expected Flags to be DRVO_LEGACY_DRIVER | DRVO_INITIALIZED, got %lu",
DriverObject->Flags);
}
else
{
ok(DriverObject->DeviceObject != NULL, "Expected DeviceObject pointer to non null");
ok (DriverObject->Flags == (DRVO_LEGACY_DRIVER | DRVO_INITIALIZED | DRVO_UNLOAD_INVOKED),
"Expected Flags to be DRVO_LEGACY_DRIVER | DRVO_INITIALIZED | DRVO_UNLOAD_INVOKED, got %lu",
DriverObject->Flags);
}
/* Select a routine that was not changed */
FirstMajorFunc = DriverObject->MajorFunction[1];
ok(FirstMajorFunc != 0, "Expected MajorFunction[1] to be non NULL");
if (FirstMajorFunc)
{
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
{
if (DriverStatus > 0) CheckThisDispatchRoutine = (i > 3) && (i != 14);
else CheckThisDispatchRoutine = TRUE;
if (CheckThisDispatchRoutine)
{
ok(DriverObject->MajorFunction[i] == FirstMajorFunc, "Expected MajorFunction[%d] to match %p",
i, FirstMajorFunc);
}
}
}
else
{
ok(TRUE, "Skipped testing for all MajorFunction");
}
}
BOOLEAN ZwLoadTest(PDRIVER_OBJECT DriverObject, PUNICODE_STRING DriverRegistryPath, PWCHAR NewDriverRegPath)
{
UNICODE_STRING RegPath;
NTSTATUS Status;
/* Try to load ourself */
Status = ZwLoadDriver(DriverRegistryPath);
ok (Status == STATUS_IMAGE_ALREADY_LOADED, "Expected NTSTATUS STATUS_IMAGE_ALREADY_LOADED, got 0x%lX", Status);
if (Status != STATUS_IMAGE_ALREADY_LOADED)
{
DbgPrint("WARNING: Loading this a second time will cause BUGCHECK!\n");
}
/* Try to load with a Registry Path that doesnt exist */
RtlInitUnicodeString(&RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\deadbeef");
Status = ZwLoadDriver(&RegPath);
ok (Status == STATUS_OBJECT_NAME_NOT_FOUND, "Expected NTSTATUS STATUS_OBJECT_NAME_NOT_FOUND, got 0x%lX", Status);
/* Load the driver */
RtlInitUnicodeString(&RegPath, NewDriverRegPath);
Status = ZwLoadDriver(&RegPath);
ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX", Status);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
return TRUE;
}
BOOLEAN ZwUnloadTest(PDRIVER_OBJECT DriverObject, PUNICODE_STRING DriverRegistryPath, PWCHAR NewDriverRegPath)
{
UNICODE_STRING RegPath;
NTSTATUS Status;
/* Try to unload ourself, which should fail as our Unload routine hasnt been set yet. */
Status = ZwUnloadDriver(DriverRegistryPath);
ok (Status == STATUS_INVALID_DEVICE_REQUEST, "Expected NTSTATUS STATUS_INVALID_DEVICE_REQUEST, got 0x%lX", Status);
/* Try to unload with a Registry Path that doesnt exist */
RtlInitUnicodeString(&RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\deadbeef");
Status = ZwUnloadDriver(&RegPath);
ok (Status == STATUS_OBJECT_NAME_NOT_FOUND, "Expected NTSTATUS STATUS_OBJECT_NAME_NOT_FOUND, got 0x%lX", Status);
/* Unload the driver */
RtlInitUnicodeString(&RegPath, NewDriverRegPath);
Status = ZwUnloadDriver(&RegPath);
ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX", Status);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
return TRUE;
}

View file

@ -40,7 +40,7 @@ StartTest()
VOID
FinishTest(LPSTR TestName)
{
DbgPrint("Test %s finished with %d succeses and %d failures\n", TestName, successes, failures);
DbgPrint("%s: %d test executed (0 marked as todo, %d failures), 0 skipped.\n", TestName, successes + failures, failures);
}
void kmtest_set_location(const char* file, int line)
@ -100,6 +100,8 @@ int kmtest_ok(int condition, const char *msg, ... )
/* PUBLIC FUNCTIONS ***********************************************************/
PWCHAR CreateLowerDeviceRegistryKey(PUNICODE_STRING RegistryPath, PWCHAR NewDriver);
/*
* Test Declarations
*/
@ -107,6 +109,63 @@ VOID NtoskrnlIoTests();
VOID NtoskrnlObTest();
VOID NtoskrnlExecutiveTests();
VOID NtoskrnlPoolsTest();
VOID DriverObjectTest(PDRIVER_OBJECT, int);
VOID DeviceCreateDeleteTest(PDRIVER_OBJECT);
VOID DeviceObjectTest(PDEVICE_OBJECT);
BOOLEAN ZwLoadTest(PDRIVER_OBJECT, PUNICODE_STRING, PWCHAR);
BOOLEAN ZwUnloadTest(PDRIVER_OBJECT, PUNICODE_STRING, PWCHAR);
BOOLEAN DetachDeviceTest(PDEVICE_OBJECT);
BOOLEAN AttachDeviceTest(PDEVICE_OBJECT, PWCHAR);
VOID LowerDeviceKernelAPITest(PDEVICE_OBJECT, BOOLEAN);
/*
* KmtestDispatch
*/
NTSTATUS
NTAPI
KmtestDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS Status = STATUS_SUCCESS;
if (AttachDeviceObject)
{
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(AttachDeviceObject, Irp);
return Status;
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
/*
* KmtestCreateClose
*/
NTSTATUS
NTAPI
KmtestCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS Status = STATUS_SUCCESS;
if (AttachDeviceObject)
{
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(AttachDeviceObject, Irp);
return Status;
}
/* Do DriverObject Test with Driver Initialized */
DriverObjectTest(DeviceObject->DriverObject, 1);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information=0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
/*
* KmtestUnload
@ -115,7 +174,24 @@ VOID
NTAPI
KmtestUnload(IN PDRIVER_OBJECT DriverObject)
{
/* Nothing to do here */
UNICODE_STRING DosDeviceString;
if(AttachDeviceObject)
{
IoDetachDevice(AttachDeviceObject);
}
/* Do DriverObject Test for Unload */
DriverObjectTest(DriverObject, 2);
if (MainDeviceObject)
{
RtlInitUnicodeString(&DosDeviceString, L"\\DosDevices\\Kmtest");
IoDeleteSymbolicLink(&DosDeviceString);
IoDeleteDevice(MainDeviceObject);
}
FinishTest("Driver Tests");
}
/*
@ -126,15 +202,70 @@ NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
{
DbgPrint("\n===============================================\nKernel Mode Regression Test driver starting...\n");
int i;
PWCHAR LowerDriverRegPath;
/* Set necessary routines */
DriverObject->DriverUnload = KmtestUnload;
DbgPrint("\n===============================================\n");
DbgPrint("Kernel Mode Regression Driver Test starting...\n");
DbgPrint("===============================================\n");
MainDeviceObject = NULL;
AttachDeviceObject = NULL;
ThisDriverObject = DriverObject;
NtoskrnlExecutiveTests();
NtoskrnlIoTests();
NtoskrnlObTest();
NtoskrnlPoolsTest();
/* Start the tests for the driver routines */
StartTest();
/* Do DriverObject Test for Driver Entry */
DriverObjectTest(DriverObject, 0);
/* Create and delete device, on return MainDeviceObject has been created */
DeviceCreateDeleteTest(DriverObject);
/* Make sure a device object was created */
if (MainDeviceObject)
{
LowerDriverRegPath = CreateLowerDeviceRegistryKey(RegistryPath, L"kmtestassist");
if (LowerDriverRegPath)
{
/* Load driver test and load the lower driver */
if (ZwLoadTest(DriverObject, RegistryPath, LowerDriverRegPath))
{
AttachDeviceTest(MainDeviceObject, L"kmtestassists");
if (AttachDeviceObject)
{
LowerDeviceKernelAPITest(MainDeviceObject, FALSE);
}
/* Unload lower driver without detaching from its device */
ZwUnloadTest(DriverObject, RegistryPath, LowerDriverRegPath);
LowerDeviceKernelAPITest(MainDeviceObject, TRUE);
}
else
{
DbgPrint("Failed to load kmtestassist driver\n");
}
}
}
else
{
return STATUS_UNSUCCESSFUL;
}
/* Set all MajorFunctions to NULL to verify that kernel fixes them */
for (i = 1; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i] = NULL;
/* Set necessary routines */
DriverObject->DriverUnload = KmtestUnload;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KmtestDispatch;
DriverObject->MajorFunction[IRP_MJ_CREATE] = KmtestCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = KmtestCreateClose;
return STATUS_SUCCESS;
}

View file

@ -4,6 +4,8 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "ntddk.h"
/*
Some macros, structs, and vars are based or inspired from the great
@ -45,4 +47,8 @@ extern int kmtest_ok( int condition, const char *msg, ... );
#define ok_(file, line) (kmtest_set_location(file, line), 0) ? 0 : kmtest_ok
#define ok ok_(__FILE__, __LINE__)
PDEVICE_OBJECT AttachDeviceObject;
PDEVICE_OBJECT MainDeviceObject;
PDRIVER_OBJECT ThisDriverObject;
#endif /* PNPTEST_H */

View file

@ -6,6 +6,9 @@
<file>kmtest.c</file>
<file>deviface.c</file>
<file>deviface_test.c</file>
<file>drvobj_test.c</file>
<file>devobj_test.c</file>
<file>reghelper.c</file>
<file>ntos_ex.c</file>
<file>ntos_io.c</file>
<file>ntos_ob.c</file>

View file

@ -0,0 +1,95 @@
/*
* Driver Regression Tests
*
* Copyright 2009 Michael Martin <martinmnet@hotmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; see the file COPYING.LIB.
* If not, write to the Free Software Foundation,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* INCLUDES *******************************************************************/
#include "ntddk.h"
#include "ntddser.h"
NTSTATUS
NTAPI
DriverDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
DbgPrint(" ControlCode %x\n",IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information=0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
DriverCreateClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
VOID
NTAPI
DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING DeviceString;
RtlInitUnicodeString(&DeviceString, L"\\DosDevices\\kmtestassist");
IoDeleteSymbolicLink(&DeviceString);
IoDeleteDevice(DriverObject->DeviceObject);
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING path)
{
PDEVICE_OBJECT pDeviceObject;
UNICODE_STRING DriverString;
UNICODE_STRING DeviceString;
NTSTATUS Status= STATUS_DEVICE_CONFIGURATION_ERROR;
RtlInitUnicodeString(&DriverString, L"\\Device\\kmtestassist");
Status = IoCreateDevice(DriverObject,0,&DriverString,FILE_DEVICE_UNKNOWN,0,FALSE,&pDeviceObject);
if (!NT_SUCCESS(Status))
{
return Status;
}
RtlInitUnicodeString(&DeviceString, L"\\DosDevices\\kmtestassist");
Status = IoCreateSymbolicLink(&DeviceString, &DriverString);
if (!NT_SUCCESS(Status))
{
// Delete device object if not successful
IoDeleteDevice(pDeviceObject);
return Status;
}
DriverObject->DriverUnload = DriverUnload;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverDispatch;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverCreateClose;
return Status;
}

View file

@ -0,0 +1,8 @@
<module name="kmtestassist" type="kernelmodedriver" installbase="system32/drivers" installname="kmtestassist.sys">
<bootstrap base="$(CDOUTPUT)" />
<define name="__USE_W32API" />
<include base="ReactOS">include/reactos/drivers</include>
<library>ntoskrnl</library>
<library>hal</library>
<file>kmtestassist.c</file>
</module>

View file

@ -0,0 +1,219 @@
/*
* Driver Regression Tests
*
* Copyright 2009 Michael Martin <martinmnet@hotmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; see the file COPYING.LIB.
* If not, write to the Free Software Foundation,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* INCLUDES *******************************************************************/
#include "kmtest.h"
/*
Adds a service registry entry for a driver
The driver must reside in the same path as this loaded driver
The caller is resposible for releasing memory
*/
PWCHAR CreateLowerDeviceRegistryKey(PUNICODE_STRING RegistryPath, PWCHAR NewDriver)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING Name;
UNICODE_STRING Value;
UNICODE_STRING NewDriverRegPath;
PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInfo = NULL;
HANDLE ServiceKey;
NTSTATUS Status;
ULONG Disposition;
ULONG ServiceDWordValue;
ULONG ResultLength = 0;
ULONG Length = 0;
PWCHAR ReturnPath = NULL;
/* Now lets find out where we were loaded from by using registry */
InitializeObjectAttributes(&ObjectAttributes, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwOpenKey(&ServiceKey, KEY_READ, &ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DbgPrint("ZwOpenKey () failed (Status %x)\n", Status);
return NULL;
}
RtlInitUnicodeString(&Name, L"ImagePath");
/* First query how much memory we need */
Status = ZwQueryValueKey(ServiceKey, &Name, KeyValuePartialInformation, 0, 0, &ResultLength);
ResultLength += sizeof(KEY_VALUE_PARTIAL_INFORMATION);
ValuePartialInfo = ExAllocatePool(PagedPool, ResultLength);
if (!ValuePartialInfo)
{
DbgPrint("Out of memory!\n");
goto cleanup;
}
Length = ResultLength;
Status = ZwQueryValueKey(ServiceKey, &Name, KeyValuePartialInformation, (PVOID)ValuePartialInfo, Length, &ResultLength);
if (!NT_SUCCESS(Status))
{
DbgPrint("ZwQueryValueKey() failed (Status %lx)\n", Status);
goto cleanup;
}
/* Remove the current driver name from the string */
/* FIXME: Dont use hard coded driver name, determine it from the string returned from the above Query */
Length = (wcslen((PWCHAR)ValuePartialInfo->Data) * 2) - (wcslen(L"kmtest.sys") * 2);
RtlZeroMemory((PVOID)((ULONG)ValuePartialInfo->Data + Length),
wcslen(L"drvtests.sys") * 2);
ZwClose(ServiceKey);
/* Now add a registry entry for the driver */
NewDriverRegPath.Length = 0;
NewDriverRegPath.MaximumLength = (wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") +
wcslen(NewDriver) + 1) * sizeof(WCHAR);
NewDriverRegPath.Buffer = ExAllocatePool(PagedPool, NewDriverRegPath.MaximumLength);
if (!NewDriverRegPath.Buffer)
{
DbgPrint("Out of memory!\n");
ExFreePool(NewDriverRegPath.Buffer);
goto cleanup;
}
RtlAppendUnicodeToString(&NewDriverRegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
RtlAppendUnicodeToString(&NewDriverRegPath, NewDriver);
InitializeObjectAttributes(&ObjectAttributes,
&NewDriverRegPath,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
0,
NULL);
Status = ZwCreateKey(&ServiceKey,
KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
&Disposition);
if (!NT_SUCCESS(Status))
{
DbgPrint("ZwCreateKey() failed (Status %lx)\n", Status);
ExFreePool(NewDriverRegPath.Buffer);
goto cleanup;
}
ReturnPath = NewDriverRegPath.Buffer;
RtlInitUnicodeString(&Name, L"ImagePath");
Value.Length = 0;
Value.MaximumLength = (wcslen((PWCHAR)ValuePartialInfo->Data) +
wcslen(NewDriver) + 5) * sizeof(WCHAR);
Value.Buffer = ExAllocatePool(PagedPool, Value.MaximumLength);
if (!Value.Buffer)
{
DbgPrint("Out of memory!\n");
ExFreePool(Value.Buffer);
goto cleanup;
}
RtlAppendUnicodeToString(&Value, (PWCHAR)ValuePartialInfo->Data);
RtlAppendUnicodeToString(&Value, NewDriver);
RtlAppendUnicodeToString(&Value, L".sys");
Status = ZwSetValueKey(ServiceKey,
&Name,
0,
REG_SZ,
Value.Buffer,
(wcslen(Value.Buffer)+1) * sizeof(WCHAR));
ExFreePool(Value.Buffer);
if (!NT_SUCCESS(Status))
{
DbgPrint("ZwCreateKey() failed (Status %lx)\n", Status);
goto cleanup;
}
RtlInitUnicodeString(&Name, L"DisplayName");
RtlInitUnicodeString(&Value, NewDriver);
Status = ZwSetValueKey(ServiceKey,
&Name,
0,
REG_SZ,
Value.Buffer,
(wcslen(Value.Buffer)+1) * sizeof(WCHAR));
if (!NT_SUCCESS(Status))
{
DbgPrint("ZwCreateKey() failed (Status %lx)\n", Status);
goto cleanup;
}
RtlInitUnicodeString(&Name, L"ErrorControl");
ServiceDWordValue = 0;
Status = ZwSetValueKey(ServiceKey,
&Name,
0,
REG_DWORD,
&ServiceDWordValue,
sizeof(ULONG));
if (!NT_SUCCESS(Status))
{
DbgPrint("ZwCreateKey() failed (Status %lx)\n", Status);
goto cleanup;
}
RtlInitUnicodeString(&Name, L"Start");
ServiceDWordValue = 3;
Status = ZwSetValueKey(ServiceKey,
&Name,
0,
REG_DWORD,
&ServiceDWordValue,
sizeof(ULONG));
if (!NT_SUCCESS(Status))
{
DbgPrint("ZwCreateKey() failed (Status %lx)\n", Status);
goto cleanup;
}
RtlInitUnicodeString(&Name, L"Type");
ServiceDWordValue = 0;
Status = ZwSetValueKey(ServiceKey,
&Name,
0,
REG_DWORD,
&ServiceDWordValue,
sizeof(ULONG));
if (!NT_SUCCESS(Status))
{
DbgPrint("ZwCreateKey() failed (Status %lx)\n", Status);
goto cleanup;
}
cleanup:
ZwClose(ServiceKey);
if (ValuePartialInfo) ExFreePool(ValuePartialInfo);
return ReturnPath;
}