[KMTESTS:OB]
[reactos.git] / rostests / kmtests / ntos_ex / ExCallback.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Executive Callback test
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <kmt_test.h>
9
10 static
11 PEX_CALLBACK_ROUTINE_BLOCK
12 (NTAPI
13 *ExAllocateCallBack)(
14 IN PEX_CALLBACK_FUNCTION Function,
15 IN PVOID Context
16 )
17 //= (PVOID)0x809af1f4 // 2003 sp1 x86
18 //= (PVOID)0x80a7f04a // 2003 sp1 x86 checked
19 ;
20
21 static
22 VOID
23 (NTAPI
24 *ExFreeCallBack)(
25 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock
26 )
27 //= (PVOID)0x80918bb5 // 2003 sp1 x86
28 //= (PVOID)0x80a355f0 // 2003 sp1 x86 checked
29 ;
30
31 static INT CallbackArgument1;
32 static INT CallbackArgument2;
33
34 static
35 NTSTATUS
36 NTAPI
37 ExCallbackFunction(
38 IN PVOID CallbackContext,
39 IN PVOID Argument1 OPTIONAL,
40 IN PVOID Argument2 OPTIONAL)
41 {
42 ok(0, "Callback function unexpectedly called\n");
43 return STATUS_SUCCESS;
44 }
45
46 static
47 VOID
48 TestPrivateFunctions(VOID)
49 {
50 UNICODE_STRING ExAllocateCallBackName = RTL_CONSTANT_STRING(L"ExAllocateCallBack");
51 UNICODE_STRING ExFreeCallBackName = RTL_CONSTANT_STRING(L"ExFreeCallBack");
52 PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock;
53 INT CallbackContext;
54
55 if (!ExAllocateCallBack)
56 ExAllocateCallBack = MmGetSystemRoutineAddress(&ExAllocateCallBackName);
57 if (!ExFreeCallBack)
58 ExFreeCallBack = MmGetSystemRoutineAddress(&ExFreeCallBackName);
59
60 if (skip(ExAllocateCallBack && ExFreeCallBack,
61 "ExAllocateCallBack and/or ExFreeCallBack unavailable\n"))
62 return;
63
64 CallbackBlock = ExAllocateCallBack(ExCallbackFunction, &CallbackContext);
65 ok(CallbackBlock != NULL, "CallbackBlock = NULL\n");
66
67 if (skip(CallbackBlock != NULL, "Allocating callback failed\n"))
68 return;
69
70 ok_eq_pointer(CallbackBlock->Function, ExCallbackFunction);
71 ok_eq_pointer(CallbackBlock->Context, &CallbackContext);
72 ok_eq_hex(KmtGetPoolTag(CallbackBlock), 'brbC');
73
74 ExFreeCallBack(CallbackBlock);
75 }
76
77 static
78 VOID
79 NTAPI
80 CallbackFunction(
81 IN PVOID CallbackContext,
82 IN PVOID Argument1,
83 IN PVOID Argument2)
84 {
85 INT *InvocationCount = CallbackContext;
86
87 ok_irql(PASSIVE_LEVEL);
88
89 (*InvocationCount)++;
90 ok_eq_pointer(Argument1, &CallbackArgument1);
91 ok_eq_pointer(Argument2, &CallbackArgument2);
92 }
93
94 START_TEST(ExCallback)
95 {
96 NTSTATUS Status;
97 PCALLBACK_OBJECT CallbackObject;
98 OBJECT_ATTRIBUTES ObjectAttributes;
99 UNICODE_STRING CallbackName = RTL_CONSTANT_STRING(L"\\Callback\\KmtestExCallbackTestCallback");
100 PVOID CallbackRegistration;
101 INT InvocationCount = 0;
102
103 TestPrivateFunctions();
104
105 /* TODO: Parameter tests */
106 /* TODO: Test the three predefined callbacks */
107 /* TODO: Test opening an existing callback */
108 /* TODO: Test AllowMultipleCallbacks */
109 /* TODO: Test calling multiple callbacks */
110 /* TODO: Test registering the same function twice */
111 /* TODO: Test callback object fields */
112 /* TODO: Test callback registration fields */
113 InitializeObjectAttributes(&ObjectAttributes,
114 &CallbackName,
115 OBJ_CASE_INSENSITIVE,
116 NULL,
117 NULL);
118
119 CallbackObject = KmtInvalidPointer;
120 Status = ExCreateCallback(&CallbackObject,
121 &ObjectAttributes,
122 TRUE,
123 TRUE);
124 ok_eq_hex(Status, STATUS_SUCCESS);
125 ok(CallbackObject != NULL && CallbackObject != KmtInvalidPointer,
126 "CallbackObject = %p", CallbackObject);
127
128 if (skip(NT_SUCCESS(Status), "Creating callback failed\n"))
129 return;
130
131 CallbackRegistration = ExRegisterCallback(CallbackObject,
132 CallbackFunction,
133 &InvocationCount);
134 ok(CallbackRegistration != NULL, "CallbackRegistration = NULL\n");
135
136 if (!skip(CallbackRegistration != NULL, "Registering callback failed\n"))
137 {
138 ok_eq_hex(KmtGetPoolTag(CallbackRegistration), 'eRBC');
139 ok_eq_int(InvocationCount, 0);
140 ExNotifyCallback(CallbackObject,
141 &CallbackArgument1,
142 &CallbackArgument2);
143 ok_eq_int(InvocationCount, 1);
144 ExNotifyCallback(CallbackObject,
145 &CallbackArgument1,
146 &CallbackArgument2);
147 ok_eq_int(InvocationCount, 2);
148
149 ExUnregisterCallback(CallbackRegistration);
150 }
151
152 ObDereferenceObject(CallbackObject);
153 }