From afcd401a323cce883f45d0d97b0c0e7f13583857 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 22 May 2010 18:34:01 +0000 Subject: [PATCH] [KMTEST] - Add support for recovering from crashed tests - Add check to prevent us from running the test every boot - Delete some useless code - Record test result information in the registry - Under the Kmtest\Parameters key, you will find CurrentStage which is the stage that testing is on (almost always 8 if it boots). You will also find SuccessCount which is the number of successful tests, FailureCount which is the number of failed tests, TotalCount which is the total number of tests, and SkippedCount which is the number of tests that have been skipped - Enjoy your reg testing! :) svn path=/trunk/; revision=47309 --- rostests/drivers/kmtest/deviface.c | 545 ------------------------ rostests/drivers/kmtest/deviface_test.c | 35 +- rostests/drivers/kmtest/kmtest.c | 343 ++++++++++++--- rostests/drivers/kmtest/kmtest.h | 8 +- rostests/drivers/kmtest/kmtest.rbuild | 1 - rostests/drivers/kmtest/ntos_ex.c | 15 +- rostests/drivers/kmtest/ntos_io.c | 17 +- rostests/drivers/kmtest/ntos_ke.c | 15 +- rostests/drivers/kmtest/ntos_ob.c | 6 +- rostests/drivers/kmtest/ntos_pools.c | 21 +- 10 files changed, 330 insertions(+), 676 deletions(-) delete mode 100644 rostests/drivers/kmtest/deviface.c diff --git a/rostests/drivers/kmtest/deviface.c b/rostests/drivers/kmtest/deviface.c deleted file mode 100644 index a3011f3d141..00000000000 --- a/rostests/drivers/kmtest/deviface.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * PnP Test - * ReactOS Device Interface functions implementation - * - * Copyright 2003, 2004 Filip Navara - * Copyright 2003, 2004 Matthew Brace - * - * 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 -#include "kmtest.h" - -//#define NDEBUG -#include "debug.h" - -/* PUBLIC FUNCTIONS ***********************************************************/ - -/* - * IoGetDeviceInterfaces - * - * Returns a list of device interfaces of a particular device interface class. - * - * Parameters - * InterfaceClassGuid - * Points to a class GUID specifying the device interface class. - * - * PhysicalDeviceObject - * Points to an optional PDO that narrows the search to only the - * device interfaces of the device represented by the PDO. - * - * Flags - * Specifies flags that modify the search for device interfaces. The - * DEVICE_INTERFACE_INCLUDE_NONACTIVE flag specifies that the list of - * returned symbolic links should contain also disabled device - * interfaces in addition to the enabled ones. - * - * SymbolicLinkList - * Points to a character pointer that is filled in on successful return - * with a list of unicode strings identifying the device interfaces - * that match the search criteria. The newly allocated buffer contains - * a list of symbolic link names. Each unicode string in the list is - * null-terminated; the end of the whole list is marked by an additional - * NULL. The caller is responsible for freeing the buffer (ExFreePool) - * when it is no longer needed. - * If no device interfaces match the search criteria, this routine - * returns STATUS_SUCCESS and the string contains a single NULL - * character. - * - * Status - * @unimplemented - * - * The parameters PhysicalDeviceObject and Flags aren't correctly - * processed. Rest of the cases was tested under Win XP and the - * function worked correctly. - */ - -NTSTATUS NTAPI -ReactOS_IoGetDeviceInterfaces( - IN CONST GUID *InterfaceClassGuid, - IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, - IN ULONG Flags, - OUT PWSTR *SymbolicLinkList) -{ - PWCHAR BaseKeyString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\"; - PWCHAR BaseInterfaceString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"; - UNICODE_STRING GuidString; - UNICODE_STRING BaseKeyName; - UNICODE_STRING AliasKeyName; - UNICODE_STRING SymbolicLink; - UNICODE_STRING Control; - UNICODE_STRING SubKeyName; - UNICODE_STRING SymbolicLinkKeyName; - UNICODE_STRING ControlKeyName; - UNICODE_STRING TempString; - HANDLE InterfaceKey; - HANDLE SubKey; - HANDLE SymbolicLinkKey; - PKEY_FULL_INFORMATION fip; - PKEY_FULL_INFORMATION bfip=NULL; - PKEY_BASIC_INFORMATION bip; - PKEY_VALUE_PARTIAL_INFORMATION vpip=NULL; - PWCHAR SymLinkList = NULL; - ULONG SymLinkListSize = 0; - NTSTATUS Status; - ULONG Size = 0; - ULONG i = 0; - ULONG j = 0; - OBJECT_ATTRIBUTES ObjectAttributes; - - Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlStringFromGUID() Failed.\n"); - return STATUS_INVALID_HANDLE; - } - - RtlInitUnicodeString(&AliasKeyName, BaseInterfaceString); - RtlInitUnicodeString(&SymbolicLink, L"SymbolicLink"); - RtlInitUnicodeString(&Control, L"\\Control"); - BaseKeyName.Length = wcslen(BaseKeyString) * sizeof(WCHAR); - BaseKeyName.MaximumLength = BaseKeyName.Length + (38 * sizeof(WCHAR)); - BaseKeyName.Buffer = ExAllocatePool( - NonPagedPool, - BaseKeyName.MaximumLength); - ASSERT(BaseKeyName.Buffer != NULL); - wcscpy(BaseKeyName.Buffer, BaseKeyString); - RtlAppendUnicodeStringToString(&BaseKeyName, &GuidString); - - if (PhysicalDeviceObject) - { - WCHAR GuidBuffer[40]; - UNICODE_STRING PdoGuidString; - - RtlFreeUnicodeString(&BaseKeyName); - - IoGetDeviceProperty( - PhysicalDeviceObject, - DevicePropertyClassGuid, - sizeof(GuidBuffer), - GuidBuffer, - &Size); - - RtlInitUnicodeString(&PdoGuidString, GuidBuffer); - if (RtlCompareUnicodeString(&GuidString, &PdoGuidString, TRUE)) - { - DPRINT("Inconsistent Guid's asked for in IoGetDeviceInterfaces()\n"); - return STATUS_INVALID_HANDLE; - } - - DPRINT("IoGetDeviceInterfaces() called with PDO, not implemented.\n"); - return STATUS_NOT_IMPLEMENTED; - } - else - { - InitializeObjectAttributes( - &ObjectAttributes, - &BaseKeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwOpenKey( - &InterfaceKey, - KEY_READ, - &ObjectAttributes); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status); - RtlFreeUnicodeString(&BaseKeyName); - return Status; - } - - Status = ZwQueryKey( - InterfaceKey, - KeyFullInformation, - NULL, - 0, - &Size); - - if (Status != STATUS_BUFFER_TOO_SMALL) - { - DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - return Status; - } - - fip = (PKEY_FULL_INFORMATION)ExAllocatePool(NonPagedPool, Size); - ASSERT(fip != NULL); - - Status = ZwQueryKey( - InterfaceKey, - KeyFullInformation, - fip, - Size, - &Size); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status); - ExFreePool(fip); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - return Status; - } - - for (; i < fip->SubKeys; i++) - { - Status = ZwEnumerateKey( - InterfaceKey, - i, - KeyBasicInformation, - NULL, - 0, - &Size); - - if (Status != STATUS_BUFFER_TOO_SMALL) - { - DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status); - ExFreePool(fip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - return Status; - } - - bip = (PKEY_BASIC_INFORMATION)ExAllocatePool(NonPagedPool, Size); - ASSERT(bip != NULL); - - Status = ZwEnumerateKey( - InterfaceKey, - i, - KeyBasicInformation, - bip, - Size, - &Size); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status); - ExFreePool(fip); - ExFreePool(bip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - return Status; - } - - SubKeyName.Length = 0; - SubKeyName.MaximumLength = BaseKeyName.Length + bip->NameLength + sizeof(WCHAR); - SubKeyName.Buffer = ExAllocatePool(NonPagedPool, SubKeyName.MaximumLength); - ASSERT(SubKeyName.Buffer != NULL); - TempString.Length = TempString.MaximumLength = bip->NameLength; - TempString.Buffer = bip->Name; - RtlCopyUnicodeString(&SubKeyName, &BaseKeyName); - RtlAppendUnicodeToString(&SubKeyName, L"\\"); - RtlAppendUnicodeStringToString(&SubKeyName, &TempString); - - ExFreePool(bip); - - InitializeObjectAttributes( - &ObjectAttributes, - &SubKeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwOpenKey( - &SubKey, - KEY_READ, - &ObjectAttributes); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status); - ExFreePool(fip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - return Status; - } - - Status = ZwQueryKey( - SubKey, - KeyFullInformation, - NULL, - 0, - &Size); - - if (Status != STATUS_BUFFER_TOO_SMALL) - { - DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status); - ExFreePool(fip); - RtlFreeUnicodeString(&BaseKeyName); - RtlFreeUnicodeString(&SubKeyName); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - bfip = (PKEY_FULL_INFORMATION)ExAllocatePool(NonPagedPool, Size); - ASSERT(bfip != NULL); - - Status = ZwQueryKey( - SubKey, - KeyFullInformation, - bfip, - Size, - &Size); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status); - ExFreePool(fip); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - for(j = 0; j < bfip->SubKeys; j++) - { - Status = ZwEnumerateKey( - SubKey, - j, - KeyBasicInformation, - NULL, - 0, - &Size); - - if (Status == STATUS_NO_MORE_ENTRIES) - continue; - - if (Status != STATUS_BUFFER_TOO_SMALL) - { - DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status); - ExFreePool(bfip); - ExFreePool(fip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - bip = (PKEY_BASIC_INFORMATION)ExAllocatePool(NonPagedPool, Size); - ASSERT(bip != NULL); - - Status = ZwEnumerateKey( - SubKey, - j, - KeyBasicInformation, - bip, - Size, - &Size); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status); - ExFreePool(fip); - ExFreePool(bfip); - ExFreePool(bip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - if (!wcsncmp(bip->Name, L"Control", bip->NameLength)) - { - continue; - } - - SymbolicLinkKeyName.Length = 0; - SymbolicLinkKeyName.MaximumLength = SubKeyName.Length + bip->NameLength + sizeof(WCHAR); - SymbolicLinkKeyName.Buffer = ExAllocatePool(NonPagedPool, SymbolicLinkKeyName.MaximumLength); - ASSERT(SymbolicLinkKeyName.Buffer != NULL); - TempString.Length = TempString.MaximumLength = bip->NameLength; - TempString.Buffer = bip->Name; - RtlCopyUnicodeString(&SymbolicLinkKeyName, &SubKeyName); - RtlAppendUnicodeToString(&SymbolicLinkKeyName, L"\\"); - RtlAppendUnicodeStringToString(&SymbolicLinkKeyName, &TempString); - - ControlKeyName.Length = 0; - ControlKeyName.MaximumLength = SymbolicLinkKeyName.Length + Control.Length + sizeof(WCHAR); - ControlKeyName.Buffer = ExAllocatePool(NonPagedPool, ControlKeyName.MaximumLength); - ASSERT(ControlKeyName.Buffer != NULL); - RtlCopyUnicodeString(&ControlKeyName, &SymbolicLinkKeyName); - RtlAppendUnicodeStringToString(&ControlKeyName, &Control); - - ExFreePool(bip); - - InitializeObjectAttributes( - &ObjectAttributes, - &SymbolicLinkKeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwOpenKey( - &SymbolicLinkKey, - KEY_READ, - &ObjectAttributes); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status); - ExFreePool(fip); - ExFreePool(bfip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SymbolicLinkKeyName); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - Status = ZwQueryValueKey( - SymbolicLinkKey, - &SymbolicLink, - KeyValuePartialInformation, - NULL, - 0, - &Size); - - if (Status == STATUS_OBJECT_NAME_NOT_FOUND) - continue; - - if (Status != STATUS_BUFFER_TOO_SMALL) - { - DPRINT("ZwQueryValueKey() Failed.(0x%X)\n", Status); - ExFreePool(fip); - ExFreePool(bfip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SymbolicLinkKeyName); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SymbolicLinkKey); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - vpip = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(NonPagedPool, Size); - ASSERT(vpip != NULL); - - Status = ZwQueryValueKey( - SymbolicLinkKey, - &SymbolicLink, - KeyValuePartialInformation, - vpip, - Size, - &Size); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwQueryValueKey() Failed.(0x%X)\n", Status); - ExFreePool(fip); - ExFreePool(bfip); - ExFreePool(vpip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SymbolicLinkKeyName); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SymbolicLinkKey); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, ControlKeyName.Buffer); - - if (NT_SUCCESS(Status)) - { - /* Put the name in the string here */ - if (SymLinkList == NULL) - { - SymLinkListSize = vpip->DataLength; - SymLinkList = ExAllocatePool(NonPagedPool, SymLinkListSize + sizeof(WCHAR)); - ASSERT(SymLinkList != NULL); - RtlCopyMemory(SymLinkList, vpip->Data, vpip->DataLength); - SymLinkList[vpip->DataLength / sizeof(WCHAR)] = 0; - SymLinkList[1] = '?'; - } - else - { - PWCHAR OldSymLinkList; - ULONG OldSymLinkListSize; - PWCHAR SymLinkListPtr; - - OldSymLinkList = SymLinkList; - OldSymLinkListSize = SymLinkListSize; - SymLinkListSize += vpip->DataLength; - SymLinkList = ExAllocatePool(NonPagedPool, SymLinkListSize + sizeof(WCHAR)); - ASSERT(SymLinkList != NULL); - RtlCopyMemory(SymLinkList, OldSymLinkList, OldSymLinkListSize); - ExFreePool(OldSymLinkList); - SymLinkListPtr = SymLinkList + (OldSymLinkListSize / sizeof(WCHAR)); - RtlCopyMemory(SymLinkListPtr, vpip->Data, vpip->DataLength); - SymLinkListPtr[vpip->DataLength / sizeof(WCHAR)] = 0; - SymLinkListPtr[1] = '?'; - } - } - - RtlFreeUnicodeString(&SymbolicLinkKeyName); - RtlFreeUnicodeString(&ControlKeyName); - ZwClose(SymbolicLinkKey); - } - - ExFreePool(vpip); - RtlFreeUnicodeString(&SubKeyName); - ZwClose(SubKey); - } - - if (SymLinkList != NULL) - { - SymLinkList[SymLinkListSize / sizeof(WCHAR)] = 0; - } - else - { - SymLinkList = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR)); - SymLinkList[0] = 0; - } - - *SymbolicLinkList = SymLinkList; - - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - ExFreePool(bfip); - ExFreePool(fip); - } - - return STATUS_SUCCESS; -} diff --git a/rostests/drivers/kmtest/deviface_test.c b/rostests/drivers/kmtest/deviface_test.c index 0fbd91ea23e..2e27349697c 100644 --- a/rostests/drivers/kmtest/deviface_test.c +++ b/rostests/drivers/kmtest/deviface_test.c @@ -26,7 +26,7 @@ #include #include "kmtest.h" -//#define NDEBUG +#define NDEBUG #include "debug.h" /* PRIVATE FUNCTIONS **********************************************************/ @@ -52,26 +52,26 @@ VOID DeviceInterfaceTest_Func() PWSTR SymbolicLinkListPtr; GUID Guid = {0x378de44c, 0x56ef, 0x11d1, {0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd}}; - Status = IoGetDeviceInterfaces_Func( + Status = IoGetDeviceInterfaces( &Guid, NULL, 0, &SymbolicLinkList); + ok(NT_SUCCESS(Status), + "IoGetDeviceInterfaces failed with status 0x%X\n", + (unsigned int)Status); if (!NT_SUCCESS(Status)) { - DPRINT( - "[PnP Test] IoGetDeviceInterfaces failed with status 0x%X\n", - Status); return; } - DPRINT("[PnP Test] IoGetDeviceInterfaces results:\n"); + DPRINT("IoGetDeviceInterfaces results:\n"); for (SymbolicLinkListPtr = SymbolicLinkList; SymbolicLinkListPtr[0] != 0 && SymbolicLinkListPtr[1] != 0; SymbolicLinkListPtr += wcslen(SymbolicLinkListPtr) + 1) { - DPRINT("[PnP Test] %S\n", SymbolicLinkListPtr); + DPRINT1("Symbolic Link: %S\n", SymbolicLinkListPtr); } #if 0 @@ -102,7 +102,7 @@ VOID DeviceInterfaceTest_Func() ExFreePool(SymbolicLinkList); } -VOID RegisterDI_Test() +VOID RegisterDI_Test(HANDLE KeyHandle) { GUID Guid = {0x378de44c, 0x56ef, 0x11d1, {0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd}}; DEVICE_OBJECT DeviceObject; @@ -111,6 +111,8 @@ VOID RegisterDI_Test() UNICODE_STRING SymbolicLinkName; NTSTATUS Status; + StartTest(); + RtlInitUnicodeString(&SymbolicLinkName, L""); // Prepare our surrogate of a Device Object @@ -132,23 +134,8 @@ VOID RegisterDI_Test() ok(Status == STATUS_INVALID_DEVICE_REQUEST, "IoRegisterDeviceInterface returned 0x%08lX\n", Status); -} -VOID NtoskrnlIoDeviceInterface() -{ - StartTest(); - - // Test IoRegisterDeviceInterface() failures now - RegisterDI_Test(); - -/* - DPRINT("Calling DeviceInterfaceTest_Func with native functions\n"); - IoGetDeviceInterfaces_Func = IoGetDeviceInterfaces; DeviceInterfaceTest_Func(); - DPRINT("Calling DeviceInterfaceTest_Func with ReactOS functions\n"); - IoGetDeviceInterfaces_Func = ReactOS_IoGetDeviceInterfaces; - DeviceInterfaceTest_Func(); -*/ - FinishTest("NTOSKRNL Io Device Interface Test"); + FinishTest(KeyHandle, L"IoDeviceInterfaceTest"); } diff --git a/rostests/drivers/kmtest/kmtest.c b/rostests/drivers/kmtest/kmtest.c index 964486a93f6..3164688336c 100644 --- a/rostests/drivers/kmtest/kmtest.c +++ b/rostests/drivers/kmtest/kmtest.c @@ -25,8 +25,12 @@ #include #include "kmtest.h" +#define NDEBUG +#include + LONG successes; LONG failures; +LONG skipped; tls_data glob_data; /* PRIVATE FUNCTIONS ***********************************************************/ @@ -35,12 +39,61 @@ StartTest() { 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) @@ -105,11 +158,14 @@ PWCHAR CreateLowerDeviceRegistryKey(PUNICODE_STRING RegistryPath, PWCHAR NewDriv /* * Test Declarations */ -VOID NtoskrnlIoTests(); -VOID NtoskrnlKeTests(); -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); @@ -119,6 +175,19 @@ BOOLEAN DetachDeviceTest(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 */ @@ -192,7 +261,148 @@ KmtestUnload(IN PDRIVER_OBJECT DriverObject) 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; + } } /* @@ -204,61 +414,98 @@ DriverEntry(PDRIVER_OBJECT DriverObject, 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; + InitializeObjectAttributes(&ObjectAttributes, + RegistryPath, + OBJ_CASE_INSENSITIVE, + 0, + NULL); - NtoskrnlExecutiveTests(); - NtoskrnlKeTests(); - 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) + Status = ZwOpenKey(&DriverKeyHandle, + KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) { - LowerDriverRegPath = CreateLowerDeviceRegistryKey(RegistryPath, L"kmtestassist"); + DPRINT1("Failed to open %wZ\n", RegistryPath); + return Status; + } - if (LowerDriverRegPath) + 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; + } + + KeyInfo = ReadRegistryValue(ParameterKeyHandle, L"CurrentStage"); + if (KeyInfo) + { + if (KeyInfo->DataLength != sizeof(ULONG)) { - /* 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("Invalid data length for CurrentStage: %d\n", KeyInfo->DataLength); + ExFreePool(KeyInfo); + return STATUS_UNSUCCESSFUL; } + + 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 + { + 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; diff --git a/rostests/drivers/kmtest/kmtest.h b/rostests/drivers/kmtest/kmtest.h index a0f20d3405d..c244d303841 100644 --- a/rostests/drivers/kmtest/kmtest.h +++ b/rostests/drivers/kmtest/kmtest.h @@ -1,5 +1,5 @@ -#ifndef PNPTEST_H -#define PNPTEST_H +#ifndef KMTEST_H +#define KMTEST_H #include #include @@ -30,7 +30,7 @@ typedef struct extern tls_data glob_data; VOID StartTest(); -VOID FinishTest(LPSTR TestName); +VOID FinishTest(HANDLE KeyHandle, LPWSTR TestName); void kmtest_set_location(const char* file, int line); #ifdef __GNUC__ @@ -51,4 +51,4 @@ PDEVICE_OBJECT AttachDeviceObject; PDEVICE_OBJECT MainDeviceObject; PDRIVER_OBJECT ThisDriverObject; -#endif /* PNPTEST_H */ +#endif /* KMTEST_H */ diff --git a/rostests/drivers/kmtest/kmtest.rbuild b/rostests/drivers/kmtest/kmtest.rbuild index 9219db9f9c1..b9920797178 100644 --- a/rostests/drivers/kmtest/kmtest.rbuild +++ b/rostests/drivers/kmtest/kmtest.rbuild @@ -5,7 +5,6 @@ hal pseh kmtest.c - deviface.c deviface_test.c drvobj_test.c devobj_test.c diff --git a/rostests/drivers/kmtest/ntos_ex.c b/rostests/drivers/kmtest/ntos_ex.c index 84d6859ab51..8edf7fec1a8 100644 --- a/rostests/drivers/kmtest/ntos_ex.c +++ b/rostests/drivers/kmtest/ntos_ex.c @@ -27,7 +27,7 @@ #include #include "kmtest.h" -//#define NDEBUG +#define NDEBUG #include "debug.h" /* PRIVATE FUNCTIONS ***********************************************************/ @@ -44,9 +44,10 @@ TestTimerApcRoutine(IN PVOID TimerContext, (*ApcCount)++; } +/* PUBLIC FUNCTIONS *************************************************************/ VOID -ExTimerTest() +ExTimerTest(HANDLE KeyHandle) { UNICODE_STRING TimerName; OBJECT_ATTRIBUTES ObjectAttributes; @@ -167,13 +168,5 @@ ExTimerTest() Status = ZwClose(TimerHandle); ok(Status == STATUS_SUCCESS, "ZwClose failed with Status=0x%08lX", Status); - FinishTest("NTOSKRNL Executive Timer"); -} - -/* PUBLIC FUNCTIONS ***********************************************************/ - -VOID -NtoskrnlExecutiveTests() -{ - ExTimerTest(); + FinishTest(KeyHandle, L"ExTimerTest"); } diff --git a/rostests/drivers/kmtest/ntos_io.c b/rostests/drivers/kmtest/ntos_io.c index 986098edc7d..d49955b95e6 100644 --- a/rostests/drivers/kmtest/ntos_io.c +++ b/rostests/drivers/kmtest/ntos_io.c @@ -29,12 +29,10 @@ #define NDEBUG #include "debug.h" -VOID NtoskrnlIoDeviceInterface(); - /* PUBLIC FUNCTIONS ***********************************************************/ -VOID NtoskrnlIoMdlTest() +VOID NtoskrnlIoMdlTest(HANDLE KeyHandle) { PMDL Mdl; PIRP Irp; @@ -81,10 +79,10 @@ VOID NtoskrnlIoMdlTest() IoFreeIrp(Irp); ExFreePool(VirtualAddress); - FinishTest("NTOSKRNL Io Mdl"); + FinishTest(KeyHandle, L"IoMdlTest"); } -VOID NtoskrnlIoIrpTest() +VOID NtoskrnlIoIrpTest(HANDLE KeyHandle) { USHORT size; IRP *iorp; @@ -166,12 +164,5 @@ VOID NtoskrnlIoIrpTest() IoFreeIrp(iorp); } - FinishTest("NTOSKRNL Io Irp"); -} - -VOID NtoskrnlIoTests() -{ - NtoskrnlIoMdlTest(); - NtoskrnlIoDeviceInterface(); - NtoskrnlIoIrpTest(); + FinishTest(KeyHandle, L"IoIrpTest"); } diff --git a/rostests/drivers/kmtest/ntos_ke.c b/rostests/drivers/kmtest/ntos_ke.c index 1c6032238be..d59eeb3a00f 100644 --- a/rostests/drivers/kmtest/ntos_ke.c +++ b/rostests/drivers/kmtest/ntos_ke.c @@ -30,11 +30,10 @@ #define NDEBUG #include "debug.h" -/* PRIVATE FUNCTIONS ***********************************************************/ +/* PUBLIC FUNCTIONS ***********************************************************/ VOID -NTAPI -KeStallTest() +KeStallTest(HANDLE KeyHandle) { ULONG i; LARGE_INTEGER TimeStart, TimeFinish; @@ -74,13 +73,5 @@ KeStallTest() KeQuerySystemTime(&TimeFinish); DPRINT1("Time elapsed: %d secs\n", (TimeFinish.QuadPart - TimeStart.QuadPart) / 10000000); // 30 - FinishTest("NTOSKRNL KeStallmanExecution test"); -} - -/* PUBLIC FUNCTIONS ***********************************************************/ - -VOID -NtoskrnlKeTests() -{ - KeStallTest(); + FinishTest(KeyHandle, L"KeStallmanExecutionTest"); } diff --git a/rostests/drivers/kmtest/ntos_ob.c b/rostests/drivers/kmtest/ntos_ob.c index a7c62fa5641..c8b4d35156a 100644 --- a/rostests/drivers/kmtest/ntos_ob.c +++ b/rostests/drivers/kmtest/ntos_ob.c @@ -26,7 +26,7 @@ #include #include "kmtest.h" -//#define NDEBUG +#define NDEBUG #include "debug.h" #include "ntndk.h" @@ -487,7 +487,7 @@ ObtReferenceTests() /* PUBLIC FUNCTIONS ***********************************************************/ VOID -NtoskrnlObTest() +NtoskrnlObTest(HANDLE KeyHandle) { StartTest(); @@ -515,5 +515,5 @@ NtoskrnlObTest() ObtClose(); DPRINT("Cleanup done\n"); - FinishTest("NTOSKRNL Ob Manager"); + FinishTest(KeyHandle, L"ObMgrTest"); } diff --git a/rostests/drivers/kmtest/ntos_pools.c b/rostests/drivers/kmtest/ntos_pools.c index 816d7c325f3..37c998774b1 100644 --- a/rostests/drivers/kmtest/ntos_pools.c +++ b/rostests/drivers/kmtest/ntos_pools.c @@ -29,15 +29,15 @@ #include #include "kmtest.h" -//#define NDEBUG +#define NDEBUG #include "debug.h" #define TAG_POOLTEST 'tstP' -/* PRIVATE FUNCTIONS ***********************************************************/ +/* PUBLIC FUNCTIONS ***********************************************************/ VOID -PoolsTest() +PoolsTest(HANDLE KeyHandle) { PVOID Ptr; ULONG AllocSize, i, AllocNumber; @@ -124,11 +124,11 @@ PoolsTest() ExFreePoolWithTag(Allocs, TAG_POOLTEST); - FinishTest("NTOSKRNL Pools Tests"); + FinishTest(KeyHandle, L"MmPoolAllocTest"); } VOID -PoolsCorruption() +PoolsCorruption(HANDLE KeyHandle) { PULONG Ptr, TestPtr; ULONG AllocSize; @@ -174,14 +174,5 @@ PoolsCorruption() // free the pool ExFreePoolWithTag(Ptr, TAG_POOLTEST); - FinishTest("NTOSKRNL Pool Corruption"); -} - -/* PUBLIC FUNCTIONS ***********************************************************/ - -VOID -NtoskrnlPoolsTest() -{ - PoolsTest(); - //PoolsCorruption(); + FinishTest(KeyHandle, L"MmPoolCorruptionTest"); }