mirror of
https://github.com/reactos/reactos.git
synced 2025-04-27 09:00:27 +00:00
- 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:
parent
978fcad8fb
commit
75946e1764
9 changed files with 877 additions and 5 deletions
|
@ -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>
|
||||
|
|
266
rostests/drivers/kmtest/devobj_test.c
Normal file
266
rostests/drivers/kmtest/devobj_test.c
Normal 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;
|
||||
}
|
141
rostests/drivers/kmtest/drvobj_test.c
Normal file
141
rostests/drivers/kmtest/drvobj_test.c
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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>
|
||||
|
|
95
rostests/drivers/kmtest/kmtestassist.c
Normal file
95
rostests/drivers/kmtest/kmtestassist.c
Normal 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;
|
||||
}
|
8
rostests/drivers/kmtest/kmtestassist.rbuild
Normal file
8
rostests/drivers/kmtest/kmtestassist.rbuild
Normal 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>
|
219
rostests/drivers/kmtest/reghelper.c
Normal file
219
rostests/drivers/kmtest/reghelper.c
Normal 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;
|
||||
|
||||
}
|
Loading…
Reference in a new issue