2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Deferred Procedure Call test
5 * PROGRAMMER: Thomas Faber <thfabba@gmx.de>
13 /* TODO: DPC importance */
15 static volatile LONG DpcCount
;
16 static volatile UCHAR DpcImportance
;
18 static KDEFERRED_ROUTINE DpcHandler
;
25 IN PVOID DeferredContext
,
26 IN PVOID SystemArgument1
,
27 IN PVOID SystemArgument2
)
29 PKPRCB Prcb
= KeGetCurrentPrcb();
31 ok_irql(DISPATCH_LEVEL
);
32 InterlockedIncrement(&DpcCount
);
33 ok(DeferredContext
== Dpc
, "DeferredContext = %p, Dpc = %p, expected equal\n", DeferredContext
, Dpc
);
34 ok_eq_pointer(SystemArgument1
, (PVOID
)0xabc123);
35 ok_eq_pointer(SystemArgument2
, (PVOID
)0x5678);
37 /* KDPC object contents */
38 ok_eq_uint(Dpc
->Type
, DpcObject
);
39 ok_eq_uint(Dpc
->Importance
, DpcImportance
);
40 ok_eq_uint(Dpc
->Number
, 0);
41 ok(Dpc
->DpcListEntry
.Blink
!= NULL
, "\n");
42 ok(Dpc
->DpcListEntry
.Blink
!= &Dpc
->DpcListEntry
, "\n");
43 if (!skip(Dpc
->DpcListEntry
.Blink
!= NULL
, "DpcListEntry.Blink == NULL\n"))
44 ok_eq_pointer(Dpc
->DpcListEntry
.Flink
, Dpc
->DpcListEntry
.Blink
->Flink
);
46 ok(Dpc
->DpcListEntry
.Flink
!= NULL
, "\n");
47 ok(Dpc
->DpcListEntry
.Flink
!= &Dpc
->DpcListEntry
, "\n");
48 if (!skip(Dpc
->DpcListEntry
.Flink
!= NULL
, "DpcListEntry.Flink == NULL\n"))
49 ok_eq_pointer(Dpc
->DpcListEntry
.Blink
, Dpc
->DpcListEntry
.Flink
->Blink
);
51 ok_eq_pointer(Dpc
->DeferredRoutine
, DpcHandler
);
52 ok_eq_pointer(Dpc
->DeferredContext
, DeferredContext
);
53 ok_eq_pointer(Dpc
->SystemArgument1
, SystemArgument1
);
54 ok_eq_pointer(Dpc
->SystemArgument2
, SystemArgument2
);
55 ok_eq_pointer(Dpc
->DpcData
, NULL
);
57 ok_eq_uint(Prcb
->DpcRoutineActive
, 1);
58 /* this DPC is not in the list anymore, but it was at the head! */
59 ok_eq_pointer(Prcb
->DpcData
[DPC_NORMAL
].DpcListHead
.Flink
, Dpc
->DpcListEntry
.Flink
);
60 ok_eq_pointer(Prcb
->DpcData
[DPC_NORMAL
].DpcListHead
.Blink
, Dpc
->DpcListEntry
.Blink
);
65 NTSTATUS Status
= STATUS_SUCCESS
;
67 KIRQL Irql
, Irql2
, Irql3
;
68 LONG ExpectedDpcCount
= 0;
73 DpcImportance
= MediumImportance
;
75 #define ok_dpccount() ok(DpcCount == ExpectedDpcCount, "DpcCount = %ld, expected %ld\n", DpcCount, ExpectedDpcCount);
76 trace("Dpc = %p\n", &Dpc
);
77 memset(&Dpc
, 0x55, sizeof Dpc
);
78 KeInitializeDpc(&Dpc
, DpcHandler
, &Dpc
);
79 /* check the Dpc object's fields */
80 ok_eq_uint(Dpc
.Type
, DpcObject
);
81 ok_eq_uint(Dpc
.Importance
, DpcImportance
);
82 ok_eq_uint(Dpc
.Number
, 0);
83 ok_eq_pointer(Dpc
.DpcListEntry
.Flink
, (LIST_ENTRY
*)0x5555555555555555LL
);
84 ok_eq_pointer(Dpc
.DpcListEntry
.Blink
, (LIST_ENTRY
*)0x5555555555555555LL
);
85 ok_eq_pointer(Dpc
.DeferredRoutine
, DpcHandler
);
86 ok_eq_pointer(Dpc
.DeferredContext
, &Dpc
);
87 ok_eq_pointer(Dpc
.SystemArgument1
, (PVOID
)0x5555555555555555LL
);
88 ok_eq_pointer(Dpc
.SystemArgument2
, (PVOID
)0x5555555555555555LL
);
89 ok_eq_pointer(Dpc
.DpcData
, NULL
);
91 /* simply run the Dpc a few times */
92 for (i
= 0; i
< 5; ++i
)
95 Ret
= KeInsertQueueDpc(&Dpc
, (PVOID
)0xabc123, (PVOID
)0x5678);
96 ok_bool_true(Ret
, "KeInsertQueueDpc returned");
101 /* insert into queue at high irql
102 * -> should only run when lowered to APC_LEVEL,
103 * inserting a second time should fail
105 KeRaiseIrql(APC_LEVEL
, &Irql
);
106 for (i
= 0; i
< 5; ++i
)
108 KeRaiseIrql(DISPATCH_LEVEL
, &Irql2
);
110 Ret
= KeInsertQueueDpc(&Dpc
, (PVOID
)0xabc123, (PVOID
)0x5678);
111 ok_bool_true(Ret
, "KeInsertQueueDpc returned");
112 Ret
= KeInsertQueueDpc(&Dpc
, (PVOID
)0xdef, (PVOID
)0x123);
113 ok_bool_false(Ret
, "KeInsertQueueDpc returned");
115 KeRaiseIrql(HIGH_LEVEL
, &Irql3
);
125 /* now test removing from the queue */
126 KeRaiseIrql(APC_LEVEL
, &Irql
);
127 for (i
= 0; i
< 5; ++i
)
129 KeRaiseIrql(DISPATCH_LEVEL
, &Irql2
);
131 Ret
= KeRemoveQueueDpc(&Dpc
);
132 ok_bool_false(Ret
, "KeRemoveQueueDpc returned");
133 Ret
= KeInsertQueueDpc(&Dpc
, (PVOID
)0xabc123, (PVOID
)0x5678);
134 ok_bool_true(Ret
, "KeInsertQueueDpc returned");
136 KeRaiseIrql(HIGH_LEVEL
, &Irql3
);
140 Ret
= KeRemoveQueueDpc(&Dpc
);
141 ok_bool_true(Ret
, "KeRemoveQueueDpc returned");
147 /* parameter checks */
148 Status
= STATUS_SUCCESS
;
150 KeInitializeDpc(&Dpc
, NULL
, NULL
);
151 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
152 Status
= _SEH2_GetExceptionCode();
154 ok_eq_hex(Status
, STATUS_SUCCESS
);
156 if (!skip(Status
== STATUS_SUCCESS
, "KeInitializeDpc failed\n"))
158 KeRaiseIrql(HIGH_LEVEL
, &Irql
);
159 Ret
= KeInsertQueueDpc(&Dpc
, NULL
, NULL
);
160 ok_bool_true(Ret
, "KeInsertQueueDpc returned");
161 Ret
= KeRemoveQueueDpc(&Dpc
);
162 ok_bool_true(Ret
, "KeRemoveQueueDpc returned");
166 Status
= STATUS_SUCCESS
;
168 KeInitializeDpc(NULL
, NULL
, NULL
);
169 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
170 Status
= _SEH2_GetExceptionCode();
172 ok_eq_hex(Status
, STATUS_ACCESS_VIOLATION
);
174 /* These result in IRQL_NOT_LESS_OR_EQUAL on 2k3 -- IRQLs 0x1f and 0xff (?)
175 Ret = KeInsertQueueDpc(NULL, NULL, NULL);
176 Ret = KeRemoveQueueDpc(NULL);*/
179 ok_irql(PASSIVE_LEVEL
);
180 trace("Final Dpc count: %ld, expected %ld\n", DpcCount
, ExpectedDpcCount
);