2 * Kernel Mode regression Test
5 * Copyright 2004 Filip Navara <xnavara@volny.cz>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; see the file COPYING.LIB.
19 * If not, write to the Free Software Foundation,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 /* INCLUDES *******************************************************************/
25 #include <ddk/ntddk.h>
36 /* PRIVATE FUNCTIONS ***********************************************************/
46 FinishTest(HANDLE KeyHandle
, LPWSTR TestName
)
49 LONG total
= successes
+ failures
;
50 UNICODE_STRING KeyNameU
;
52 wcscpy(KeyName
, TestName
);
53 wcscat(KeyName
, L
"SuccessCount");
54 RtlInitUnicodeString(&KeyNameU
, KeyName
);
56 ZwSetValueKey(KeyHandle
,
63 wcscpy(KeyName
, TestName
);
64 wcscat(KeyName
, L
"FailureCount");
65 RtlInitUnicodeString(&KeyNameU
, KeyName
);
67 ZwSetValueKey(KeyHandle
,
74 wcscpy(KeyName
, TestName
);
75 wcscat(KeyName
, L
"TotalCount");
76 RtlInitUnicodeString(&KeyNameU
, KeyName
);
78 ZwSetValueKey(KeyHandle
,
85 wcscpy(KeyName
, TestName
);
86 wcscat(KeyName
, L
"SkipCount");
87 RtlInitUnicodeString(&KeyNameU
, KeyName
);
89 ZwSetValueKey(KeyHandle
,
96 DbgPrint("%S: %d test executed (0 marked as todo, %d failures), %d skipped.\n", TestName
, total
, failures
, skipped
);
99 void kmtest_set_location(const char* file
, int line
)
101 glob_data
.current_file
=strrchr(file
,'/');
102 if (glob_data
.current_file
==NULL
)
103 glob_data
.current_file
=strrchr(file
,'\\');
104 if (glob_data
.current_file
==NULL
)
105 glob_data
.current_file
=file
;
107 glob_data
.current_file
++;
108 glob_data
.current_line
=line
;
114 * - condition - condition to check;
115 * - msg test description;
116 * - file - test application source code file name of the check
117 * - line - test application source code file line number of the check
119 * 0 if condition does not have the expected value, 1 otherwise
121 int kmtest_ok(int condition
, const char *msg
, ... )
130 va_start(valist
, msg
);
131 vsprintf(string
, msg
, valist
);
132 DbgPrint( "%s:%d: Test failed: %s\n",
133 glob_data
.current_file
, glob_data
.current_line
, string
);
138 DbgPrint( "%s:%d: Test failed\n",
139 glob_data
.current_file
, glob_data
.current_line
);
141 InterlockedIncrement(&failures
);
147 fprintf( stdout, "%s:%d: Test succeeded\n",
148 glob_data.current_file, glob_data.current_line);*/
149 InterlockedIncrement(&successes
);
154 /* PUBLIC FUNCTIONS ***********************************************************/
156 PWCHAR
CreateLowerDeviceRegistryKey(PUNICODE_STRING RegistryPath
, PWCHAR NewDriver
);
161 VOID
RegisterDI_Test(HANDLE KeyHandle
);
162 VOID
NtoskrnlIoMdlTest(HANDLE KeyHandle
);
163 VOID
NtoskrnlIoIrpTest(HANDLE KeyHandle
);
164 VOID
NtoskrnlObTest(HANDLE KeyHandle
);
165 VOID
ExTimerTest(HANDLE KeyHandle
);
166 VOID
PoolsTest(HANDLE KeyHandle
);
167 VOID
PoolsCorruption(HANDLE KeyHandle
);
168 VOID
KeStallTest(HANDLE KeyHandle
);
169 VOID
DriverObjectTest(PDRIVER_OBJECT
, int);
170 VOID
DeviceCreateDeleteTest(PDRIVER_OBJECT
);
171 VOID
DeviceObjectTest(PDEVICE_OBJECT
);
172 BOOLEAN
ZwLoadTest(PDRIVER_OBJECT
, PUNICODE_STRING
, PWCHAR
);
173 BOOLEAN
ZwUnloadTest(PDRIVER_OBJECT
, PUNICODE_STRING
, PWCHAR
);
174 BOOLEAN
DetachDeviceTest(PDEVICE_OBJECT
);
175 BOOLEAN
AttachDeviceTest(PDEVICE_OBJECT
, PWCHAR
);
176 VOID
LowerDeviceKernelAPITest(PDEVICE_OBJECT
, BOOLEAN
);
179 TestStageExTimer
= 0,
184 TestStageMmPoolCorruption
,
196 KmtestDispatch(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
199 NTSTATUS Status
= STATUS_SUCCESS
;
201 if (AttachDeviceObject
)
203 IoSkipCurrentIrpStackLocation(Irp
);
204 Status
= IoCallDriver(AttachDeviceObject
, Irp
);
208 Irp
->IoStatus
.Status
= Status
;
209 Irp
->IoStatus
.Information
= 0;
210 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
219 KmtestCreateClose(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
221 NTSTATUS Status
= STATUS_SUCCESS
;
223 if (AttachDeviceObject
)
225 IoSkipCurrentIrpStackLocation(Irp
);
226 Status
= IoCallDriver(AttachDeviceObject
, Irp
);
230 /* Do DriverObject Test with Driver Initialized */
231 DriverObjectTest(DeviceObject
->DriverObject
, 1);
233 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
234 Irp
->IoStatus
.Information
=0;
236 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
237 return STATUS_SUCCESS
;
245 KmtestUnload(IN PDRIVER_OBJECT DriverObject
)
247 UNICODE_STRING DosDeviceString
;
249 if(AttachDeviceObject
)
251 IoDetachDevice(AttachDeviceObject
);
254 /* Do DriverObject Test for Unload */
255 DriverObjectTest(DriverObject
, 2);
257 if (MainDeviceObject
)
259 RtlInitUnicodeString(&DosDeviceString
, L
"\\DosDevices\\Kmtest");
260 IoDeleteSymbolicLink(&DosDeviceString
);
262 IoDeleteDevice(MainDeviceObject
);
267 PKEY_VALUE_PARTIAL_INFORMATION
269 ReadRegistryValue(HANDLE KeyHandle
, PWCHAR ValueName
)
272 PKEY_VALUE_PARTIAL_INFORMATION InformationBuffer
= NULL
;
273 ULONG AllocatedLength
= 0, RequiredLength
= 0;
274 UNICODE_STRING ValueNameU
;
276 RtlInitUnicodeString(&ValueNameU
, ValueName
);
278 Status
= ZwQueryValueKey(KeyHandle
,
280 KeyValuePartialInformation
,
284 if (Status
== STATUS_BUFFER_TOO_SMALL
|| Status
== STATUS_BUFFER_OVERFLOW
)
286 InformationBuffer
= ExAllocatePool(PagedPool
, RequiredLength
);
287 AllocatedLength
= RequiredLength
;
288 if (!InformationBuffer
) return NULL
;
290 Status
= ZwQueryValueKey(KeyHandle
,
292 KeyValuePartialInformation
,
298 if (!NT_SUCCESS(Status
))
300 DPRINT1("Failed to read %S (0x%x)\n", ValueName
, Status
);
301 if (InformationBuffer
!= NULL
)
302 ExFreePool(InformationBuffer
);
306 return InformationBuffer
;
311 RunKernelModeTest(PDRIVER_OBJECT DriverObject
,
312 PUNICODE_STRING RegistryPath
,
316 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"CurrentStage");
317 PWCHAR LowerDriverRegPath
;
319 DPRINT1("Running stage %d test...\n", Stage
);
321 ZwSetValueKey(KeyHandle
,
330 case TestStageExTimer
:
331 ExTimerTest(KeyHandle
);
335 NtoskrnlIoMdlTest(KeyHandle
);
339 RegisterDI_Test(KeyHandle
);
343 NtoskrnlIoIrpTest(KeyHandle
);
346 case TestStageMmPoolTest
:
347 PoolsTest(KeyHandle
);
350 case TestStageMmPoolCorruption
:
351 PoolsCorruption(KeyHandle
);
355 NtoskrnlObTest(KeyHandle
);
358 case TestStageKeStall
:
359 KeStallTest(KeyHandle
);
363 /* Start the tests for the driver routines */
366 /* Do DriverObject Test for Driver Entry */
367 DriverObjectTest(DriverObject
, 0);
369 /* Create and delete device, on return MainDeviceObject has been created */
370 DeviceCreateDeleteTest(DriverObject
);
372 /* Make sure a device object was created */
373 if (MainDeviceObject
)
375 LowerDriverRegPath
= CreateLowerDeviceRegistryKey(RegistryPath
, L
"kmtestassist");
377 if (LowerDriverRegPath
)
379 /* Load driver test and load the lower driver */
380 if (ZwLoadTest(DriverObject
, RegistryPath
, LowerDriverRegPath
))
382 AttachDeviceTest(MainDeviceObject
, L
"kmtestassists");
383 if (AttachDeviceObject
)
385 LowerDeviceKernelAPITest(MainDeviceObject
, FALSE
);
388 /* Unload lower driver without detaching from its device */
389 ZwUnloadTest(DriverObject
, RegistryPath
, LowerDriverRegPath
);
390 LowerDeviceKernelAPITest(MainDeviceObject
, TRUE
);
394 DbgPrint("Failed to load kmtestassist driver\n");
399 FinishTest(KeyHandle
, L
"DriverTest");
413 DriverEntry(PDRIVER_OBJECT DriverObject
,
414 PUNICODE_STRING RegistryPath
)
418 OBJECT_ATTRIBUTES ObjectAttributes
;
419 UNICODE_STRING ParameterKeyName
= RTL_CONSTANT_STRING(L
"Parameters");
420 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
422 TEST_STAGE CurrentStage
;
423 HANDLE DriverKeyHandle
, ParameterKeyHandle
;
425 DbgPrint("\n===============================================\n");
426 DbgPrint("Kernel Mode Regression Driver Test starting...\n");
427 DbgPrint("===============================================\n");
429 InitializeObjectAttributes(&ObjectAttributes
,
431 OBJ_CASE_INSENSITIVE
,
435 Status
= ZwOpenKey(&DriverKeyHandle
,
436 KEY_CREATE_SUB_KEY
| KEY_ENUMERATE_SUB_KEYS
,
438 if (!NT_SUCCESS(Status
))
440 DPRINT1("Failed to open %wZ\n", RegistryPath
);
444 InitializeObjectAttributes(&ObjectAttributes
,
446 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
449 Status
= ZwCreateKey(&ParameterKeyHandle
,
450 KEY_SET_VALUE
| KEY_QUERY_VALUE
,
454 REG_OPTION_NON_VOLATILE
,
456 ZwClose(DriverKeyHandle
);
457 if (!NT_SUCCESS(Status
))
459 DPRINT1("Failed to create %wZ\\%wZ\n", RegistryPath
, &ParameterKeyName
);
463 KeyInfo
= ReadRegistryValue(ParameterKeyHandle
, L
"CurrentStage");
466 if (KeyInfo
->DataLength
!= sizeof(ULONG
))
468 DPRINT1("Invalid data length for CurrentStage: %d\n", KeyInfo
->DataLength
);
470 return STATUS_UNSUCCESSFUL
;
473 KeyValue
= (PULONG
)KeyInfo
->Data
;
475 if ((*KeyValue
) + 1 < TestStageMax
)
477 DPRINT1("Resuming testing after a crash at stage %d\n", (*KeyValue
));
479 CurrentStage
= (TEST_STAGE
)((*KeyValue
) + 1);
483 DPRINT1("Testing was completed on a previous boot\n");
485 return STATUS_UNSUCCESSFUL
;
492 DPRINT1("Starting a fresh test\n");
493 CurrentStage
= (TEST_STAGE
)0;
497 while (CurrentStage
< TestStageMax
)
499 RunKernelModeTest(DriverObject
,
506 DPRINT1("Testing is complete!\n");
507 ZwClose(ParameterKeyHandle
);
509 /* Set all MajorFunctions to NULL to verify that kernel fixes them */
510 for (i
= 1; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
511 DriverObject
->MajorFunction
[i
] = NULL
;
513 /* Set necessary routines */
514 DriverObject
->DriverUnload
= KmtestUnload
;
515 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = KmtestDispatch
;
516 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = KmtestCreateClose
;
517 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = KmtestCreateClose
;
519 return STATUS_SUCCESS
;