From: Thomas Faber Date: Thu, 14 Jun 2012 18:43:32 +0000 (+0000) Subject: [KMTESTS] X-Git-Tag: backups/ros-csrss@57560~809 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=4cef47981381d9dfe9b6cf956366fbfcc2318e90 [KMTESTS] - Add minimal ExCallback and PsNotify tests See issue #7120 for more details. svn path=/trunk/; revision=56734 --- diff --git a/rostests/kmtests/CMakeLists.txt b/rostests/kmtests/CMakeLists.txt index d8c63a244fe..d4b366f24a5 100644 --- a/rostests/kmtests/CMakeLists.txt +++ b/rostests/kmtests/CMakeLists.txt @@ -24,6 +24,7 @@ list(APPEND KMTEST_DRV_SOURCE example/Example.c example/KernelType.c + ntos_ex/ExCallback.c ntos_ex/ExDoubleList.c ntos_ex/ExFastMutex.c ntos_ex/ExHardError.c @@ -50,6 +51,7 @@ list(APPEND KMTEST_DRV_SOURCE ntos_ob/ObReference.c ntos_ob/ObType.c ntos_ob/ObTypes.c + ntos_ps/PsNotify.c ${COMMON_SOURCE} kmtest_drv/kmtest_drv.rc) diff --git a/rostests/kmtests/kmtest_drv/testlist.c b/rostests/kmtests/kmtest_drv/testlist.c index d633c39f4a7..4170778396d 100644 --- a/rostests/kmtests/kmtest_drv/testlist.c +++ b/rostests/kmtests/kmtest_drv/testlist.c @@ -8,6 +8,7 @@ #include KMT_TESTFUNC Test_Example; +KMT_TESTFUNC Test_ExCallback; KMT_TESTFUNC Test_ExDoubleList; KMT_TESTFUNC Test_ExFastMutex; KMT_TESTFUNC Test_ExHardError; @@ -37,6 +38,7 @@ KMT_TESTFUNC Test_ObType; KMT_TESTFUNC Test_ObTypeClean; KMT_TESTFUNC Test_ObTypeNoClean; KMT_TESTFUNC Test_ObTypes; +KMT_TESTFUNC Test_PsNotify; KMT_TESTFUNC Test_RtlAvlTree; KMT_TESTFUNC Test_RtlException; KMT_TESTFUNC Test_RtlMemory; @@ -44,6 +46,7 @@ KMT_TESTFUNC Test_RtlSplayTree; const KMT_TEST TestList[] = { + { "ExCallback", Test_ExCallback }, { "ExDoubleList", Test_ExDoubleList }, { "ExFastMutex", Test_ExFastMutex }, { "ExHardError", Test_ExHardError }, @@ -74,6 +77,7 @@ const KMT_TEST TestList[] = { "-ObTypeClean", Test_ObTypeClean }, { "-ObTypeNoClean", Test_ObTypeNoClean }, { "ObTypes", Test_ObTypes }, + { "PsNotify", Test_PsNotify }, { "RtlAvlTreeKM", Test_RtlAvlTree }, { "RtlExceptionKM", Test_RtlException }, { "RtlMemoryKM", Test_RtlMemory }, diff --git a/rostests/kmtests/ntos_ex/ExCallback.c b/rostests/kmtests/ntos_ex/ExCallback.c new file mode 100644 index 00000000000..631b75300e6 --- /dev/null +++ b/rostests/kmtests/ntos_ex/ExCallback.c @@ -0,0 +1,153 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Kernel-Mode Test Suite Executive Callback test + * PROGRAMMER: Thomas Faber + */ + +#include + +static +PEX_CALLBACK_ROUTINE_BLOCK +(NTAPI +*ExAllocateCallBack)( + IN PEX_CALLBACK_FUNCTION Function, + IN PVOID Context +) +//= (PVOID)0x809af1f4 // 2003 sp1 x86 +//= (PVOID)0x80a7f04a // 2003 sp1 x86 checked +; + +static +VOID +(NTAPI +*ExFreeCallBack)( + IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock +) +//= (PVOID)0x80918bb5 // 2003 sp1 x86 +//= (PVOID)0x80a355f0 // 2003 sp1 x86 checked +; + +static INT CallbackArgument1; +static INT CallbackArgument2; + +static +NTSTATUS +NTAPI +ExCallbackFunction( + IN PVOID CallbackContext, + IN PVOID Argument1 OPTIONAL, + IN PVOID Argument2 OPTIONAL) +{ + ok(0, "Callback function unexpectedly called\n"); + return STATUS_SUCCESS; +} + +static +VOID +TestPrivateFunctions(VOID) +{ + UNICODE_STRING ExAllocateCallBackName = RTL_CONSTANT_STRING(L"ExAllocateCallBack"); + UNICODE_STRING ExFreeCallBackName = RTL_CONSTANT_STRING(L"ExFreeCallBack"); + PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock; + INT CallbackContext; + + if (!ExAllocateCallBack) + ExAllocateCallBack = MmGetSystemRoutineAddress(&ExAllocateCallBackName); + if (!ExFreeCallBack) + ExFreeCallBack = MmGetSystemRoutineAddress(&ExFreeCallBackName); + + if (skip(ExAllocateCallBack && ExFreeCallBack, + "ExAllocateCallBack and/or ExFreeCallBack unavailable\n")) + return; + + CallbackBlock = ExAllocateCallBack(ExCallbackFunction, &CallbackContext); + ok(CallbackBlock != NULL, "CallbackBlock = NULL\n"); + + if (skip(CallbackBlock != NULL, "Allocating callback failed\n")) + return; + + ok_eq_pointer(CallbackBlock->Function, ExCallbackFunction); + ok_eq_pointer(CallbackBlock->Context, &CallbackContext); + ok_eq_hex(KmtGetPoolTag(CallbackBlock), 'brbC'); + + ExFreeCallBack(CallbackBlock); +} + +static +VOID +NTAPI +CallbackFunction( + IN PVOID CallbackContext, + IN PVOID Argument1, + IN PVOID Argument2) +{ + INT *InvocationCount = CallbackContext; + + ok_irql(PASSIVE_LEVEL); + + (*InvocationCount)++; + ok_eq_pointer(Argument1, &CallbackArgument1); + ok_eq_pointer(Argument2, &CallbackArgument2); +} + +START_TEST(ExCallback) +{ + NTSTATUS Status; + PCALLBACK_OBJECT CallbackObject; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING CallbackName = RTL_CONSTANT_STRING(L"\\Callback\\KmtestExCallbackTestCallback"); + PVOID CallbackRegistration; + INT InvocationCount = 0; + + TestPrivateFunctions(); + + /* TODO: Parameter tests */ + /* TODO: Test the three predefined callbacks */ + /* TODO: Test opening an existing callback */ + /* TODO: Test AllowMultipleCallbacks */ + /* TODO: Test calling multiple callbacks */ + /* TODO: Test registering the same function twice */ + /* TODO: Test callback object fields */ + /* TODO: Test callback registration fields */ + InitializeObjectAttributes(&ObjectAttributes, + &CallbackName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + CallbackObject = KmtInvalidPointer; + Status = ExCreateCallback(&CallbackObject, + &ObjectAttributes, + TRUE, + TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + ok(CallbackObject != NULL && CallbackObject != KmtInvalidPointer, + "CallbackObject = %p", CallbackObject); + + if (skip(NT_SUCCESS(Status), "Creating callback failed\n")) + return; + + CallbackRegistration = ExRegisterCallback(CallbackObject, + CallbackFunction, + &InvocationCount); + ok(CallbackRegistration != NULL, "CallbackRegistration = NULL\n"); + + if (!skip(CallbackRegistration != NULL, "Registering callback failed\n")) + { + ok_eq_hex(KmtGetPoolTag(CallbackRegistration), 'eRBC'); + ok_eq_int(InvocationCount, 0); + ExNotifyCallback(CallbackObject, + &CallbackArgument1, + &CallbackArgument2); + ok_eq_int(InvocationCount, 1); + ExNotifyCallback(CallbackObject, + &CallbackArgument1, + &CallbackArgument2); + ok_eq_int(InvocationCount, 2); + + ExUnregisterCallback(CallbackRegistration); + } + + ObDereferenceObject(CallbackObject); +} diff --git a/rostests/kmtests/ntos_ps/PsNotify.c b/rostests/kmtests/ntos_ps/PsNotify.c new file mode 100644 index 00000000000..7062d1255de --- /dev/null +++ b/rostests/kmtests/ntos_ps/PsNotify.c @@ -0,0 +1,177 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Kernel-Mode Test Suite Process Notification Routines test + * PROGRAMMER: Thomas Faber + */ + +#include + +//#define NDEBUG +#include + +static +VOID +NTAPI +CreateProcessNotifyRoutine( + IN HANDLE ParentId, + IN HANDLE ProcessId, + IN BOOLEAN Create) +{ + ok_irql(PASSIVE_LEVEL); + if (!Create) + ok_eq_pointer(ProcessId, PsGetCurrentProcessId()); + else + ok(ProcessId != PsGetCurrentProcessId(), + "ProcessId %p equals current\n", ProcessId); + DPRINT("%s(%p, %p, %d)\n", __FUNCTION__, ParentId, ProcessId, Create); +} + +static +VOID +TestCreateProcessNotify(VOID) +{ + NTSTATUS Status; + + Status = PsSetCreateProcessNotifyRoutine(NULL, TRUE); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + Status = PsSetCreateProcessNotifyRoutine(NULL, FALSE); + ok_eq_hex(Status, STATUS_SUCCESS); + + Status = PsSetCreateProcessNotifyRoutine(NULL, TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + + Status = PsSetCreateProcessNotifyRoutine(NULL, TRUE); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + Status = PsSetCreateProcessNotifyRoutine(CreateProcessNotifyRoutine, TRUE); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + Status = PsSetCreateProcessNotifyRoutine(CreateProcessNotifyRoutine, FALSE); + ok_eq_hex(Status, STATUS_SUCCESS); + + /* TODO: test whether the callback is notified on process creation */ + + Status = PsSetCreateProcessNotifyRoutine(CreateProcessNotifyRoutine, TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + + Status = PsSetCreateProcessNotifyRoutine(CreateProcessNotifyRoutine, TRUE); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + /* TODO: register the same routine twice */ + /* TODO: register more than the maximum number of notifications */ +} + +static +VOID +NTAPI +CreateThreadNotifyRoutine( + IN HANDLE ProcessId, + IN HANDLE ThreadId, + IN BOOLEAN Create) +{ + ok_irql(PASSIVE_LEVEL); + if (!Create) + { + ok_eq_pointer(ProcessId, PsGetCurrentProcessId()); + ok_eq_pointer(ThreadId, PsGetCurrentThreadId()); + } + else + { + ok(ThreadId != PsGetCurrentThreadId(), + "ThreadId %p equals current\n", ThreadId); + } + DPRINT("%s(%p, %p, %d)\n", __FUNCTION__, ProcessId, ThreadId, Create); +} + +static +VOID +TestCreateThreadNotify(VOID) +{ + NTSTATUS Status; + + Status = PsRemoveCreateThreadNotifyRoutine(NULL); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + Status = PsSetCreateThreadNotifyRoutine(NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + + Status = PsRemoveCreateThreadNotifyRoutine(NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + + Status = PsRemoveCreateThreadNotifyRoutine(NULL); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + Status = PsRemoveCreateThreadNotifyRoutine(CreateThreadNotifyRoutine); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + Status = PsSetCreateThreadNotifyRoutine(CreateThreadNotifyRoutine); + ok_eq_hex(Status, STATUS_SUCCESS); + + /* TODO: test whether the callback is notified on thread creation */ + + Status = PsRemoveCreateThreadNotifyRoutine(CreateThreadNotifyRoutine); + ok_eq_hex(Status, STATUS_SUCCESS); + + Status = PsRemoveCreateThreadNotifyRoutine(CreateThreadNotifyRoutine); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + /* TODO: register the same routine twice */ + /* TODO: register more than the maximum number of notifications */ +} + +static +VOID +NTAPI +LoadImageNotifyRoutine( + IN PUNICODE_STRING FullImageName OPTIONAL, + IN HANDLE ProcessId, + IN PIMAGE_INFO ImageInfo) +{ + ok_irql(PASSIVE_LEVEL); + DPRINT("%s('%wZ', %p, %p)\n", __FUNCTION__, FullImageName, ProcessId, ImageInfo); +} + +static +VOID +TestLoadImageNotify(VOID) +{ + NTSTATUS Status; + + Status = PsRemoveLoadImageNotifyRoutine(NULL); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + Status = PsSetLoadImageNotifyRoutine(NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + + Status = PsRemoveLoadImageNotifyRoutine(NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + + Status = PsRemoveLoadImageNotifyRoutine(NULL); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + Status = PsRemoveLoadImageNotifyRoutine(LoadImageNotifyRoutine); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + Status = PsSetLoadImageNotifyRoutine(LoadImageNotifyRoutine); + ok_eq_hex(Status, STATUS_SUCCESS); + + /* TODO: test whether the callback is notified on image load */ + + Status = PsRemoveLoadImageNotifyRoutine(LoadImageNotifyRoutine); + ok_eq_hex(Status, STATUS_SUCCESS); + + Status = PsRemoveLoadImageNotifyRoutine(LoadImageNotifyRoutine); + ok_eq_hex(Status, STATUS_PROCEDURE_NOT_FOUND); + + /* TODO: register the same routine twice */ + /* TODO: register more than the maximum number of notifications */ +} + +START_TEST(PsNotify) +{ + TestCreateProcessNotify(); + TestCreateThreadNotify(); + TestLoadImageNotify(); +}