#include <ddk/ntddk.h>
#include "kmtest.h"
+#define NDEBUG
+#include <debug.h>
+
LONG successes;
LONG failures;
+LONG skipped;
tls_data glob_data;
/* PRIVATE FUNCTIONS ***********************************************************/
{
successes = 0;
failures = 0;
+ skipped = 0;
}
VOID
-FinishTest(LPSTR TestName)
+FinishTest(HANDLE KeyHandle, LPWSTR TestName)
{
- DbgPrint("%s: %d test executed (0 marked as todo, %d failures), 0 skipped.\n", TestName, successes + failures, failures);
+ WCHAR KeyName[100];
+ LONG total = successes + failures;
+ UNICODE_STRING KeyNameU;
+
+ wcscpy(KeyName, TestName);
+ wcscat(KeyName, L"SuccessCount");
+ RtlInitUnicodeString(&KeyNameU, KeyName);
+
+ ZwSetValueKey(KeyHandle,
+ &KeyNameU,
+ 0,
+ REG_DWORD,
+ &successes,
+ sizeof(ULONG));
+
+ wcscpy(KeyName, TestName);
+ wcscat(KeyName, L"FailureCount");
+ RtlInitUnicodeString(&KeyNameU, KeyName);
+
+ ZwSetValueKey(KeyHandle,
+ &KeyNameU,
+ 0,
+ REG_DWORD,
+ &failures,
+ sizeof(ULONG));
+
+ wcscpy(KeyName, TestName);
+ wcscat(KeyName, L"TotalCount");
+ RtlInitUnicodeString(&KeyNameU, KeyName);
+
+ ZwSetValueKey(KeyHandle,
+ &KeyNameU,
+ 0,
+ REG_DWORD,
+ &total,
+ sizeof(ULONG));
+
+ wcscpy(KeyName, TestName);
+ wcscat(KeyName, L"SkipCount");
+ RtlInitUnicodeString(&KeyNameU, KeyName);
+
+ ZwSetValueKey(KeyHandle,
+ &KeyNameU,
+ 0,
+ REG_DWORD,
+ &skipped,
+ sizeof(ULONG));
+
+ DbgPrint("%S: %d test executed (0 marked as todo, %d failures), %d skipped.\n", TestName, total, failures, skipped);
}
void kmtest_set_location(const char* file, int line)
/*
* Test Declarations
*/
-VOID NtoskrnlIoTests();
-VOID NtoskrnlObTest();
-VOID NtoskrnlExecutiveTests();
-VOID NtoskrnlPoolsTest();
+VOID RegisterDI_Test(HANDLE KeyHandle);
+VOID NtoskrnlIoMdlTest(HANDLE KeyHandle);
+VOID NtoskrnlIoIrpTest(HANDLE KeyHandle);
+VOID NtoskrnlObTest(HANDLE KeyHandle);
+VOID ExTimerTest(HANDLE KeyHandle);
+VOID PoolsTest(HANDLE KeyHandle);
+VOID PoolsCorruption(HANDLE KeyHandle);
+VOID KeStallTest(HANDLE KeyHandle);
VOID DriverObjectTest(PDRIVER_OBJECT, int);
VOID DeviceCreateDeleteTest(PDRIVER_OBJECT);
VOID DeviceObjectTest(PDEVICE_OBJECT);
BOOLEAN AttachDeviceTest(PDEVICE_OBJECT, PWCHAR);
VOID LowerDeviceKernelAPITest(PDEVICE_OBJECT, BOOLEAN);
+typedef enum {
+ TestStageExTimer = 0,
+ TestStageIoMdl,
+ TestStageIoDi,
+ TestStageIoIrp,
+ TestStageMmPoolTest,
+ TestStageMmPoolCorruption,
+ TestStageOb,
+ TestStageKeStall,
+ TestStageDrv,
+ TestStageMax
+} TEST_STAGE;
+
/*
* KmtestDispatch
*/
IoDeleteDevice(MainDeviceObject);
}
- FinishTest("Driver Tests");
+}
+
+static
+PKEY_VALUE_PARTIAL_INFORMATION
+NTAPI
+ReadRegistryValue(HANDLE KeyHandle, PWCHAR ValueName)
+{
+ NTSTATUS Status;
+ PKEY_VALUE_PARTIAL_INFORMATION InformationBuffer = NULL;
+ ULONG AllocatedLength = 0, RequiredLength = 0;
+ UNICODE_STRING ValueNameU;
+
+ RtlInitUnicodeString(&ValueNameU, ValueName);
+
+ Status = ZwQueryValueKey(KeyHandle,
+ &ValueNameU,
+ KeyValuePartialInformation,
+ NULL,
+ 0,
+ &RequiredLength);
+ if (Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW)
+ {
+ InformationBuffer = ExAllocatePool(PagedPool, RequiredLength);
+ AllocatedLength = RequiredLength;
+ if (!InformationBuffer) return NULL;
+
+ Status = ZwQueryValueKey(KeyHandle,
+ &ValueNameU,
+ KeyValuePartialInformation,
+ InformationBuffer,
+ AllocatedLength,
+ &RequiredLength);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to read %S (0x%x)\n", ValueName, Status);
+ if (InformationBuffer != NULL)
+ ExFreePool(InformationBuffer);
+ return NULL;
+ }
+
+ return InformationBuffer;
+}
+
+static
+VOID
+RunKernelModeTest(PDRIVER_OBJECT DriverObject,
+ PUNICODE_STRING RegistryPath,
+ HANDLE KeyHandle,
+ TEST_STAGE Stage)
+{
+ UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"CurrentStage");
+ PWCHAR LowerDriverRegPath;
+
+ DPRINT1("Running stage %d test...\n", Stage);
+
+ ZwSetValueKey(KeyHandle,
+ &KeyName,
+ 0,
+ REG_DWORD,
+ &Stage,
+ sizeof(ULONG));
+
+ switch (Stage)
+ {
+ case TestStageExTimer:
+ ExTimerTest(KeyHandle);
+ break;
+
+ case TestStageIoMdl:
+ NtoskrnlIoMdlTest(KeyHandle);
+ break;
+
+ case TestStageIoDi:
+ RegisterDI_Test(KeyHandle);
+ break;
+
+ case TestStageIoIrp:
+ NtoskrnlIoIrpTest(KeyHandle);
+ break;
+
+ case TestStageMmPoolTest:
+ PoolsTest(KeyHandle);
+ break;
+
+ case TestStageMmPoolCorruption:
+ PoolsCorruption(KeyHandle);
+ break;
+
+ case TestStageOb:
+ NtoskrnlObTest(KeyHandle);
+ break;
+
+ case TestStageKeStall:
+ KeStallTest(KeyHandle);
+ break;
+
+ case TestStageDrv:
+ /* 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");
+ }
+ }
+ }
+
+ FinishTest(KeyHandle, L"DriverTest");
+ break;
+
+ default:
+ ASSERT(FALSE);
+ break;
+ }
}
/*
PUNICODE_STRING RegistryPath)
{
int i;
- PWCHAR LowerDriverRegPath;
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING ParameterKeyName = RTL_CONSTANT_STRING(L"Parameters");
+ PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
+ PULONG KeyValue;
+ TEST_STAGE CurrentStage;
+ HANDLE DriverKeyHandle, ParameterKeyHandle;
DbgPrint("\n===============================================\n");
DbgPrint("Kernel Mode Regression Driver Test starting...\n");
DbgPrint("===============================================\n");
- MainDeviceObject = NULL;
- AttachDeviceObject = NULL;
- ThisDriverObject = DriverObject;
-
- NtoskrnlExecutiveTests();
- NtoskrnlIoTests();
- NtoskrnlObTest();
- NtoskrnlPoolsTest();
+ InitializeObjectAttributes(&ObjectAttributes,
+ RegistryPath,
+ OBJ_CASE_INSENSITIVE,
+ 0,
+ NULL);
- /* Start the tests for the driver routines */
- StartTest();
+ Status = ZwOpenKey(&DriverKeyHandle,
+ KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to open %wZ\n", RegistryPath);
+ return Status;
+ }
- /* Do DriverObject Test for Driver Entry */
- DriverObjectTest(DriverObject, 0);
- /* Create and delete device, on return MainDeviceObject has been created */
- DeviceCreateDeleteTest(DriverObject);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ParameterKeyName,
+ OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+ DriverKeyHandle,
+ NULL);
+ Status = ZwCreateKey(&ParameterKeyHandle,
+ KEY_SET_VALUE | KEY_QUERY_VALUE,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ NULL);
+ ZwClose(DriverKeyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create %wZ\\%wZ\n", RegistryPath, &ParameterKeyName);
+ return Status;
+ }
- /* Make sure a device object was created */
- if (MainDeviceObject)
+ KeyInfo = ReadRegistryValue(ParameterKeyHandle, L"CurrentStage");
+ if (KeyInfo)
{
- LowerDriverRegPath = CreateLowerDeviceRegistryKey(RegistryPath, L"kmtestassist");
+ if (KeyInfo->DataLength != sizeof(ULONG))
+ {
+ DPRINT1("Invalid data length for CurrentStage: %d\n", KeyInfo->DataLength);
+ ExFreePool(KeyInfo);
+ return STATUS_UNSUCCESSFUL;
+ }
- if (LowerDriverRegPath)
+ KeyValue = (PULONG)KeyInfo->Data;
+
+ if ((*KeyValue) + 1 < TestStageMax)
+ {
+ DPRINT1("Resuming testing after a crash at stage %d\n", (*KeyValue));
+
+ CurrentStage = (TEST_STAGE)((*KeyValue) + 1);
+ }
+ else
{
- /* 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");
- }
+ DPRINT1("Testing was completed on a previous boot\n");
+ ExFreePool(KeyInfo);
+ return STATUS_UNSUCCESSFUL;
}
+
+ ExFreePool(KeyInfo);
}
else
{
- return STATUS_UNSUCCESSFUL;
+ DPRINT1("Starting a fresh test\n");
+ CurrentStage = (TEST_STAGE)0;
}
+ /* Run the tests */
+ while (CurrentStage < TestStageMax)
+ {
+ RunKernelModeTest(DriverObject,
+ RegistryPath,
+ ParameterKeyHandle,
+ CurrentStage);
+ CurrentStage++;
+ }
+
+ DPRINT1("Testing is complete!\n");
+ ZwClose(ParameterKeyHandle);
+
/* Set all MajorFunctions to NULL to verify that kernel fixes them */
for (i = 1; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i] = NULL;