1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Interrupt test
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <kmt_test.h>
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #define CheckSpinLock(Lock, Locked) do \
14 { \
15 if (KmtIsMultiProcessorBuild) \
16 ok_eq_ulongptr(*(Lock), (Locked) != 0); \
17 else if (KmtIsCheckedBuild) \
18 ok_eq_bool(*(Lock) != 0, (Locked) != 0); \
19 else \
20 ok_eq_ulongptr(*(Lock), 0); \
21 } while (0)
22
23 typedef struct
24 {
25 BOOLEAN ReturnValue;
26 KIRQL ExpectedIrql;
27 PKINTERRUPT Interrupt;
28 } TEST_CONTEXT, *PTEST_CONTEXT;
29
30 static KSYNCHRONIZE_ROUTINE SynchronizeRoutine;
31
32 static
33 BOOLEAN
34 NTAPI
SynchronizeRoutine(IN PVOID Context)35 SynchronizeRoutine(
36 IN PVOID Context)
37 {
38 PTEST_CONTEXT TestContext = Context;
39
40 ok_irql(TestContext->ExpectedIrql);
41
42 CheckSpinLock(TestContext->Interrupt->ActualLock, TRUE);
43
44 return TestContext->ReturnValue;
45 }
46
47 static
48 VOID
TestSynchronizeExecution(VOID)49 TestSynchronizeExecution(VOID)
50 {
51 KINTERRUPT Interrupt;
52 TEST_CONTEXT TestContext;
53 KIRQL SynchIrql;
54 KIRQL OriginalIrql;
55 KIRQL Irql;
56 KSPIN_LOCK ActualLock;
57 BOOLEAN Ret;
58
59 RtlFillMemory(&Interrupt, sizeof Interrupt, 0x55);
60 Interrupt.ActualLock = &ActualLock;
61 KeInitializeSpinLock(Interrupt.ActualLock);
62 CheckSpinLock(Interrupt.ActualLock, FALSE);
63
64 TestContext.Interrupt = &Interrupt;
65 TestContext.ReturnValue = TRUE;
66
67 for (TestContext.ReturnValue = 0; TestContext.ReturnValue <= 2; ++TestContext.ReturnValue)
68 {
69 for (OriginalIrql = PASSIVE_LEVEL; OriginalIrql <= HIGH_LEVEL; ++OriginalIrql)
70 {
71 /* TODO: don't hardcode this :| */
72 if (OriginalIrql == 3 || (OriginalIrql >= 11 && OriginalIrql <= 26) || OriginalIrql == 30)
73 continue;
74 KeRaiseIrql(OriginalIrql, &Irql);
75 for (SynchIrql = max(DISPATCH_LEVEL, OriginalIrql); SynchIrql <= HIGH_LEVEL; ++SynchIrql)
76 {
77 if (SynchIrql == 3 || (SynchIrql >= 11 && SynchIrql <= 26) || SynchIrql == 30)
78 continue;
79 Interrupt.SynchronizeIrql = SynchIrql;
80 ok_irql(OriginalIrql);
81 CheckSpinLock(Interrupt.ActualLock, FALSE);
82 TestContext.ExpectedIrql = SynchIrql;
83 Ret = KeSynchronizeExecution(&Interrupt, SynchronizeRoutine, &TestContext);
84 ok_eq_int(Ret, TestContext.ReturnValue);
85 ok_irql(OriginalIrql);
86 CheckSpinLock(Interrupt.ActualLock, FALSE);
87 /* TODO: Check that all other fields of the interrupt are untouched */
88 }
89 KeLowerIrql(Irql);
90 }
91 }
92 }
93
94 static
95 VOID
TestConnectInterrupt(VOID)96 TestConnectInterrupt(VOID)
97 {
98 PKINTERRUPT InterruptObject;
99 NTSTATUS Status;
100
101 /* If the IoConnectInterrupt() fails, the interrupt object should be set to NULL */
102 InterruptObject = KmtInvalidPointer;
103
104 /* Test for invalid interrupt */
105 Status = IoConnectInterrupt(&InterruptObject,
106 (PKSERVICE_ROUTINE)TestConnectInterrupt,
107 NULL,
108 NULL,
109 0,
110 0,
111 0,
112 LevelSensitive,
113 TRUE,
114 (KAFFINITY)-1,
115 FALSE);
116 ok_eq_hex(Status, STATUS_INVALID_PARAMETER);
117 ok_eq_pointer(InterruptObject, NULL);
118 }
119
START_TEST(IoInterrupt)120 START_TEST(IoInterrupt)
121 {
122 TestSynchronizeExecution();
123 TestConnectInterrupt();
124 }
125