2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Hard error message test
5 * PROGRAMMER: Thomas Faber <thfabba@gmx.de>
10 #include <ndk/exfuncs.h>
11 #include <pseh/pseh2.h>
15 /* TODO: don't require user interaction, test Io* routines,
16 * test NTSTATUS values with special handling */
21 OUT PULONG_PTR Parameters
,
27 va_start(Arguments
, Count
);
28 for (i
= 0; i
< Count
; ++i
)
29 Parameters
[i
] = va_arg(Arguments
, ULONG_PTR
);
35 #define CheckHardError(ErrStatus, UnicodeStringMask, ResponseOption, \
36 ExpectedStatus, ExpectedResponse, \
37 NumberOfParameters, ...) do \
39 SetParameters(HardErrorParameters, NumberOfParameters, __VA_ARGS__);\
40 Response = NoResponse; \
42 Status = ExRaiseHardError(ErrStatus, \
45 HardErrorParameters, \
48 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
49 Status = _SEH2_GetExceptionCode(); \
51 ok_eq_hex(Status, ExpectedStatus); \
52 ok_eq_ulong(Response, (ULONG)ExpectedResponse); \
55 #define CheckInformationalHardError(ErrStatus, String, Thread, \
56 ExpectedStatus, ExpectedRet) do \
58 Status = STATUS_SUCCESS; \
61 Ret = IoRaiseInformationalHardError(ErrStatus, \
64 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
65 Status = _SEH2_GetExceptionCode(); \
67 ok_eq_hex(Status, ExpectedStatus); \
68 ok_eq_bool(Ret, ExpectedRet); \
74 BOOLEAN InteractivePart1
,
75 BOOLEAN InteractivePart2
,
76 BOOLEAN InteractivePart3
,
77 BOOLEAN InteractivePart4
)
81 WCHAR StringBuffer1
[] = L
"Parameter1+Garbage";
82 CHAR StringBuffer1Ansi
[] = "Parameter1+Garbage";
83 WCHAR StringBuffer2
[] = L
"Parameter2+Garbage";
84 UNICODE_STRING String1
= RTL_CONSTANT_STRING(StringBuffer1
);
85 ANSI_STRING String1Ansi
= RTL_CONSTANT_STRING(StringBuffer1Ansi
);
86 UNICODE_STRING String2
= RTL_CONSTANT_STRING(StringBuffer2
);
87 ULONG_PTR HardErrorParameters
[6];
90 String1
.Length
= sizeof L
"Parameter1" - sizeof UNICODE_NULL
;
91 String1Ansi
.Length
= sizeof "Parameter1" - sizeof ANSI_NULL
;
92 String2
.Length
= sizeof L
"Parameter2" - sizeof UNICODE_NULL
;
96 CheckHardError(0x40000000, 0, OptionOk
, STATUS_SUCCESS
, ResponseOk
, 0, 0); // outputs a box :|
97 CheckHardError(0x40000001, 0, OptionOk
, STATUS_SUCCESS
, ResponseOk
, 4, 1, 2, 3, 4); // outputs a box :|
98 CheckHardError(0x40000002, 0, OptionOk
, STATUS_SUCCESS
, ResponseOk
, 5, 1, 2, 3, 4, 5); // outputs a box :|
100 CheckHardError(0x40000003, 0, OptionOk
, STATUS_SUCCESS
, ResponseNotHandled
, 6, 1, 2, 3, 4, 5, 6);
102 CheckHardError(0x40000004, 0, OptionShutdownSystem
, STATUS_PRIVILEGE_NOT_HELD
, ResponseNotHandled
, 0, 0);
103 CheckHardError(0x40000005, 0, OptionOkNoWait
, STATUS_SUCCESS
, ResponseOk
, 0, 0); // outputs a balloon notification
104 CheckHardError(0x4000000f, 0, OptionOkNoWait
, STATUS_SUCCESS
, ResponseOk
, 0, 0); // outputs a balloon notification
105 if (InteractivePart1
)
107 CheckHardError(0x40000006, 0, OptionAbortRetryIgnore
, STATUS_SUCCESS
, ResponseAbort
, 0, 0); // outputs a box :|
108 CheckHardError(0x40000006, 0, OptionAbortRetryIgnore
, STATUS_SUCCESS
, ResponseRetry
, 0, 0); // outputs a box :|
109 CheckHardError(0x40000006, 0, OptionAbortRetryIgnore
, STATUS_SUCCESS
, ResponseIgnore
, 0, 0); // outputs a box :|
110 CheckHardError(0x40000008, 0, OptionCancelTryContinue
, STATUS_SUCCESS
, ResponseCancel
, 0, 0); // outputs a box :|
111 CheckHardError(0x40000008, 0, OptionCancelTryContinue
, STATUS_SUCCESS
, ResponseTryAgain
, 0, 0); // outputs a box :|
112 CheckHardError(0x40000008, 0, OptionCancelTryContinue
, STATUS_SUCCESS
, ResponseContinue
, 0, 0); // outputs a box :|
113 CheckHardError(0x40000010, 0, OptionOkCancel
, STATUS_SUCCESS
, ResponseOk
, 0, 0); // outputs a box :|
114 CheckHardError(0x40000010, 0, OptionOkCancel
, STATUS_SUCCESS
, ResponseCancel
, 0, 0); // outputs a box :|
115 CheckHardError(0x40000011, 0, OptionRetryCancel
, STATUS_SUCCESS
, ResponseRetry
, 0, 0); // outputs a box :|
116 CheckHardError(0x40000011, 0, OptionRetryCancel
, STATUS_SUCCESS
, ResponseCancel
, 0, 0); // outputs a box :|
117 CheckHardError(0x40000012, 0, OptionYesNo
, STATUS_SUCCESS
, ResponseYes
, 0, 0); // outputs a box :|
118 CheckHardError(0x40000012, 0, OptionYesNo
, STATUS_SUCCESS
, ResponseNo
, 0, 0); // outputs a box :|
119 CheckHardError(0x40000013, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseYes
, 0, 0); // outputs a box :|
120 CheckHardError(0x40000013, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNo
, 0, 0); // outputs a box :|
121 CheckHardError(0x40000013, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 0, 0); // outputs a box :|
123 CheckHardError(0x40000009, 0, 9, STATUS_SUCCESS
, ResponseNotHandled
, 0, 0);
124 CheckHardError(0x4000000a, 0, 10, STATUS_SUCCESS
, ResponseNotHandled
, 0, 0);
125 CheckHardError(0x4000000b, 0, 11, STATUS_SUCCESS
, ResponseNotHandled
, 0, 0);
126 CheckHardError(0x4000000c, 0, 12, STATUS_SUCCESS
, ResponseNotHandled
, 0, 0);
127 CheckHardError(0x4000000d, 0, MAXULONG
/ 2 + 1, STATUS_SUCCESS
, ResponseNotHandled
, 0, 0);
128 CheckHardError(0x4000000d, 0, MAXULONG
, STATUS_SUCCESS
, ResponseNotHandled
, 0, 0);
130 if (InteractivePart2
)
132 /* try a message with one parameter */
133 CheckHardError(STATUS_DLL_NOT_FOUND
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseYes
, 1, &String1
); // outputs a box :|
134 CheckHardError(STATUS_DLL_NOT_FOUND
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, &String1
); // outputs a box :|
135 CheckHardError(STATUS_DLL_NOT_FOUND
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 0, &String1
); // outputs a box :|
136 CheckHardError(STATUS_DLL_NOT_FOUND
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 0, &String1
); // outputs a box :|
137 /* give too many parameters */
138 CheckHardError(STATUS_DLL_NOT_FOUND
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseYes
, 2, &String1
, &String2
); // outputs a box :|
139 CheckHardError(STATUS_DLL_NOT_FOUND
, 2, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 2, &String1
, &String2
); // outputs a box :|
140 CheckHardError(STATUS_DLL_NOT_FOUND
, 3, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseYes
, 2, &String1
, &String2
); // outputs a box :|
141 CheckHardError(STATUS_DLL_NOT_FOUND
, 3, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseYes
, 4, &String1
, &String2
, 0, 0); // outputs a box :|
142 /* try with stuff that's not a UNICODE_STRING */
143 CheckHardError(STATUS_DLL_NOT_FOUND
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNo
, 1, &String1Ansi
); // outputs a box :|
144 CheckHardError(STATUS_DLL_NOT_FOUND
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNo
, 1, L
"Parameter1"); // outputs a box :|
145 CheckHardError(STATUS_DLL_NOT_FOUND
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNo
, 1, "Parameter1"); // outputs a box :|
146 CheckHardError(STATUS_DLL_NOT_FOUND
, 1, OptionYesNoCancel
, STATUS_ACCESS_VIOLATION
, NoResponse
, 1, 1234); // outputs a box :|
147 CheckHardError(STATUS_DLL_NOT_FOUND
, 1, OptionYesNoCancel
, STATUS_ACCESS_VIOLATION
, NoResponse
, 1, NULL
); // outputs a box :|
148 CheckHardError(STATUS_DLL_NOT_FOUND
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, &String1Ansi
); // outputs a box :|
149 CheckHardError(STATUS_DLL_NOT_FOUND
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, L
"Parameter1"); // outputs a box :|
150 CheckHardError(STATUS_DLL_NOT_FOUND
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, "Parameter1"); // outputs a box :|
151 CheckHardError(STATUS_DLL_NOT_FOUND
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, 1234); // outputs a box :|
152 CheckHardError(STATUS_DLL_NOT_FOUND
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, NULL
); // outputs a box :|
154 if (InteractivePart3
)
156 /* try a message with one parameter */
157 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 1, &String1
); // outputs a box :|
158 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 1, &String1
); // outputs a box :|
159 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 0, &String1
); // outputs a box :|
160 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 0, &String1
); // outputs a box :|
161 /* give too many parameters */
162 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 2, &String1
, &String2
); // outputs a box :|
163 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 2, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 2, &String1
, &String2
); // outputs a box :|
164 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 3, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 2, &String1
, &String2
); // outputs a box :|
165 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 3, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseOk
, 3, &String1
, &String2
, 0); // outputs a box :|
166 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 3, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseOk
, 4, &String1
, &String2
, 0, 0); // outputs a box :|
167 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 3, OptionOkNoWait
, STATUS_SUCCESS
, ResponseOk
, 4, &String1
, &String2
, 0, 0); // outputs a balloon notification
168 /* try with stuff that's not a UNICODE_STRING */
169 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 1, &String1Ansi
); // outputs a box :|
170 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 1, L
"Parameter1"); // outputs a box :|
171 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 1, "Parameter1"); // outputs a box :|
172 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 1, OptionYesNoCancel
, STATUS_ACCESS_VIOLATION
, NoResponse
, 1, 1234); // outputs a box :|
173 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 1, OptionYesNoCancel
, STATUS_ACCESS_VIOLATION
, NoResponse
, 1, NULL
); // outputs a box :|
174 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 1, &String1Ansi
); // outputs a box :|
175 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 1, L
"Parameter1"); // outputs a box :|
176 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 1, "Parameter1"); // outputs a box :|
177 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 1, 1234); // outputs a box :|
178 CheckHardError(STATUS_SERVICE_NOTIFICATION
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNotHandled
, 1, NULL
); // outputs a box :|
180 if (InteractivePart4
)
182 /* try a message with one parameter */
183 CheckHardError(STATUS_FATAL_APP_EXIT
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseYes
, 1, &String1
); // outputs a box :|
184 CheckHardError(STATUS_FATAL_APP_EXIT
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, &String1
); // outputs a box :|
185 CheckHardError(STATUS_FATAL_APP_EXIT
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 0, &String1
); // outputs a box :|
186 CheckHardError(STATUS_FATAL_APP_EXIT
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 0, &String1
); // outputs a box :|
187 /* give too many parameters */
188 CheckHardError(STATUS_FATAL_APP_EXIT
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseYes
, 2, &String1
, &String2
); // outputs a box :|
189 CheckHardError(STATUS_FATAL_APP_EXIT
, 2, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 2, &String1
, &String2
); // outputs a box :|
190 CheckHardError(STATUS_FATAL_APP_EXIT
, 3, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseYes
, 2, &String1
, &String2
); // outputs a box :|
191 CheckHardError(STATUS_FATAL_APP_EXIT
, 3, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseYes
, 4, &String1
, &String2
, 0, 0); // outputs a box :|
192 /* try with stuff that's not a UNICODE_STRING */
193 CheckHardError(STATUS_FATAL_APP_EXIT
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNo
, 1, &String1Ansi
); // outputs a box :|
194 CheckHardError(STATUS_FATAL_APP_EXIT
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNo
, 1, L
"Parameter1"); // outputs a box :|
195 CheckHardError(STATUS_FATAL_APP_EXIT
, 1, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseNo
, 1, "Parameter1"); // outputs a box :|
196 CheckHardError(STATUS_FATAL_APP_EXIT
, 1, OptionYesNoCancel
, STATUS_ACCESS_VIOLATION
, NoResponse
, 1, 1234); // outputs a box :|
197 CheckHardError(STATUS_FATAL_APP_EXIT
, 1, OptionYesNoCancel
, STATUS_ACCESS_VIOLATION
, NoResponse
, 1, NULL
); // outputs a box :|
198 CheckHardError(STATUS_FATAL_APP_EXIT
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, &String1Ansi
); // outputs a box :|
199 CheckHardError(STATUS_FATAL_APP_EXIT
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, L
"Parameter1"); // outputs a box :|
200 CheckHardError(STATUS_FATAL_APP_EXIT
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, "Parameter1"); // outputs a box :|
201 CheckHardError(STATUS_FATAL_APP_EXIT
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, 1234); // outputs a box :|
202 CheckHardError(STATUS_FATAL_APP_EXIT
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseCancel
, 1, NULL
); // outputs a box :|
205 CheckInformationalHardError(STATUS_WAIT_0
, NULL
, NULL
, STATUS_SUCCESS
, TRUE
); // outputs a balloon notification
206 CheckInformationalHardError(STATUS_DLL_NOT_FOUND
, &String1
, NULL
, STATUS_SUCCESS
, TRUE
); // outputs a balloon notification
207 CheckInformationalHardError(STATUS_DLL_NOT_FOUND
, NULL
, NULL
, STATUS_SUCCESS
, TRUE
); // outputs a balloon notification
208 CheckInformationalHardError(STATUS_SERVICE_NOTIFICATION
, &String1
, NULL
, STATUS_SUCCESS
, FALSE
);
210 ok_bool_true(IoSetThreadHardErrorMode(TRUE
), "IoSetThreadHardErrorMode returned");
211 ok_bool_true(IoSetThreadHardErrorMode(FALSE
), "IoSetThreadHardErrorMode returned");
212 ok_bool_false(IoSetThreadHardErrorMode(FALSE
), "IoSetThreadHardErrorMode returned");
213 CheckHardError(STATUS_FATAL_APP_EXIT
, 0, OptionYesNoCancel
, STATUS_SUCCESS
, ResponseReturnToCaller
, 0, 0);
214 CheckHardError(STATUS_FATAL_APP_EXIT
, 1, OptionYesNoCancel
, STATUS_ACCESS_VIOLATION
, NoResponse
, 1, NULL
);
215 CheckInformationalHardError(STATUS_WAIT_0
, NULL
, NULL
, STATUS_SUCCESS
, FALSE
);
216 CheckInformationalHardError(STATUS_DLL_NOT_FOUND
, &String1
, NULL
, STATUS_SUCCESS
, FALSE
);
217 CheckInformationalHardError(STATUS_DLL_NOT_FOUND
, NULL
, NULL
, STATUS_SUCCESS
, FALSE
);
218 CheckInformationalHardError(STATUS_SERVICE_NOTIFICATION
, &String1
, NULL
, STATUS_SUCCESS
, FALSE
);
219 ok_bool_false(IoSetThreadHardErrorMode(TRUE
), "IoSetThreadHardErrorMode returned");
222 START_TEST(ExHardError
)
224 TestHardError(FALSE
, FALSE
, FALSE
, FALSE
);
227 /* Here's how to do the interactive test:
228 * - First there will be a few messages random messages. If there's
229 * multiple options available, the same box will appear multiple times --
230 * click the buttons in order from left to right
231 * - After that, you must verify the error parameters. You should always
232 * see Parameter1 or Parameter2 for strings, and 0x12345678 for numbers.
233 * if there's a message saying an exception occured during processing,
234 * click cancel. If there's a bad parameter (Parameter1+, Parameter1+Garbage
235 * or an empty string for example), click no. Otherwise click yes. */
236 START_TEST(ExHardErrorInteractive
)
238 TestHardError(TRUE
, TRUE
, TRUE
, TRUE
);