- 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 <Test Name>SuccessCount which is the number of successful tests, <Test Name>FailureCount which is the number of failed tests, <Test Name>TotalCount which is the total number of tests, and <Test Name>SkippedCount which is the number of tests that have been skipped
- Enjoy your reg testing! :)

svn path=/trunk/; revision=47309
This commit is contained in:
Cameron Gutman 2010-05-22 18:34:01 +00:00
parent d7bbeaed19
commit afcd401a32
10 changed files with 330 additions and 676 deletions

View file

@ -1,545 +0,0 @@
/*
* PnP Test
* ReactOS Device Interface functions implementation
*
* Copyright 2003, 2004 Filip Navara <xnavara@volny.cz>
* Copyright 2003, 2004 Matthew Brace <ismarc@austin.rr.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 <ddk/ntddk.h>
#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;
}

View file

@ -26,7 +26,7 @@
#include <ndk/iotypes.h>
#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");
}

View file

@ -25,8 +25,12 @@
#include <ddk/ntddk.h>
#include "kmtest.h"
#define NDEBUG
#include <debug.h>
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;

View file

@ -1,5 +1,5 @@
#ifndef PNPTEST_H
#define PNPTEST_H
#ifndef KMTEST_H
#define KMTEST_H
#include <stdio.h>
#include <stdarg.h>
@ -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 */

View file

@ -5,7 +5,6 @@
<library>hal</library>
<library>pseh</library>
<file>kmtest.c</file>
<file>deviface.c</file>
<file>deviface_test.c</file>
<file>drvobj_test.c</file>
<file>devobj_test.c</file>

View file

@ -27,7 +27,7 @@
#include <ndk/ntndk.h>
#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");
}

View file

@ -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");
}

View file

@ -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");
}

View file

@ -26,7 +26,7 @@
#include <ddk/ntifs.h>
#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");
}

View file

@ -29,15 +29,15 @@
#include <pseh/pseh2.h>
#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");
}