VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTNoCrt-3.cpp

Last change on this file was 98484, checked in by vboxsync, 16 months ago

IPRT/tstRTNoCrt-3: Corrected testcase name string. bugref:10261

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.8 KB
Line 
1/* $Id: tstRTNoCrt-3.cpp 98484 2023-02-07 10:43:44Z vboxsync $ */
2/** @file
3 * IPRT Testcase - Testcase for the No-CRT SEH bits on Windows.
4 */
5
6/*
7 * Copyright (C) 2022-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/win/windows.h>
42#include <iprt/string.h>
43#include <iprt/test.h>
44
45
46
47/*********************************************************************************************************************************
48* Global Variables *
49*********************************************************************************************************************************/
50RTTEST g_hTest;
51
52
53/*
54 * Simple access violation with a filter and handler that's called.
55 */
56
57static int tstSeh1Filter(uint32_t uStatus, PEXCEPTION_POINTERS pXcptPtrs)
58{
59 PEXCEPTION_RECORD const pXcptRec = pXcptPtrs->ExceptionRecord;
60 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
61 "tstSeh1Filter: uStatus=%#x pXcptPtrs=%p: Code=%#x Flags=%#x Rec=%p Addr=%#x cParms=%#x %p %p\n",
62 uStatus, pXcptPtrs,
63 pXcptRec->ExceptionCode,
64 pXcptRec->ExceptionFlags,
65 pXcptRec->ExceptionRecord,
66 pXcptRec->ExceptionAddress,
67 pXcptRec->NumberParameters,
68 pXcptRec->ExceptionInformation[0],
69 pXcptRec->ExceptionInformation[1]);
70 RTTESTI_CHECK_MSG(uStatus == STATUS_ACCESS_VIOLATION, ("uStatus=%#x\n", uStatus));
71 RTTESTI_CHECK_MSG(pXcptRec->ExceptionCode == STATUS_ACCESS_VIOLATION, ("ExceptionCode=%#x\n", pXcptRec->ExceptionCode));
72 RTTESTI_CHECK_MSG(pXcptRec->NumberParameters == 2, ("NumberParameters=%#x\n", pXcptRec->NumberParameters));
73 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[0] == 1, ("ExceptionInformation[0]=%#x\n", pXcptRec->ExceptionInformation[0]));
74 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[1] == 0x42, ("ExceptionInformation[1]=%#x\n", pXcptRec->ExceptionInformation[1]));
75 return EXCEPTION_EXECUTE_HANDLER;
76}
77
78static void tstSeh1(void)
79{
80 RTTestSub(g_hTest, "SEH #1");
81 uint8_t volatile cHandlerCalled = 0;
82 __try
83 {
84 uint8_t volatile *pu8 = (uint8_t volatile *)(uintptr_t)0x42;
85 *pu8 = 0x42;
86 }
87 __except(tstSeh1Filter(GetExceptionCode(), GetExceptionInformation()))
88 {
89 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh1/1: __except\n");
90 cHandlerCalled++;
91 }
92 RTTESTI_CHECK_MSG(cHandlerCalled == 1, ("cHandlerCalled=%d\n", cHandlerCalled));
93}
94
95
96/*
97 * Same but handler not called (continue search). We need to use a 2nd
98 * wrapper here to avoid terminating the app.
99 */
100
101static int tstSeh2Filter(uint32_t uStatus, PEXCEPTION_POINTERS pXcptPtrs)
102{
103 PEXCEPTION_RECORD const pXcptRec = pXcptPtrs->ExceptionRecord;
104 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
105 "tstSeh2Filter: uStatus=%#x pXcptPtrs=%p: Code=%#x Flags=%#x Rec=%p Addr=%#x cParms=%#x %p %p\n",
106 uStatus, pXcptPtrs,
107 pXcptRec->ExceptionCode,
108 pXcptRec->ExceptionFlags,
109 pXcptRec->ExceptionRecord,
110 pXcptRec->ExceptionAddress,
111 pXcptRec->NumberParameters,
112 pXcptRec->ExceptionInformation[0],
113 pXcptRec->ExceptionInformation[1]);
114 RTTESTI_CHECK_MSG(uStatus == STATUS_ACCESS_VIOLATION, ("uStatus=%#x\n", uStatus));
115 RTTESTI_CHECK_MSG(pXcptRec->ExceptionCode == STATUS_ACCESS_VIOLATION, ("ExceptionCode=%#x\n", pXcptRec->ExceptionCode));
116 RTTESTI_CHECK_MSG(pXcptRec->NumberParameters == 2, ("NumberParameters=%#x\n", pXcptRec->NumberParameters));
117 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[0] == 1, ("ExceptionInformation[0]=%#x\n", pXcptRec->ExceptionInformation[0]));
118 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[1] == 0x42, ("ExceptionInformation[1]=%#x\n", pXcptRec->ExceptionInformation[1]));
119 return EXCEPTION_CONTINUE_SEARCH;
120}
121
122static void tstSeh2(void)
123{
124 RTTestSub(g_hTest, "SEH #2");
125 uint8_t volatile cInnerHandlerCalled = 0;
126 uint8_t volatile cOuterHandlerCalled = 0;
127 __try
128 {
129 __try
130 {
131 uint8_t volatile *pu8 = (uint8_t volatile *)(uintptr_t)0x42;
132 *pu8 = 0x42;
133 }
134 __except(tstSeh2Filter(GetExceptionCode(), GetExceptionInformation()))
135 {
136 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh2/inner: __except\n");
137 cInnerHandlerCalled++;
138 }
139 }
140 __except(EXCEPTION_EXECUTE_HANDLER)
141 {
142 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh2/outer: __except\n");
143 cOuterHandlerCalled++;
144 }
145 RTTESTI_CHECK_MSG(cInnerHandlerCalled == 0, ("cHandlerCalled=%d\n", cInnerHandlerCalled));
146 RTTESTI_CHECK_MSG(cOuterHandlerCalled == 1, ("cOuterHandlerCalled=%d\n", cOuterHandlerCalled));
147}
148
149
150/*
151 * Simple finally construct.
152 */
153static void tstSeh3(void)
154{
155 RTTestSub(g_hTest, "SEH #3");
156 uint8_t volatile cFinallyHandlerCalled = 0;
157 uint8_t volatile cOuterHandlerCalled = 0;
158 __try
159 {
160 __try
161 {
162 uint8_t volatile *pu8 = (uint8_t volatile *)(uintptr_t)0x42;
163 *pu8 = 0x42;
164 }
165 __finally
166 {
167 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh3/inner: __finally: AbnormalTermination()=>%d\n", AbnormalTermination());
168 RTTESTI_CHECK_MSG(AbnormalTermination() == 1, ("AbnormalTermination()=>%d\n", AbnormalTermination()));
169 cFinallyHandlerCalled++;
170 }
171 }
172 __except(EXCEPTION_EXECUTE_HANDLER)
173 {
174 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh3/outer: __except\n");
175 cOuterHandlerCalled++;
176 }
177 RTTESTI_CHECK_MSG(cFinallyHandlerCalled == 1, ("cFinallyHandlerCalled=%d\n", cFinallyHandlerCalled));
178 RTTESTI_CHECK_MSG(cOuterHandlerCalled == 1, ("cOuterHandlerCalled=%d\n", cOuterHandlerCalled));
179}
180
181
182/*
183 * Continue execution.
184 */
185static volatile unsigned g_cSeh4FilterCalls = 0;
186
187static int tstSeh4Filter(PEXCEPTION_POINTERS pXcptPtrs)
188{
189 PEXCEPTION_RECORD const pXcptRec = pXcptPtrs->ExceptionRecord;
190 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
191 "tstSeh4Filter: pXcptPtrs=%p: Code=%#x Flags=%#x Rec=%p Addr=%#x cParms=%#x %p %p\n",
192 pXcptPtrs,
193 pXcptRec->ExceptionCode,
194 pXcptRec->ExceptionFlags,
195 pXcptRec->ExceptionRecord,
196 pXcptRec->ExceptionAddress,
197 pXcptRec->NumberParameters);
198 RTTESTI_CHECK_MSG(pXcptRec->ExceptionCode == UINT32_C(0xc0c1c2c3), ("ExceptionCode=%#x\n", pXcptRec->ExceptionCode));
199 RTTESTI_CHECK_MSG(pXcptRec->NumberParameters == 0, ("NumberParameters=%#x\n", pXcptRec->NumberParameters));
200 g_cSeh4FilterCalls++;
201 return EXCEPTION_CONTINUE_EXECUTION;
202}
203
204
205static void tstSeh4(void)
206{
207 RTTestSub(g_hTest, "SEH #4");
208 uint8_t volatile cHandlerCalled = 0;
209 uint8_t volatile cContinued = 0;
210 g_cSeh4FilterCalls = 0;
211 __try
212 {
213 RaiseException(UINT32_C(0xc0c1c2c3), 0, 0, NULL);
214 cContinued++;
215 }
216 __except(tstSeh4Filter(GetExceptionInformation()))
217 {
218 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh4/outer: __except\n");
219 cHandlerCalled++;
220 }
221 RTTESTI_CHECK_MSG(cContinued == 1, ("cContinued=%d\n", cContinued));
222 RTTESTI_CHECK_MSG(cHandlerCalled == 0, ("cHandlerCalled=%d\n", cHandlerCalled));
223 RTTESTI_CHECK_MSG(g_cSeh4FilterCalls == 1, ("g_cSeh4FilterCalls=%d\n", g_cSeh4FilterCalls));
224}
225
226
227/*
228 * Catching exception in sub function.
229 */
230unsigned volatile g_cSeh5InnerCalls = 0;
231unsigned volatile g_cSeh5FilterCalls = 0;
232
233DECL_NO_INLINE(extern, void) tstSeh5Inner(void)
234{
235 uint8_t volatile *pu8 = (uint8_t volatile *)(uintptr_t)0x22;
236 g_cSeh5InnerCalls++;
237 *pu8 = 0x22;
238}
239
240
241static int tstSeh5Filter(PEXCEPTION_POINTERS pXcptPtrs)
242{
243 PEXCEPTION_RECORD const pXcptRec = pXcptPtrs->ExceptionRecord;
244 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
245 "tstSeh5Filter: pXcptPtrs=%p: Code=%#x Flags=%#x Rec=%p Addr=%#x cParms=%#x %p %p\n",
246 pXcptPtrs,
247 pXcptRec->ExceptionCode,
248 pXcptRec->ExceptionFlags,
249 pXcptRec->ExceptionRecord,
250 pXcptRec->ExceptionAddress,
251 pXcptRec->NumberParameters,
252 pXcptRec->ExceptionInformation[0],
253 pXcptRec->ExceptionInformation[1]);
254 RTTESTI_CHECK_MSG(pXcptRec->ExceptionCode == STATUS_ACCESS_VIOLATION, ("ExceptionCode=%#x\n", pXcptRec->ExceptionCode));
255 RTTESTI_CHECK_MSG(pXcptRec->NumberParameters == 2, ("NumberParameters=%#x\n", pXcptRec->NumberParameters));
256 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[0] == 1, ("ExceptionInformation[0]=%#x\n", pXcptRec->ExceptionInformation[0]));
257 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[1] == 0x22, ("ExceptionInformation[1]=%#x\n", pXcptRec->ExceptionInformation[1]));
258 g_cSeh5FilterCalls++;
259 return EXCEPTION_EXECUTE_HANDLER;
260}
261
262
263static void tstSeh5(void)
264{
265 RTTestSub(g_hTest, "SEH #5");
266 uint8_t volatile cHandlerCalled = 0;
267 g_cSeh5InnerCalls = 0;
268 g_cSeh5FilterCalls = 0;
269 __try
270 {
271 tstSeh5Inner();
272 RTTestIFailed("tstSeh5Inner returned");
273 }
274 __except(tstSeh5Filter(GetExceptionInformation()))
275 {
276 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh5: __except\n");
277 cHandlerCalled++;
278 }
279 RTTESTI_CHECK_MSG(cHandlerCalled == 1, ("cHandlerCalled=%d\n", cHandlerCalled));
280 RTTESTI_CHECK_MSG(g_cSeh5InnerCalls == 1, ("g_cSeh5FilterCalls=%d\n", g_cSeh5FilterCalls));
281 RTTESTI_CHECK_MSG(g_cSeh5FilterCalls == 1, ("g_cSeh5FilterCalls=%d\n", g_cSeh5FilterCalls));
282}
283
284
285/*
286 * Catching exception in sub function with a __try/__finally block in it.
287 */
288unsigned volatile g_cSeh6InnerCalls = 0;
289unsigned volatile g_cSeh6InnerFinallyCalls = 0;
290unsigned volatile g_cSeh6FilterCalls = 0;
291
292DECL_NO_INLINE(extern, void) tstSeh6Inner(void)
293{
294 __try
295 {
296 uint8_t volatile *pu8 = (uint8_t volatile *)(uintptr_t)0x22;
297 g_cSeh6InnerCalls++;
298 *pu8 = 0x22;
299 }
300 __finally
301 {
302 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh6Inner: __finally: AbnormalTermination()=>%d\n", AbnormalTermination());
303 RTTESTI_CHECK_MSG(AbnormalTermination() == 1, ("AbnormalTermination()=>%d\n", AbnormalTermination()));
304 g_cSeh6InnerFinallyCalls++;
305 }
306}
307
308
309static int tstSeh6Filter(PEXCEPTION_POINTERS pXcptPtrs)
310{
311 PEXCEPTION_RECORD const pXcptRec = pXcptPtrs->ExceptionRecord;
312 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
313 "tstSeh6Filter: pXcptPtrs=%p: Code=%#x Flags=%#x Rec=%p Addr=%#x cParms=%#x %p %p\n",
314 pXcptPtrs,
315 pXcptRec->ExceptionCode,
316 pXcptRec->ExceptionFlags,
317 pXcptRec->ExceptionRecord,
318 pXcptRec->ExceptionAddress,
319 pXcptRec->NumberParameters,
320 pXcptRec->ExceptionInformation[0],
321 pXcptRec->ExceptionInformation[1]);
322 RTTESTI_CHECK_MSG(pXcptRec->ExceptionCode == STATUS_ACCESS_VIOLATION, ("ExceptionCode=%#x\n", pXcptRec->ExceptionCode));
323 RTTESTI_CHECK_MSG(pXcptRec->NumberParameters == 2, ("NumberParameters=%#x\n", pXcptRec->NumberParameters));
324 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[0] == 1, ("ExceptionInformation[0]=%#x\n", pXcptRec->ExceptionInformation[0]));
325 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[1] == 0x22, ("ExceptionInformation[1]=%#x\n", pXcptRec->ExceptionInformation[1]));
326 g_cSeh6FilterCalls++;
327 return EXCEPTION_EXECUTE_HANDLER;
328}
329
330
331static void tstSeh6(void)
332{
333 RTTestSub(g_hTest, "SEH #6");
334 uint8_t volatile cHandlerCalled = 0;
335 g_cSeh6InnerCalls = 0;
336 g_cSeh6FilterCalls = 0;
337 g_cSeh6InnerFinallyCalls = 0;
338 __try
339 {
340 tstSeh6Inner();
341 RTTestIFailed("tstSeh6Inner returned");
342 }
343 __except(tstSeh6Filter(GetExceptionInformation()))
344 {
345 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh6: __except\n");
346 cHandlerCalled++;
347 }
348 RTTESTI_CHECK_MSG(cHandlerCalled == 1, ("cHandlerCalled=%d\n", cHandlerCalled));
349 RTTESTI_CHECK_MSG(g_cSeh6InnerCalls == 1, ("g_cSeh6FilterCalls=%d\n", g_cSeh6FilterCalls));
350 RTTESTI_CHECK_MSG(g_cSeh6FilterCalls == 1, ("g_cSeh6FilterCalls=%d\n", g_cSeh6FilterCalls));
351 RTTESTI_CHECK_MSG(g_cSeh6InnerFinallyCalls == 1, ("g_cSeh6InnerFinallyCalls=%d\n", g_cSeh6InnerFinallyCalls));
352}
353
354
355/*
356 * Catching exception in sub function with a __try/__finally block in it as well as the caller.
357 */
358unsigned volatile g_cSeh7InnerCalls = 0;
359unsigned volatile g_cSeh7InnerFinallyCalls = 0;
360unsigned volatile g_cSeh7FilterCalls = 0;
361
362DECL_NO_INLINE(extern, void) tstSeh7Inner(void)
363{
364 __try
365 {
366 uint8_t volatile *pu8 = (uint8_t volatile *)(uintptr_t)0x22;
367 g_cSeh7InnerCalls++;
368 *pu8 = 0x22;
369 }
370 __finally
371 {
372 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh7Inner: __finally: AbnormalTermination()=>%d\n", AbnormalTermination());
373 RTTESTI_CHECK_MSG(AbnormalTermination() == 1, ("AbnormalTermination()=>%d\n", AbnormalTermination()));
374 g_cSeh7InnerFinallyCalls++;
375 }
376}
377
378
379static int tstSeh7Filter(PEXCEPTION_POINTERS pXcptPtrs)
380{
381 PEXCEPTION_RECORD const pXcptRec = pXcptPtrs->ExceptionRecord;
382 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
383 "tstSeh7Filter: pXcptPtrs=%p: Code=%#x Flags=%#x Rec=%p Addr=%#x cParms=%#x %p %p\n",
384 pXcptPtrs,
385 pXcptRec->ExceptionCode,
386 pXcptRec->ExceptionFlags,
387 pXcptRec->ExceptionRecord,
388 pXcptRec->ExceptionAddress,
389 pXcptRec->NumberParameters,
390 pXcptRec->ExceptionInformation[0],
391 pXcptRec->ExceptionInformation[1]);
392 RTTESTI_CHECK_MSG(pXcptRec->ExceptionCode == STATUS_ACCESS_VIOLATION, ("ExceptionCode=%#x\n", pXcptRec->ExceptionCode));
393 RTTESTI_CHECK_MSG(pXcptRec->NumberParameters == 2, ("NumberParameters=%#x\n", pXcptRec->NumberParameters));
394 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[0] == 1, ("ExceptionInformation[0]=%#x\n", pXcptRec->ExceptionInformation[0]));
395 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[1] == 0x22, ("ExceptionInformation[1]=%#x\n", pXcptRec->ExceptionInformation[1]));
396 g_cSeh7FilterCalls++;
397 return EXCEPTION_EXECUTE_HANDLER;
398}
399
400
401static void tstSeh7(void)
402{
403 RTTestSub(g_hTest, "SEH #7");
404 uint8_t volatile cHandlerCalled = 0;
405 uint8_t volatile cOuterFinallyCalls = 0;
406 g_cSeh7InnerCalls = 0;
407 g_cSeh7FilterCalls = 0;
408 g_cSeh7InnerFinallyCalls = 0;
409 __try
410 {
411 __try
412 {
413 tstSeh7Inner();
414 }
415 __finally
416 {
417 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh7: __finally: AbnormalTermination()=>%d\n", AbnormalTermination());
418 RTTESTI_CHECK_MSG(AbnormalTermination() == 1, ("AbnormalTermination()=>%d\n", AbnormalTermination()));
419 cOuterFinallyCalls++;
420 }
421 RTTestIFailed("tstSeh7Inner returned");
422 }
423 __except(tstSeh7Filter(GetExceptionInformation()))
424 {
425 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh7: __except\n");
426 cHandlerCalled++;
427 }
428 RTTESTI_CHECK_MSG(cHandlerCalled == 1, ("cHandlerCalled=%d\n", cHandlerCalled));
429 RTTESTI_CHECK_MSG(cOuterFinallyCalls == 1, ("ccOuterFinallyCalls=%d\n", cOuterFinallyCalls));
430 RTTESTI_CHECK_MSG(g_cSeh7InnerCalls == 1, ("g_cSeh7FilterCalls=%d\n", g_cSeh7FilterCalls));
431 RTTESTI_CHECK_MSG(g_cSeh7FilterCalls == 1, ("g_cSeh7FilterCalls=%d\n", g_cSeh7FilterCalls));
432 RTTESTI_CHECK_MSG(g_cSeh7InnerFinallyCalls == 1, ("g_cSeh7InnerFinallyCalls=%d\n", g_cSeh7InnerFinallyCalls));
433}
434
435
436/*
437 * Much nested setup.
438 */
439unsigned volatile g_acSeh8Calls[6] = {0};
440unsigned volatile g_acSeh8FilterCalls[6] = {0};
441unsigned volatile g_acSeh8FinallyCalls[6] = {0};
442
443
444DECL_NO_INLINE(extern, void) tstSeh8Inner5(void)
445{
446 __try
447 {
448 uint8_t volatile *pu8 = (uint8_t volatile *)(uintptr_t)0x22;
449 g_acSeh8Calls[5] += 1;
450 *pu8 = 0x22;
451 }
452 __finally
453 {
454 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh8Inner5: __finally: AbnormalTermination()=>%d\n", AbnormalTermination());
455 RTTESTI_CHECK_MSG(AbnormalTermination() == 1, ("AbnormalTermination()=>%d\n", AbnormalTermination()));
456 g_acSeh8FinallyCalls[5] += 1;
457 }
458}
459
460
461DECL_NO_INLINE(extern, void) tstSeh8Inner4(void)
462{
463 __try
464 {
465 g_acSeh8Calls[4] += 1;
466 tstSeh8Inner5();
467 }
468 __finally
469 {
470 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh8Inner4: __finally: AbnormalTermination()=>%d\n", AbnormalTermination());
471 RTTESTI_CHECK_MSG(AbnormalTermination() == 1, ("AbnormalTermination()=>%d\n", AbnormalTermination()));
472 g_acSeh8FinallyCalls[4] += 1;
473 }
474}
475
476
477DECL_NO_INLINE(extern, void) tstSeh8Inner3(void)
478{
479 __try
480 {
481 __try
482 {
483 g_acSeh8Calls[3] += 1;
484 tstSeh8Inner4();
485 }
486 __finally
487 {
488 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh8Inner3: __finally: AbnormalTermination()=>%d\n", AbnormalTermination());
489 RTTESTI_CHECK_MSG(AbnormalTermination() == 1, ("AbnormalTermination()=>%d\n", AbnormalTermination()));
490 g_acSeh8FinallyCalls[3] += 1;
491 }
492 }
493 __except( g_acSeh8FilterCalls[3]++ == 0 && GetExceptionCode() == STATUS_ACCESS_VIOLATION
494 ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER)
495 {
496 RTTestIFailed("tstSeh3Inner3: Unexpected __except");
497 }
498}
499
500
501DECL_NO_INLINE(extern, void) tstSeh8Inner2(void)
502{
503 g_acSeh8Calls[2] += 1;
504 tstSeh8Inner3();
505}
506
507
508DECL_NO_INLINE(extern, void) tstSeh8Inner1(void)
509{
510 __try
511 {
512 g_acSeh8Calls[1] += 1;
513 tstSeh8Inner2();
514 }
515 __except( g_acSeh8FilterCalls[1]++ == 0 && GetExceptionCode() == STATUS_ACCESS_VIOLATION
516 ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER)
517 {
518 RTTestIFailed("tstSeh3Inner1: Unexpected __except");
519 }
520}
521
522
523static int tstSeh8Filter(PEXCEPTION_POINTERS pXcptPtrs)
524{
525 PEXCEPTION_RECORD const pXcptRec = pXcptPtrs->ExceptionRecord;
526 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
527 "tstSeh8Filter: pXcptPtrs=%p: Code=%#x Flags=%#x Rec=%p Addr=%#x cParms=%#x %p %p\n",
528 pXcptPtrs,
529 pXcptRec->ExceptionCode,
530 pXcptRec->ExceptionFlags,
531 pXcptRec->ExceptionRecord,
532 pXcptRec->ExceptionAddress,
533 pXcptRec->NumberParameters,
534 pXcptRec->ExceptionInformation[0],
535 pXcptRec->ExceptionInformation[1]);
536 RTTESTI_CHECK_MSG(pXcptRec->ExceptionCode == STATUS_ACCESS_VIOLATION, ("ExceptionCode=%#x\n", pXcptRec->ExceptionCode));
537 RTTESTI_CHECK_MSG(pXcptRec->NumberParameters == 2, ("NumberParameters=%#x\n", pXcptRec->NumberParameters));
538 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[0] == 1, ("ExceptionInformation[0]=%#x\n", pXcptRec->ExceptionInformation[0]));
539 RTTESTI_CHECK_MSG(pXcptRec->ExceptionInformation[1] == 0x22, ("ExceptionInformation[1]=%#x\n", pXcptRec->ExceptionInformation[1]));
540 g_acSeh8FilterCalls[0] += 1;
541 return EXCEPTION_EXECUTE_HANDLER;
542}
543
544
545static void tstSeh8(void)
546{
547 RTTestSub(g_hTest, "SEH #8");
548 for (unsigned i = 0; i < RT_ELEMENTS(g_acSeh8FinallyCalls); i++)
549 {
550 g_acSeh8Calls[i] = 0;
551 g_acSeh8FilterCalls[i] = 0;
552 g_acSeh8FinallyCalls[i] = 0;
553 }
554 uint8_t volatile cHandlerCalled = 0;
555 __try
556 {
557 __try
558 {
559 g_acSeh8Calls[0] += 1;
560 tstSeh8Inner1();
561 }
562 __finally
563 {
564 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh8: __finally: AbnormalTermination()=>%d\n", AbnormalTermination());
565 RTTESTI_CHECK_MSG(AbnormalTermination() == 1, ("AbnormalTermination()=>%d\n", AbnormalTermination()));
566 g_acSeh8FinallyCalls[0] += 1;
567 }
568 RTTestIFailed("tstSeh8Inner returned");
569 }
570 __except(tstSeh8Filter(GetExceptionInformation()))
571 {
572 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstSeh8: __except\n");
573 cHandlerCalled++;
574 }
575
576 for (unsigned i = 0; i < RT_ELEMENTS(g_acSeh8Calls); i++)
577 RTTESTI_CHECK(g_acSeh8Calls[i] == 1);
578 RTTESTI_CHECK_MSG(cHandlerCalled == 1, ("cHandlerCalled=%d\n", cHandlerCalled));
579 RTTESTI_CHECK(g_acSeh8FilterCalls[0] == 1);
580 RTTESTI_CHECK(g_acSeh8FilterCalls[1] == 1);
581 RTTESTI_CHECK(g_acSeh8FilterCalls[2] == 0);
582 RTTESTI_CHECK(g_acSeh8FilterCalls[3] == 1);
583 RTTESTI_CHECK(g_acSeh8FilterCalls[4] == 0);
584 RTTESTI_CHECK(g_acSeh8FilterCalls[5] == 0);
585 RTTESTI_CHECK(g_acSeh8FinallyCalls[0] == 1);
586 RTTESTI_CHECK(g_acSeh8FinallyCalls[1] == 0);
587 RTTESTI_CHECK(g_acSeh8FinallyCalls[2] == 0);
588 RTTESTI_CHECK(g_acSeh8FinallyCalls[3] == 1);
589 RTTESTI_CHECK(g_acSeh8FinallyCalls[4] == 1);
590 RTTESTI_CHECK(g_acSeh8FinallyCalls[5] == 1);
591}
592
593
594
595int main()
596{
597 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTNoCrt-3", &g_hTest);
598 if (rcExit != RTEXITCODE_SUCCESS)
599 return rcExit;
600
601 tstSeh1();
602 tstSeh2();
603 tstSeh3();
604 tstSeh4();
605 tstSeh5();
606 tstSeh6();
607 tstSeh7();
608 tstSeh8();
609
610 return RTTestSummaryAndDestroy(g_hTest);
611}
612
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use