1 /*
2 	Copyright (c) 2008 KJK::Hyperion
3 
4 	Permission is hereby granted, free of charge, to any person obtaining a
5 	copy of this software and associated documentation files (the "Software"),
6 	to deal in the Software without restriction, including without limitation
7 	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 	and/or sell copies of the Software, and to permit persons to whom the
9 	Software is furnished to do so, subject to the following conditions:
10 
11 	The above copyright notice and this permission notice shall be included in
12 	all copies or substantial portions of the Software.
13 
14 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 	DEALINGS IN THE SOFTWARE.
21 */
22 
23 #include <pseh/pseh2.h>
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 #include <wine/test.h>
30 #undef subtest
31 
32 extern void no_op(void);
33 extern int return_arg(int);
34 
35 extern int return_zero(void);
36 extern int return_positive(void);
37 extern int return_negative(void);
38 extern int return_one(void);
39 extern int return_minusone(void);
40 
41 extern int return_zero_2(void *);
42 extern int return_positive_2(void *);
43 extern int return_negative_2(void *);
44 extern int return_one_2(void *);
45 extern int return_minusone_2(void *);
46 
47 extern int return_zero_3(int);
48 extern int return_positive_3(int);
49 extern int return_negative_3(int);
50 extern int return_one_3(int);
51 extern int return_minusone_3(int);
52 
53 extern int return_zero_4(void *, int);
54 extern int return_positive_4(void *, int);
55 extern int return_negative_4(void *, int);
56 extern int return_one_4(void *, int);
57 extern int return_minusone_4(void *, int);
58 
59 extern void set_positive(int *);
60 
61 //static int call_test(int (*)(void));
62 
63 #ifdef __cplusplus
64 } // extern "C"
65 #endif
66 
67 #define DEFINE_TEST(NAME_) static int NAME_(void)
68 
69 /* Empty statements *///{{{
70 DEFINE_TEST(test_empty_1)
71 {
72 	_SEH2_TRY { } _SEH2_EXCEPT(0) { } _SEH2_END;
73 	return 1;
74 }
75 
76 DEFINE_TEST(test_empty_2)
77 {
78 	_SEH2_TRY { } _SEH2_EXCEPT(-1) { } _SEH2_END;
79 	return 1;
80 }
81 
82 DEFINE_TEST(test_empty_3)
83 {
84 	_SEH2_TRY { } _SEH2_EXCEPT(1) { } _SEH2_END;
85 	return 1;
86 }
87 
88 DEFINE_TEST(test_empty_4)
89 {
90 	_SEH2_TRY { } _SEH2_FINALLY { } _SEH2_END;
91 	return 1;
92 }
93 
94 DEFINE_TEST(test_empty_5)
95 {
96 	_SEH2_TRY { _SEH2_TRY { } _SEH2_EXCEPT(0) { } _SEH2_END; } _SEH2_FINALLY { } _SEH2_END;
97 	return 1;
98 }
99 
100 DEFINE_TEST(test_empty_6)
101 {
102 	_SEH2_TRY { _SEH2_TRY { } _SEH2_EXCEPT(-1) { } _SEH2_END; } _SEH2_FINALLY { } _SEH2_END;
103 	return 1;
104 }
105 
106 DEFINE_TEST(test_empty_7)
107 {
108 	_SEH2_TRY { _SEH2_TRY { } _SEH2_EXCEPT(1) { } _SEH2_END; } _SEH2_FINALLY { } _SEH2_END;
109 	return 1;
110 }
111 
112 DEFINE_TEST(test_empty_8)
113 {
114 	_SEH2_TRY { _SEH2_TRY { } _SEH2_FINALLY { } _SEH2_END; } _SEH2_FINALLY { } _SEH2_END;
115 	return 1;
116 }
117 //}}}
118 
119 /* Static exception filters *///{{{
120 DEFINE_TEST(test_execute_handler_1)
121 {
122 	static int ret;
123 
124 	ret = return_zero();
125 
126 	_SEH2_TRY
127 	{
128 		RaiseException(0xE00DEAD0, 0, 0, NULL);
129 		ret = return_zero();
130 	}
131 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
132 	{
133 		ret = return_positive();
134 	}
135 	_SEH2_END;
136 
137 	return ret == return_positive();
138 }
139 
140 DEFINE_TEST(test_continue_execution_1)
141 {
142 	static int ret;
143 
144 	ret = return_zero();
145 
146 	_SEH2_TRY
147 	{
148 		RaiseException(0xE00DEAD0, 0, 0, NULL);
149 		ret = return_positive();
150 	}
151 	_SEH2_EXCEPT(EXCEPTION_CONTINUE_EXECUTION)
152 	{
153 		ret = return_zero();
154 	}
155 	_SEH2_END;
156 
157 	return ret == return_positive();
158 }
159 
160 DEFINE_TEST(test_continue_search_1)
161 {
162 	static int ret;
163 
164 	ret = return_zero();
165 
166 	_SEH2_TRY
167 	{
168 		_SEH2_TRY
169 		{
170 			RaiseException(0xE00DEAD0, 0, 0, NULL);
171 			ret = return_zero();
172 		}
173 		_SEH2_EXCEPT(EXCEPTION_CONTINUE_SEARCH)
174 		{
175 			ret = return_zero();
176 		}
177 		_SEH2_END;
178 	}
179 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
180 	{
181 		ret = return_positive();
182 	}
183 	_SEH2_END;
184 
185 	return ret == return_positive();
186 }
187 
188 DEFINE_TEST(test_execute_handler_2)
189 {
190 	static int ret;
191 
192 	ret = return_zero();
193 
194 	_SEH2_TRY
195 	{
196 		RaiseException(0xE00DEAD0, 0, 0, NULL);
197 		ret = return_zero();
198 	}
199 	_SEH2_EXCEPT(12345)
200 	{
201 		ret = return_positive();
202 	}
203 	_SEH2_END;
204 
205 	return ret == return_positive();
206 }
207 
208 DEFINE_TEST(test_continue_execution_2)
209 {
210 	static int ret;
211 
212 	ret = return_zero();
213 
214 	_SEH2_TRY
215 	{
216 		RaiseException(0xE00DEAD0, 0, 0, NULL);
217 		ret = return_positive();
218 	}
219 	_SEH2_EXCEPT(-12345)
220 	{
221 		ret = return_zero();
222 	}
223 	_SEH2_END;
224 
225 	return ret == return_positive();
226 }
227 //}}}
228 
229 /* Dynamic exception filters *///{{{
230 DEFINE_TEST(test_execute_handler_3)
231 {
232 	static int ret;
233 
234 	ret = return_zero();
235 
236 	_SEH2_TRY
237 	{
238 		RaiseException(0xE00DEAD0, 0, 0, NULL);
239 		ret = return_zero();
240 	}
241 	_SEH2_EXCEPT(return_one())
242 	{
243 		ret = return_positive();
244 	}
245 	_SEH2_END;
246 
247 	return ret == return_positive();
248 }
249 
250 DEFINE_TEST(test_continue_execution_3)
251 {
252 	static int ret;
253 
254 	ret = return_zero();
255 
256 	_SEH2_TRY
257 	{
258 		RaiseException(0xE00DEAD0, 0, 0, NULL);
259 		ret = return_positive();
260 	}
261 	_SEH2_EXCEPT(return_minusone())
262 	{
263 		ret = return_zero();
264 	}
265 	_SEH2_END;
266 
267 	return ret == return_positive();
268 }
269 
270 DEFINE_TEST(test_continue_search_2)
271 {
272 	static int ret;
273 
274 	ret = return_zero();
275 
276 	_SEH2_TRY
277 	{
278 		_SEH2_TRY
279 		{
280 			RaiseException(0xE00DEAD0, 0, 0, NULL);
281 			ret = return_zero();
282 		}
283 		_SEH2_EXCEPT(return_zero())
284 		{
285 			ret = return_zero();
286 		}
287 		_SEH2_END;
288 	}
289 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
290 	{
291 		ret = return_positive();
292 	}
293 	_SEH2_END;
294 
295 	return ret == return_positive();
296 }
297 
298 DEFINE_TEST(test_execute_handler_4)
299 {
300 	static int ret;
301 
302 	ret = return_zero();
303 
304 	_SEH2_TRY
305 	{
306 		RaiseException(0xE00DEAD0, 0, 0, NULL);
307 		ret = return_zero();
308 	}
309 	_SEH2_EXCEPT(return_positive())
310 	{
311 		ret = return_positive();
312 	}
313 	_SEH2_END;
314 
315 	return ret == return_positive();
316 }
317 
318 DEFINE_TEST(test_continue_execution_4)
319 {
320 	static int ret;
321 
322 	ret = return_zero();
323 
324 	_SEH2_TRY
325 	{
326 		RaiseException(0xE00DEAD0, 0, 0, NULL);
327 		ret = return_positive();
328 	}
329 	_SEH2_EXCEPT(return_negative())
330 	{
331 		ret = return_zero();
332 	}
333 	_SEH2_END;
334 
335 	return ret == return_positive();
336 }
337 //}}}
338 
339 /* Dynamic exception filters, using _SEH2_GetExceptionInformation() *///{{{
340 DEFINE_TEST(test_execute_handler_5)
341 {
342 	static int ret;
343 
344 	ret = return_zero();
345 
346 	_SEH2_TRY
347 	{
348 		RaiseException(0xE00DEAD0, 0, 0, NULL);
349 		ret = return_zero();
350 	}
351 	_SEH2_EXCEPT(return_one_2(_SEH2_GetExceptionInformation()))
352 	{
353 		ret = return_positive();
354 	}
355 	_SEH2_END;
356 
357 	return ret == return_positive();
358 }
359 
360 DEFINE_TEST(test_continue_execution_5)
361 {
362 	static int ret;
363 
364 	ret = return_zero();
365 
366 	_SEH2_TRY
367 	{
368 		RaiseException(0xE00DEAD0, 0, 0, NULL);
369 		ret = return_positive();
370 	}
371 	_SEH2_EXCEPT(return_minusone_2(_SEH2_GetExceptionInformation()))
372 	{
373 		ret = return_zero();
374 	}
375 	_SEH2_END;
376 
377 	return ret == return_positive();
378 }
379 
380 DEFINE_TEST(test_continue_search_3)
381 {
382 	static int ret;
383 
384 	ret = return_positive();
385 
386 	_SEH2_TRY
387 	{
388 		_SEH2_TRY
389 		{
390 			RaiseException(0xE00DEAD0, 0, 0, NULL);
391 			ret = return_zero();
392 		}
393 		_SEH2_EXCEPT(return_zero_2(_SEH2_GetExceptionInformation()))
394 		{
395 			ret = return_zero();
396 		}
397 		_SEH2_END;
398 	}
399 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
400 	{
401 		ret = return_arg(ret);
402 	}
403 	_SEH2_END;
404 
405 	return ret == return_positive();
406 }
407 
408 DEFINE_TEST(test_execute_handler_6)
409 {
410 	static int ret;
411 
412 	ret = return_zero();
413 
414 	_SEH2_TRY
415 	{
416 		RaiseException(0xE00DEAD0, 0, 0, NULL);
417 		ret = return_zero();
418 	}
419 	_SEH2_EXCEPT(return_positive_2(_SEH2_GetExceptionInformation()))
420 	{
421 		ret = return_positive();
422 	}
423 	_SEH2_END;
424 
425 	return ret == return_positive();
426 }
427 
428 DEFINE_TEST(test_continue_execution_6)
429 {
430 	static int ret;
431 
432 	ret = return_zero();
433 
434 	_SEH2_TRY
435 	{
436 		RaiseException(0xE00DEAD0, 0, 0, NULL);
437 		ret = return_positive();
438 	}
439 	_SEH2_EXCEPT(return_negative_2(_SEH2_GetExceptionInformation()))
440 	{
441 		ret = return_zero();
442 	}
443 	_SEH2_END;
444 
445 	return ret == return_positive();
446 }
447 //}}}
448 
449 /* Dynamic exception filters, using _SEH2_GetExceptionCode() *///{{{
450 DEFINE_TEST(test_execute_handler_7)
451 {
452 	static int ret;
453 
454 	ret = return_zero();
455 
456 	_SEH2_TRY
457 	{
458 		RaiseException(0xE00DEAD0, 0, 0, NULL);
459 		ret = return_zero();
460 	}
461 	_SEH2_EXCEPT(return_one_3(_SEH2_GetExceptionCode()))
462 	{
463 		ret = return_positive();
464 	}
465 	_SEH2_END;
466 
467 	return ret == return_positive();
468 }
469 
470 DEFINE_TEST(test_continue_execution_7)
471 {
472 	static int ret;
473 
474 	ret = return_zero();
475 
476 	_SEH2_TRY
477 	{
478 		RaiseException(0xE00DEAD0, 0, 0, NULL);
479 		ret = return_positive();
480 	}
481 	_SEH2_EXCEPT(return_minusone_3(_SEH2_GetExceptionCode()))
482 	{
483 		ret = return_zero();
484 	}
485 	_SEH2_END;
486 
487 	return ret == return_positive();
488 }
489 
490 DEFINE_TEST(test_continue_search_4)
491 {
492 	static int ret;
493 
494 	ret = return_zero();
495 
496 	_SEH2_TRY
497 	{
498 		_SEH2_TRY
499 		{
500 			RaiseException(0xE00DEAD0, 0, 0, NULL);
501 			ret = return_zero();
502 		}
503 		_SEH2_EXCEPT(return_zero_3(_SEH2_GetExceptionCode()))
504 		{
505 			ret = return_zero();
506 		}
507 		_SEH2_END;
508 	}
509 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
510 	{
511 		ret = return_positive();
512 	}
513 	_SEH2_END;
514 
515 	return ret == return_positive();
516 }
517 
518 DEFINE_TEST(test_execute_handler_8)
519 {
520 	static int ret;
521 
522 	ret = return_zero();
523 
524 	_SEH2_TRY
525 	{
526 		RaiseException(0xE00DEAD0, 0, 0, NULL);
527 		ret = return_zero();
528 	}
529 	_SEH2_EXCEPT(return_positive_3(_SEH2_GetExceptionCode()))
530 	{
531 		ret = return_positive();
532 	}
533 	_SEH2_END;
534 
535 	return ret == return_positive();
536 }
537 
538 DEFINE_TEST(test_continue_execution_8)
539 {
540 	static int ret;
541 
542 	ret = return_zero();
543 
544 	_SEH2_TRY
545 	{
546 		RaiseException(0xE00DEAD0, 0, 0, NULL);
547 		ret = return_positive();
548 	}
549 	_SEH2_EXCEPT(return_negative_3(_SEH2_GetExceptionCode()))
550 	{
551 		ret = return_zero();
552 	}
553 	_SEH2_END;
554 
555 	return ret == return_positive();
556 }
557 //}}}
558 
559 /* Dynamic exception filters, using _SEH2_GetExceptionInformation() and _SEH2_GetExceptionCode() *///{{{
560 DEFINE_TEST(test_execute_handler_9)
561 {
562 	static int ret;
563 
564 	ret = return_zero();
565 
566 	_SEH2_TRY
567 	{
568 		RaiseException(0xE00DEAD0, 0, 0, NULL);
569 		ret = return_zero();
570 	}
571 	_SEH2_EXCEPT(return_one_4(_SEH2_GetExceptionInformation(), _SEH2_GetExceptionCode()))
572 	{
573 		ret = return_positive();
574 	}
575 	_SEH2_END;
576 
577 	return ret == return_positive();
578 }
579 
580 DEFINE_TEST(test_continue_execution_9)
581 {
582 	static int ret;
583 
584 	ret = return_zero();
585 
586 	_SEH2_TRY
587 	{
588 		RaiseException(0xE00DEAD0, 0, 0, NULL);
589 		ret = return_positive();
590 	}
591 	_SEH2_EXCEPT(return_minusone_4(_SEH2_GetExceptionInformation(), _SEH2_GetExceptionCode()))
592 	{
593 		ret = return_zero();
594 	}
595 	_SEH2_END;
596 
597 	return ret == return_positive();
598 }
599 
600 DEFINE_TEST(test_continue_search_5)
601 {
602 	static int ret;
603 
604 	ret = return_zero();
605 
606 	_SEH2_TRY
607 	{
608 		_SEH2_TRY
609 		{
610 			RaiseException(0xE00DEAD0, 0, 0, NULL);
611 			ret = return_zero();
612 		}
613 		_SEH2_EXCEPT(return_zero_4(_SEH2_GetExceptionInformation(), _SEH2_GetExceptionCode()))
614 		{
615 			ret = return_zero();
616 		}
617 		_SEH2_END;
618 	}
619 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
620 	{
621 		ret = return_positive();
622 	}
623 	_SEH2_END;
624 
625 	return ret == return_positive();
626 }
627 
628 DEFINE_TEST(test_execute_handler_10)
629 {
630 	static int ret;
631 
632 	ret = return_zero();
633 
634 	_SEH2_TRY
635 	{
636 		RaiseException(0xE00DEAD0, 0, 0, NULL);
637 		ret = return_zero();
638 	}
639 	_SEH2_EXCEPT(return_positive_4(_SEH2_GetExceptionInformation(), _SEH2_GetExceptionCode()))
640 	{
641 		ret = return_positive();
642 	}
643 	_SEH2_END;
644 
645 	return ret == return_positive();
646 }
647 
648 DEFINE_TEST(test_continue_execution_10)
649 {
650 	static int ret;
651 
652 	ret = return_zero();
653 
654 	_SEH2_TRY
655 	{
656 		RaiseException(0xE00DEAD0, 0, 0, NULL);
657 		ret = return_positive();
658 	}
659 	_SEH2_EXCEPT(return_negative_4(_SEH2_GetExceptionInformation(), _SEH2_GetExceptionCode()))
660 	{
661 		ret = return_zero();
662 	}
663 	_SEH2_END;
664 
665 	return ret == return_positive();
666 }
667 //}}}
668 
669 /* Constant exception filters with side effects *///{{{
670 DEFINE_TEST(test_execute_handler_11)
671 {
672 	static int ret;
673 
674 	ret = return_zero();
675 
676 	_SEH2_TRY
677 	{
678 		RaiseException(0xE00DEAD0, 0, 0, NULL);
679 		ret = return_zero();
680 	}
681 	_SEH2_EXCEPT(set_positive(&ret), EXCEPTION_EXECUTE_HANDLER)
682 	{
683 		ret = ret ? return_positive() : return_zero();
684 	}
685 	_SEH2_END;
686 
687 	return ret == return_positive();
688 }
689 
690 DEFINE_TEST(test_continue_execution_11)
691 {
692 	static int ret;
693 
694 	ret = return_zero();
695 
696 	_SEH2_TRY
697 	{
698 		RaiseException(0xE00DEAD0, 0, 0, NULL);
699 		ret = ret ? return_positive() : return_zero();
700 	}
701 	_SEH2_EXCEPT(set_positive(&ret), EXCEPTION_CONTINUE_EXECUTION)
702 	{
703 		ret = return_zero();
704 	}
705 	_SEH2_END;
706 
707 	return ret == return_positive();
708 }
709 
710 DEFINE_TEST(test_continue_search_6)
711 {
712 	static int ret;
713 	static int ret2;
714 
715 	ret = return_zero();
716 	ret2 = return_zero();
717 
718 	_SEH2_TRY
719 	{
720 		_SEH2_TRY
721 		{
722 			RaiseException(0xE00DEAD0, 0, 0, NULL);
723 			ret = return_zero();
724 			ret2 = return_zero();
725 		}
726 		_SEH2_EXCEPT(set_positive(&ret), EXCEPTION_CONTINUE_SEARCH)
727 		{
728 			ret = return_zero();
729 			ret2 = return_zero();
730 		}
731 		_SEH2_END;
732 	}
733 	_SEH2_EXCEPT(set_positive(&ret2), EXCEPTION_EXECUTE_HANDLER)
734 	{
735 		ret = return_arg(ret);
736 		ret2 = return_arg(ret2);
737 	}
738 	_SEH2_END;
739 
740 	return ret == return_positive() && ret2 == return_positive();
741 }
742 
743 DEFINE_TEST(test_execute_handler_12)
744 {
745 	static int ret;
746 
747 	ret = return_zero();
748 
749 	_SEH2_TRY
750 	{
751 		RaiseException(0xE00DEAD0, 0, 0, NULL);
752 		ret = return_zero();
753 	}
754 	_SEH2_EXCEPT(set_positive(&ret), 12345)
755 	{
756 		ret = return_arg(ret);
757 	}
758 	_SEH2_END;
759 
760 	return ret == return_positive();
761 }
762 
763 DEFINE_TEST(test_continue_execution_12)
764 {
765 	static int ret;
766 
767 	ret = return_zero();
768 
769 	_SEH2_TRY
770 	{
771 		RaiseException(0xE00DEAD0, 0, 0, NULL);
772 		ret = return_arg(ret);
773 	}
774 	_SEH2_EXCEPT(set_positive(&ret), -12345)
775 	{
776 		ret = return_zero();
777 	}
778 	_SEH2_END;
779 
780 	return ret == return_positive();
781 }
782 //}}}
783 
784 /* _SEH2_LEAVE *///{{{
785 DEFINE_TEST(test_leave_1)
786 {
787 	static int ret;
788 
789 	ret = return_zero();
790 
791 	_SEH2_TRY
792 	{
793 		ret = return_positive();
794 		_SEH2_LEAVE;
795 		ret = return_zero();
796 	}
797 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
798 	{
799 		ret = return_zero();
800 	}
801 	_SEH2_END;
802 
803 	return ret == return_positive();
804 }
805 
806 DEFINE_TEST(test_leave_2)
807 {
808 	static int ret;
809 
810 	ret = return_zero();
811 
812 	_SEH2_TRY
813 	{
814 		ret = return_positive();
815 		_SEH2_LEAVE;
816 
817 		RaiseException(0xE00DEAD0, 0, 0, NULL);
818 		ret = return_zero();
819 	}
820 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
821 	{
822 		ret = return_zero();
823 	}
824 	_SEH2_END;
825 
826 	return ret == return_positive();
827 }
828 
829 DEFINE_TEST(test_leave_3)
830 {
831 	static int ret;
832 
833 	ret = return_zero();
834 
835 	_SEH2_TRY
836 	{
837 		ret = return_positive();
838 
839 		if(return_one())
840 			_SEH2_LEAVE;
841 
842 		ret = return_zero();
843 	}
844 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
845 	{
846 		ret = return_zero();
847 	}
848 	_SEH2_END;
849 
850 	return ret == return_positive();
851 }
852 
853 DEFINE_TEST(test_leave_4)
854 {
855 	static int ret;
856 
857 	ret = return_zero();
858 
859 	_SEH2_TRY
860 	{
861 		int i;
862 		int n = return_one() + return_one();
863 
864 		for(i = return_zero(); i < n; ++ i)
865 		{
866 			if(i == return_one())
867 			{
868 				ret = return_positive();
869 				_SEH2_LEAVE;
870 			}
871 		}
872 
873 		ret = return_zero();
874 	}
875 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
876 	{
877 		ret = return_zero();
878 	}
879 	_SEH2_END;
880 
881 	return ret == return_positive();
882 }
883 
884 DEFINE_TEST(test_leave_5)
885 {
886 	static int ret;
887 
888 	ret = return_zero();
889 
890 	_SEH2_TRY
891 	{
892 		switch(return_one())
893 		{
894 		case 0: ret = return_zero();
895 		case 1: ret = return_positive(); _SEH2_LEAVE;
896 		case 2: ret = return_zero();
897 		}
898 
899 		ret = return_zero();
900 	}
901 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
902 	{
903 		ret = return_zero();
904 	}
905 	_SEH2_END;
906 
907 	return ret == return_positive();
908 }
909 
910 DEFINE_TEST(test_leave_6)
911 {
912 	static int ret;
913 
914 	ret = return_zero();
915 
916 	_SEH2_TRY
917 	{
918 		_SEH2_TRY
919 		{
920 			_SEH2_LEAVE;
921 		}
922 		_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
923 		{
924 			ret = return_zero();
925 		}
926 		_SEH2_END;
927 
928 		ret = return_positive();
929 	}
930 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
931 	{
932 		ret = return_zero();
933 	}
934 	_SEH2_END;
935 
936 	return ret == return_positive();
937 }
938 //}}}
939 
940 /* _SEH2_YIELD() *///{{{
941 static
942 int test_yield_1_helper(void)
943 {
944 	_SEH2_TRY
945 	{
946 		_SEH2_YIELD(return return_positive());
947 	}
948 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
949 	{
950 		_SEH2_YIELD(return return_zero());
951 	}
952 	_SEH2_END;
953 
954 	return return_zero();
955 }
956 
957 DEFINE_TEST(test_yield_1)
958 {
959 	return test_yield_1_helper() == return_positive();
960 }
961 
962 static
963 int test_yield_2_helper(void)
964 {
965 	_SEH2_TRY
966 	{
967 		RaiseException(0xE00DEAD0, 0, 0, NULL);
968 		_SEH2_YIELD(return return_zero());
969 	}
970 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
971 	{
972 		_SEH2_YIELD(return return_positive());
973 	}
974 	_SEH2_END;
975 
976 	return return_zero();
977 }
978 
979 DEFINE_TEST(test_yield_2)
980 {
981 	return test_yield_2_helper() == return_positive();
982 }
983 
984 static
985 int test_yield_3_helper(void)
986 {
987 	_SEH2_TRY
988 	{
989 		_SEH2_TRY
990 		{
991 			_SEH2_YIELD(return return_positive());
992 		}
993 		_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
994 		{
995 			_SEH2_YIELD(return return_zero());
996 		}
997 		_SEH2_END;
998 
999 		_SEH2_YIELD(return return_zero());
1000 	}
1001 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1002 	{
1003 		_SEH2_YIELD(return return_zero());
1004 	}
1005 	_SEH2_END;
1006 
1007 	return return_zero();
1008 }
1009 
1010 DEFINE_TEST(test_yield_3)
1011 {
1012 	return test_yield_3_helper() == return_positive();
1013 }
1014 
1015 static
1016 int test_yield_4_helper(void)
1017 {
1018 	_SEH2_TRY
1019 	{
1020 		_SEH2_TRY
1021 		{
1022 			RaiseException(0xE00DEAD0, 0, 0, NULL);
1023 			_SEH2_YIELD(return return_zero());
1024 		}
1025 		_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1026 		{
1027 			_SEH2_YIELD(return return_positive());
1028 		}
1029 		_SEH2_END;
1030 
1031 		_SEH2_YIELD(return return_zero());
1032 	}
1033 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1034 	{
1035 		_SEH2_YIELD(return return_zero());
1036 	}
1037 	_SEH2_END;
1038 
1039 	return return_zero();
1040 }
1041 
1042 DEFINE_TEST(test_yield_4)
1043 {
1044 	return test_yield_4_helper() == return_positive();
1045 }
1046 
1047 static int test_yield_5_ret;
1048 
1049 static
1050 int test_yield_5_helper(void)
1051 {
1052 	test_yield_5_ret = return_zero();
1053 
1054 	_SEH2_TRY
1055 	{
1056 		_SEH2_YIELD(return return_positive());
1057 	}
1058 	_SEH2_FINALLY
1059 	{
1060 		test_yield_5_ret = return_positive();
1061 	}
1062 	_SEH2_END;
1063 
1064 	return return_zero();
1065 }
1066 
1067 DEFINE_TEST(test_yield_5)
1068 {
1069 	return test_yield_5_helper() == return_positive() && test_yield_5_ret == return_positive();
1070 }
1071 
1072 int test_yield_6_ret;
1073 
1074 static
1075 int test_yield_6_helper(void)
1076 {
1077 	test_yield_6_ret = return_zero();
1078 
1079 	_SEH2_TRY
1080 	{
1081 		_SEH2_TRY
1082 		{
1083 			_SEH2_YIELD(return return_positive());
1084 		}
1085 		_SEH2_FINALLY
1086 		{
1087 			test_yield_6_ret = return_positive();
1088 		}
1089 		_SEH2_END;
1090 	}
1091 	_SEH2_FINALLY
1092 	{
1093 		test_yield_6_ret += return_one();
1094 	}
1095 	_SEH2_END;
1096 
1097 	return return_zero();
1098 }
1099 
1100 DEFINE_TEST(test_yield_6)
1101 {
1102 	return test_yield_6_helper() == return_positive() && test_yield_6_ret == return_positive() + return_one();
1103 }
1104 //}}}
1105 
1106 /* Termination blocks *///{{{
1107 DEFINE_TEST(test_finally_1)
1108 {
1109 	static int ret;
1110 
1111 	ret = return_zero();
1112 
1113 	_SEH2_TRY
1114 	{
1115 		ret = return_arg(ret);
1116 	}
1117 	_SEH2_FINALLY
1118 	{
1119 		ret = return_positive();
1120 	}
1121 	_SEH2_END;
1122 
1123 	return ret == return_positive();
1124 }
1125 
1126 DEFINE_TEST(test_finally_2)
1127 {
1128 	static int ret;
1129 
1130 	ret = return_zero();
1131 
1132 	_SEH2_TRY
1133 	{
1134 		ret = return_arg(ret);
1135 		_SEH2_LEAVE;
1136 	}
1137 	_SEH2_FINALLY
1138 	{
1139 		ret = return_positive();
1140 	}
1141 	_SEH2_END;
1142 
1143 	return ret == return_positive();
1144 }
1145 
1146 DEFINE_TEST(test_finally_3)
1147 {
1148 	static int ret;
1149 
1150 	ret = return_zero();
1151 
1152 	_SEH2_TRY
1153 	{
1154 		ret = return_arg(ret);
1155 		_SEH2_YIELD(goto leave);
1156 	}
1157 	_SEH2_FINALLY
1158 	{
1159 		ret = return_positive();
1160 	}
1161 	_SEH2_END;
1162 
1163 leave:
1164 	return ret == return_positive();
1165 }
1166 
1167 static int test_finally_4_ret;
1168 
1169 static int test_finally_4_helper(void)
1170 {
1171 	test_finally_4_ret = return_zero();
1172 
1173 	_SEH2_TRY
1174 	{
1175 		test_finally_4_ret = return_arg(test_finally_4_ret);
1176 		_SEH2_YIELD(return return_positive());
1177 	}
1178 	_SEH2_FINALLY
1179 	{
1180 		test_finally_4_ret = return_positive();
1181 	}
1182 	_SEH2_END;
1183 
1184 	return return_zero();
1185 }
1186 
1187 DEFINE_TEST(test_finally_4)
1188 {
1189 	return test_finally_4_helper() == return_positive() && test_finally_4_ret;
1190 }
1191 
1192 DEFINE_TEST(test_finally_5)
1193 {
1194 	static int ret;
1195 
1196 	ret = return_zero();
1197 
1198 	_SEH2_TRY
1199 	{
1200 		_SEH2_TRY
1201 		{
1202 			RaiseException(0xE00DEAD0, 0, 0, NULL);
1203 			ret = return_zero();
1204 		}
1205 		_SEH2_FINALLY
1206 		{
1207 			ret = return_positive();
1208 		}
1209 		_SEH2_END;
1210 	}
1211 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1212 	{
1213 		ret = return_arg(ret);
1214 	}
1215 	_SEH2_END;
1216 
1217 	return ret == return_positive();
1218 }
1219 
1220 DEFINE_TEST(test_finally_6)
1221 {
1222 	static int ret;
1223 
1224 	ret = return_zero();
1225 
1226 	_SEH2_TRY
1227 	{
1228 		_SEH2_TRY
1229 		{
1230 			ret = return_arg(ret);
1231 		}
1232 		_SEH2_FINALLY
1233 		{
1234 			if(ret == return_zero())
1235 				ret = return_positive();
1236 		}
1237 		_SEH2_END;
1238 	}
1239 	_SEH2_FINALLY
1240 	{
1241 		if(ret == return_positive())
1242 			ret = return_positive() + return_one();
1243 	}
1244 	_SEH2_END;
1245 
1246 	return ret == return_positive() + return_one();
1247 }
1248 
1249 DEFINE_TEST(test_finally_7)
1250 {
1251 	static int ret;
1252 
1253 	ret = return_zero();
1254 
1255 	_SEH2_TRY
1256 	{
1257 		_SEH2_TRY
1258 		{
1259 			ret = return_arg(ret);
1260 			_SEH2_LEAVE;
1261 		}
1262 		_SEH2_FINALLY
1263 		{
1264 			if(ret == return_zero())
1265 				ret = return_positive();
1266 		}
1267 		_SEH2_END;
1268 	}
1269 	_SEH2_FINALLY
1270 	{
1271 		if(ret == return_positive())
1272 			ret = return_positive() + return_one();
1273 	}
1274 	_SEH2_END;
1275 
1276 	return ret == return_positive() + return_one();
1277 }
1278 
1279 DEFINE_TEST(test_finally_8)
1280 {
1281 	static int ret;
1282 
1283 	ret = return_zero();
1284 
1285 	_SEH2_TRY
1286 	{
1287 		_SEH2_TRY
1288 		{
1289 			ret = return_arg(ret);
1290 			_SEH2_YIELD(goto leave);
1291 		}
1292 		_SEH2_FINALLY
1293 		{
1294 			if(ret == return_zero())
1295 				ret = return_positive();
1296 		}
1297 		_SEH2_END;
1298 	}
1299 	_SEH2_FINALLY
1300 	{
1301 		if(ret == return_positive())
1302 			ret = return_positive() + return_one();
1303 	}
1304 	_SEH2_END;
1305 
1306 leave:
1307 	return ret == return_positive() + return_one();
1308 }
1309 
1310 static int test_finally_9_ret;
1311 
1312 static int test_finally_9_helper(void)
1313 {
1314 	test_finally_9_ret = return_zero();
1315 
1316 	_SEH2_TRY
1317 	{
1318 		_SEH2_TRY
1319 		{
1320 			test_finally_9_ret = return_arg(test_finally_9_ret);
1321 			_SEH2_YIELD(return return_positive());
1322 		}
1323 		_SEH2_FINALLY
1324 		{
1325 			if(test_finally_9_ret == return_zero())
1326 				test_finally_9_ret = return_positive();
1327 		}
1328 		_SEH2_END;
1329 	}
1330 	_SEH2_FINALLY
1331 	{
1332 		if(test_finally_9_ret == return_positive())
1333 			test_finally_9_ret = return_positive() + return_one();
1334 	}
1335 	_SEH2_END;
1336 
1337 	return return_zero();
1338 }
1339 
1340 DEFINE_TEST(test_finally_9)
1341 {
1342 	return test_finally_9_helper() == return_positive() && test_finally_9_ret == return_positive() + return_one();
1343 }
1344 
1345 DEFINE_TEST(test_finally_10)
1346 {
1347 	static int ret;
1348 
1349 	ret = return_zero();
1350 
1351 	_SEH2_TRY
1352 	{
1353 		_SEH2_TRY
1354 		{
1355 			_SEH2_TRY
1356 			{
1357 				RaiseException(0xE00DEAD0, 0, 0, NULL);
1358 				ret = return_zero();
1359 			}
1360 			_SEH2_FINALLY
1361 			{
1362 				if(ret == return_zero())
1363 					ret = return_positive();
1364 			}
1365 			_SEH2_END;
1366 		}
1367 		_SEH2_FINALLY
1368 		{
1369 			if(ret == return_positive())
1370 				ret = return_positive() + return_one();
1371 		}
1372 		_SEH2_END;
1373 	}
1374 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1375 	{
1376 		ret = return_arg(ret);
1377 	}
1378 	_SEH2_END;
1379 
1380 	return ret == return_positive() + return_one();
1381 }
1382 
1383 DEFINE_TEST(test_finally_11)
1384 {
1385 	static int ret;
1386 
1387 	ret = return_zero();
1388 
1389 	_SEH2_TRY
1390 	{
1391 		_SEH2_TRY
1392 		{
1393 			_SEH2_TRY
1394 			{
1395 				ret = return_arg(ret);
1396 			}
1397 			_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1398 			{
1399 				ret = return_zero();
1400 			}
1401 			_SEH2_END;
1402 		}
1403 		_SEH2_FINALLY
1404 		{
1405 			ret = return_positive();
1406 			RaiseException(0xE00DEAD0, 0, 0, NULL);
1407 			ret = return_zero();
1408 		}
1409 		_SEH2_END;
1410 	}
1411 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1412 	{
1413 		if(ret == return_positive())
1414 			ret += return_one();
1415 	}
1416 	_SEH2_END;
1417 
1418 	return ret == return_positive() + return_one();
1419 }
1420 
1421 DEFINE_TEST(test_finally_12)
1422 {
1423 	static int ret;
1424 
1425 	ret = return_zero();
1426 
1427 	_SEH2_TRY
1428 	{
1429 		_SEH2_TRY
1430 		{
1431 			_SEH2_TRY
1432 			{
1433 				ret = return_arg(ret);
1434 			}
1435 			_SEH2_FINALLY
1436 			{
1437 				ret = return_positive();
1438 				RaiseException(0xE00DEAD0, 0, 0, NULL);
1439 				ret = return_zero();
1440 			}
1441 			_SEH2_END;
1442 		}
1443 		_SEH2_FINALLY
1444 		{
1445 			if(ret == return_positive())
1446 				ret += return_one();
1447 		}
1448 		_SEH2_END;
1449 	}
1450 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1451 	{
1452 		if(ret == return_positive() + return_one())
1453 			ret += return_one();
1454 	}
1455 	_SEH2_END;
1456 
1457 	return ret == return_positive() + return_one() + return_one();
1458 }
1459 
1460 static int test_finally_13_ret;
1461 
1462 static
1463 void test_finally_13_helper(void)
1464 {
1465 	test_finally_13_ret = return_zero();
1466 
1467 	_SEH2_TRY
1468 	{
1469 		_SEH2_TRY
1470 		{
1471 			test_finally_13_ret = return_positive();
1472 			_SEH2_YIELD(return);
1473 			test_finally_13_ret = return_zero();
1474 		}
1475 		_SEH2_FINALLY
1476 		{
1477 			if(test_finally_13_ret == return_positive())
1478 				test_finally_13_ret += return_one();
1479 		}
1480 		_SEH2_END;
1481 	}
1482 	_SEH2_FINALLY
1483 	{
1484 		if(test_finally_13_ret == return_positive() + return_one())
1485 			test_finally_13_ret += return_one();
1486 
1487 		RaiseException(0xE00DEAD0, 0, 0, NULL);
1488 		test_finally_13_ret = return_zero();
1489 	}
1490 	_SEH2_END;
1491 
1492 	test_finally_13_ret = return_zero();
1493 }
1494 
1495 DEFINE_TEST(test_finally_13)
1496 {
1497 	static int ret;
1498 
1499 	ret = return_zero();
1500 
1501 	_SEH2_TRY
1502 	{
1503 		ret = return_arg(ret);
1504 		test_finally_13_helper();
1505 		ret = return_zero();
1506 	}
1507 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1508 	{
1509 		ret = return_positive();
1510 	}
1511 	_SEH2_END;
1512 
1513 	return ret == return_positive() && test_finally_13_ret == return_positive() + return_one() + return_one();
1514 }
1515 
1516 static int test_finally_14_ret;
1517 
1518 static
1519 void test_finally_14_helper(void)
1520 {
1521 	test_finally_14_ret = return_zero();
1522 
1523 	_SEH2_TRY
1524 	{
1525 		_SEH2_TRY
1526 		{
1527 			_SEH2_TRY
1528 			{
1529 				test_finally_14_ret = return_positive();
1530 				RaiseException(0xE00DEAD0, 0, 0, NULL);
1531 				test_finally_14_ret = return_zero();
1532 			}
1533 			_SEH2_FINALLY
1534 			{
1535 				if(test_finally_14_ret == return_positive())
1536 					test_finally_14_ret += return_one();
1537 			}
1538 			_SEH2_END;
1539 		}
1540 		_SEH2_FINALLY
1541 		{
1542 			if(test_finally_14_ret == return_positive() + return_one())
1543 				test_finally_14_ret += return_one();
1544 
1545 			RaiseException(0xE00DEAD0, 0, 0, NULL);
1546 			test_finally_14_ret = return_zero();
1547 		}
1548 		_SEH2_END;
1549 	}
1550 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1551 	{
1552 		if(test_finally_14_ret == return_positive() + return_one() + return_one())
1553 			test_finally_14_ret += return_one();
1554 	}
1555 	_SEH2_END;
1556 
1557 	test_finally_14_ret = return_arg(test_finally_14_ret);
1558 }
1559 
1560 DEFINE_TEST(test_finally_14)
1561 {
1562 	static int ret;
1563 
1564 	ret = return_zero();
1565 
1566 	_SEH2_TRY
1567 	{
1568 		ret = return_arg(ret);
1569 		test_finally_14_helper();
1570 		ret = return_positive();
1571 	}
1572 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1573 	{
1574 		ret = return_zero();
1575 	}
1576 	_SEH2_END;
1577 
1578 	return ret == return_positive() && test_finally_14_ret == return_positive() + return_one() + return_one() + return_one();
1579 }
1580 //}}}
1581 
1582 /* _SEH2_GetExceptionInformation() *///{{{
1583 static
1584 int verify_xpointers(struct _EXCEPTION_POINTERS * ep, DWORD code, DWORD flags, DWORD argc, const ULONG_PTR * argv, int * ret, int filter)
1585 {
1586 	*ret =
1587 		ep &&
1588 		ep->ExceptionRecord &&
1589 		ep->ContextRecord &&
1590 		ep->ExceptionRecord->ExceptionCode == code &&
1591 		ep->ExceptionRecord->ExceptionFlags == flags &&
1592 		ep->ExceptionRecord->NumberParameters == argc &&
1593 		(argv || !argc) &&
1594 		memcmp(ep->ExceptionRecord->ExceptionInformation, argv, sizeof(argv[0]) * argc) == 0;
1595 
1596 	if(*ret)
1597 		*ret = return_positive();
1598 
1599 	return filter;
1600 }
1601 
1602 DEFINE_TEST(test_xpointers_1)
1603 {
1604 	static int ret;
1605 
1606 	ret = return_zero();
1607 
1608 	_SEH2_TRY
1609 	{
1610 		RaiseException(0xE00DEAD0, 0, 0, NULL);
1611 	}
1612 	_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, 0, 0, NULL, &ret, EXCEPTION_EXECUTE_HANDLER))
1613 	{
1614 		ret = return_arg(ret);
1615 	}
1616 	_SEH2_END;
1617 
1618 	return ret == return_positive();
1619 }
1620 
1621 DEFINE_TEST(test_xpointers_2)
1622 {
1623 	static int ret;
1624 
1625 	ret = return_zero();
1626 
1627 	_SEH2_TRY
1628 	{
1629 		RaiseException(0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 0, NULL);
1630 	}
1631 	_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 0, NULL, &ret, EXCEPTION_EXECUTE_HANDLER))
1632 	{
1633 		ret = return_arg(ret);
1634 	}
1635 	_SEH2_END;
1636 
1637 	return ret == return_positive();
1638 }
1639 
1640 DEFINE_TEST(test_xpointers_3)
1641 {
1642 	static int ret;
1643 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1644 
1645 	ret = return_zero();
1646 
1647 	_SEH2_TRY
1648 	{
1649 		RaiseException(0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 0, args);
1650 	}
1651 	_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 0, args, &ret, EXCEPTION_EXECUTE_HANDLER))
1652 	{
1653 		ret = return_arg(ret);
1654 	}
1655 	_SEH2_END;
1656 
1657 	return ret == return_positive();
1658 }
1659 
1660 DEFINE_TEST(test_xpointers_4)
1661 {
1662 	static int ret;
1663 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1664 
1665 	ret = return_zero();
1666 
1667 	_SEH2_TRY
1668 	{
1669 		RaiseException(0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 1, args);
1670 	}
1671 	_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 1, args, &ret, EXCEPTION_EXECUTE_HANDLER))
1672 	{
1673 		ret = return_arg(ret);
1674 	}
1675 	_SEH2_END;
1676 
1677 	return ret == return_positive();
1678 }
1679 
1680 DEFINE_TEST(test_xpointers_5)
1681 {
1682 	static int ret;
1683 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1684 
1685 	ret = return_zero();
1686 
1687 	_SEH2_TRY
1688 	{
1689 		RaiseException(0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 2, args);
1690 	}
1691 	_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 2, args, &ret, EXCEPTION_EXECUTE_HANDLER))
1692 	{
1693 		ret = return_arg(ret);
1694 	}
1695 	_SEH2_END;
1696 
1697 	return ret == return_positive();
1698 }
1699 
1700 DEFINE_TEST(test_xpointers_6)
1701 {
1702 	static int ret;
1703 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1704 
1705 	ret = return_zero();
1706 
1707 	_SEH2_TRY
1708 	{
1709 		RaiseException(0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 3, args);
1710 	}
1711 	_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 3, args, &ret, EXCEPTION_EXECUTE_HANDLER))
1712 	{
1713 		ret = return_arg(ret);
1714 	}
1715 	_SEH2_END;
1716 
1717 	return ret == return_positive();
1718 }
1719 
1720 DEFINE_TEST(test_xpointers_7)
1721 {
1722 	static int ret;
1723 
1724 	ret = return_zero();
1725 
1726 	_SEH2_TRY
1727 	{
1728 		RaiseException(0xE00DEAD0, 0, 0, NULL);
1729 		ret = return_arg(ret);
1730 	}
1731 	_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, 0, 0, NULL, &ret, EXCEPTION_CONTINUE_EXECUTION))
1732 	{
1733 		ret = return_zero();
1734 	}
1735 	_SEH2_END;
1736 
1737 	return ret == return_positive();
1738 }
1739 
1740 DEFINE_TEST(test_xpointers_8)
1741 {
1742 	static int ret;
1743 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1744 
1745 	ret = return_zero();
1746 
1747 	_SEH2_TRY
1748 	{
1749 		RaiseException(0xE00DEAD0, 0, 0, args);
1750 		ret = return_arg(ret);
1751 	}
1752 	_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, 0, 0, args, &ret, EXCEPTION_CONTINUE_EXECUTION))
1753 	{
1754 		ret = return_zero();
1755 	}
1756 	_SEH2_END;
1757 
1758 	return ret == return_positive();
1759 }
1760 
1761 DEFINE_TEST(test_xpointers_9)
1762 {
1763 	static int ret;
1764 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1765 
1766 	ret = return_zero();
1767 
1768 	_SEH2_TRY
1769 	{
1770 		RaiseException(0xE00DEAD0, 0, 1, args);
1771 		ret = return_arg(ret);
1772 	}
1773 	_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, 0, 1, args, &ret, EXCEPTION_CONTINUE_EXECUTION))
1774 	{
1775 		ret = return_zero();
1776 	}
1777 	_SEH2_END;
1778 
1779 	return ret == return_positive();
1780 }
1781 
1782 DEFINE_TEST(test_xpointers_10)
1783 {
1784 	static int ret;
1785 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1786 
1787 	ret = return_zero();
1788 
1789 	_SEH2_TRY
1790 	{
1791 		RaiseException(0xE00DEAD0, 0, 2, args);
1792 		ret = return_arg(ret);
1793 	}
1794 	_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, 0, 2, args, &ret, EXCEPTION_CONTINUE_EXECUTION))
1795 	{
1796 		ret = return_zero();
1797 	}
1798 	_SEH2_END;
1799 
1800 	return ret == return_positive();
1801 }
1802 
1803 DEFINE_TEST(test_xpointers_11)
1804 {
1805 	static int ret;
1806 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1807 
1808 	ret = return_zero();
1809 
1810 	_SEH2_TRY
1811 	{
1812 		RaiseException(0xE00DEAD0, 0, 3, args);
1813 		ret = return_arg(ret);
1814 	}
1815 	_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, 0, 3, args, &ret, EXCEPTION_CONTINUE_EXECUTION))
1816 	{
1817 		ret = return_zero();
1818 	}
1819 	_SEH2_END;
1820 
1821 	return ret == return_positive();
1822 }
1823 
1824 DEFINE_TEST(test_xpointers_12)
1825 {
1826 	static int ret;
1827 
1828 	ret = return_zero();
1829 
1830 	_SEH2_TRY
1831 	{
1832 		_SEH2_TRY
1833 		{
1834 			RaiseException(0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 0, NULL);
1835 		}
1836 		_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 0, NULL, &ret, EXCEPTION_CONTINUE_SEARCH))
1837 		{
1838 			ret = return_zero();
1839 		}
1840 		_SEH2_END;
1841 	}
1842 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1843 	{
1844 		ret = return_arg(ret);
1845 	}
1846 	_SEH2_END;
1847 
1848 	return ret == return_positive();
1849 }
1850 
1851 DEFINE_TEST(test_xpointers_13)
1852 {
1853 	static int ret;
1854 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1855 
1856 	ret = return_zero();
1857 
1858 	_SEH2_TRY
1859 	{
1860 		_SEH2_TRY
1861 		{
1862 			RaiseException(0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 0, args);
1863 		}
1864 		_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 0, args, &ret, EXCEPTION_CONTINUE_SEARCH))
1865 		{
1866 			ret = return_zero();
1867 		}
1868 		_SEH2_END;
1869 	}
1870 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1871 	{
1872 		ret = return_arg(ret);
1873 	}
1874 	_SEH2_END;
1875 
1876 	return ret == return_positive();
1877 }
1878 
1879 DEFINE_TEST(test_xpointers_14)
1880 {
1881 	static int ret;
1882 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1883 
1884 	ret = return_zero();
1885 
1886 	_SEH2_TRY
1887 	{
1888 		_SEH2_TRY
1889 		{
1890 			RaiseException(0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 1, args);
1891 		}
1892 		_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 1, args, &ret, EXCEPTION_CONTINUE_SEARCH))
1893 		{
1894 			ret = return_zero();
1895 		}
1896 		_SEH2_END;
1897 	}
1898 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1899 	{
1900 		ret = return_arg(ret);
1901 	}
1902 	_SEH2_END;
1903 
1904 	return ret == return_positive();
1905 }
1906 
1907 DEFINE_TEST(test_xpointers_15)
1908 {
1909 	static int ret;
1910 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1911 
1912 	ret = return_zero();
1913 
1914 	_SEH2_TRY
1915 	{
1916 		_SEH2_TRY
1917 		{
1918 			RaiseException(0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 2, args);
1919 		}
1920 		_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 2, args, &ret, EXCEPTION_CONTINUE_SEARCH))
1921 		{
1922 			ret = return_zero();
1923 		}
1924 		_SEH2_END;
1925 	}
1926 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1927 	{
1928 		ret = return_arg(ret);
1929 	}
1930 	_SEH2_END;
1931 
1932 	return ret == return_positive();
1933 }
1934 
1935 DEFINE_TEST(test_xpointers_16)
1936 {
1937 	static int ret;
1938 	static const ULONG_PTR args[] = { 1, 2, 12345 };
1939 
1940 	ret = return_zero();
1941 
1942 	_SEH2_TRY
1943 	{
1944 		_SEH2_TRY
1945 		{
1946 			RaiseException(0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 3, args);
1947 		}
1948 		_SEH2_EXCEPT(verify_xpointers(_SEH2_GetExceptionInformation(), 0xE00DEAD0, EXCEPTION_NONCONTINUABLE, 3, args, &ret, EXCEPTION_CONTINUE_SEARCH))
1949 		{
1950 			ret = return_zero();
1951 		}
1952 		_SEH2_END;
1953 	}
1954 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1955 	{
1956 		ret = return_arg(ret);
1957 	}
1958 	_SEH2_END;
1959 
1960 	return ret == return_positive();
1961 }
1962 //}}}
1963 
1964 /* _SEH2_GetExceptionCode() *///{{{
1965 static
1966 int verify_xcode(int code, int xcode, int * ret, int filter)
1967 {
1968 	*ret = code == xcode;
1969 
1970 	if(*ret)
1971 		*ret = return_positive();
1972 
1973 	return filter;
1974 }
1975 
1976 DEFINE_TEST(test_xcode_1)
1977 {
1978 	static int ret;
1979 
1980 	ret = return_zero();
1981 
1982 	_SEH2_TRY
1983 	{
1984 		RaiseException(0xE00DEAD0, 0, 0, NULL);
1985 		ret = return_zero();
1986 	}
1987 	_SEH2_EXCEPT(verify_xcode(_SEH2_GetExceptionCode(), 0xE00DEAD0, &ret, EXCEPTION_EXECUTE_HANDLER))
1988 	{
1989 		ret = return_arg(ret);
1990 	}
1991 	_SEH2_END;
1992 
1993 	return ret == return_positive();
1994 }
1995 
1996 DEFINE_TEST(test_xcode_2)
1997 {
1998 	static int ret;
1999 
2000 	ret = return_zero();
2001 
2002 	_SEH2_TRY
2003 	{
2004 		RaiseException(0xE00DEAD0, 0, 0, NULL);
2005 		ret = return_arg(ret);
2006 	}
2007 	_SEH2_EXCEPT(verify_xcode(_SEH2_GetExceptionCode(), 0xE00DEAD0, &ret, EXCEPTION_CONTINUE_EXECUTION))
2008 	{
2009 		ret = return_zero();
2010 	}
2011 	_SEH2_END;
2012 
2013 	return ret == return_positive();
2014 }
2015 
2016 DEFINE_TEST(test_xcode_3)
2017 {
2018 	static int ret;
2019 
2020 	ret = return_zero();
2021 
2022 	_SEH2_TRY
2023 	{
2024 		_SEH2_TRY
2025 		{
2026 			RaiseException(0xE00DEAD0, 0, 0, NULL);
2027 			ret = return_zero();
2028 		}
2029 		_SEH2_EXCEPT(verify_xcode(_SEH2_GetExceptionCode(), 0xE00DEAD0, &ret, EXCEPTION_CONTINUE_SEARCH))
2030 		{
2031 			ret = return_zero();
2032 		}
2033 		_SEH2_END;
2034 	}
2035 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2036 	{
2037 		ret = return_arg(ret);
2038 	}
2039 	_SEH2_END;
2040 
2041 	return ret == return_positive();
2042 }
2043 //}}}
2044 
2045 /* _SEH2_AbnormalTermination() *///{{{
2046 DEFINE_TEST(test_abnorm_1)
2047 {
2048 	static int ret;
2049 
2050 	ret = return_zero();
2051 
2052 	_SEH2_TRY
2053 	{
2054 		ret = return_arg(ret);
2055 	}
2056 	_SEH2_FINALLY
2057 	{
2058 		ret = _SEH2_AbnormalTermination() ? return_zero() : return_positive();
2059 	}
2060 	_SEH2_END;
2061 
2062 	return ret == return_positive();
2063 }
2064 
2065 DEFINE_TEST(test_abnorm_2)
2066 {
2067 	static int ret;
2068 
2069 	ret = return_zero();
2070 
2071 	_SEH2_TRY
2072 	{
2073 		_SEH2_LEAVE;
2074 	}
2075 	_SEH2_FINALLY
2076 	{
2077 		ret = _SEH2_AbnormalTermination() ? return_zero() : return_positive();
2078 	}
2079 	_SEH2_END;
2080 
2081 	return ret == return_positive();
2082 }
2083 
2084 DEFINE_TEST(test_abnorm_3)
2085 {
2086 	static int ret;
2087 
2088 	ret = return_zero();
2089 
2090 	_SEH2_TRY
2091 	{
2092 		_SEH2_YIELD(goto leave);
2093 	}
2094 	_SEH2_FINALLY
2095 	{
2096 		ret = _SEH2_AbnormalTermination() ? return_positive() : return_zero();
2097 	}
2098 	_SEH2_END;
2099 
2100 leave:
2101 	return ret == return_positive();
2102 }
2103 
2104 DEFINE_TEST(test_abnorm_4)
2105 {
2106 	static int ret;
2107 
2108 	ret = return_zero();
2109 
2110 	_SEH2_TRY
2111 	{
2112 		_SEH2_TRY
2113 		{
2114 			RaiseException(0xE00DEAD0, 0, 0, NULL);
2115 			ret = return_zero();
2116 		}
2117 		_SEH2_FINALLY
2118 		{
2119 			ret = _SEH2_AbnormalTermination() ? return_positive() : return_zero();
2120 		}
2121 		_SEH2_END;
2122 	}
2123 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2124 	{
2125 		ret = return_arg(ret);
2126 	}
2127 	_SEH2_END;
2128 
2129 	return ret == return_positive();
2130 }
2131 
2132 DEFINE_TEST(test_abnorm_5)
2133 {
2134 	static int ret;
2135 
2136 	ret = return_zero();
2137 
2138 	_SEH2_TRY
2139 	{
2140 		_SEH2_TRY
2141 		{
2142 			ret = return_arg(ret);
2143 		}
2144 		_SEH2_FINALLY
2145 		{
2146 			ret = _SEH2_AbnormalTermination() ? return_zero() : return_positive();
2147 		}
2148 		_SEH2_END;
2149 	}
2150 	_SEH2_FINALLY
2151 	{
2152 		ret = ret == return_positive() && !_SEH2_AbnormalTermination() ? return_positive() + return_one() : ret;
2153 	}
2154 	_SEH2_END;
2155 
2156 	return ret == return_positive() + return_one();
2157 }
2158 
2159 DEFINE_TEST(test_abnorm_6)
2160 {
2161 	static int ret;
2162 
2163 	ret = return_zero();
2164 
2165 	_SEH2_TRY
2166 	{
2167 		_SEH2_TRY
2168 		{
2169 			_SEH2_LEAVE;
2170 		}
2171 		_SEH2_FINALLY
2172 		{
2173 			ret = _SEH2_AbnormalTermination() ? return_zero() : return_positive();
2174 		}
2175 		_SEH2_END;
2176 	}
2177 	_SEH2_FINALLY
2178 	{
2179 		ret = ret == return_positive() && !_SEH2_AbnormalTermination() ? return_positive() + return_one() : ret;
2180 	}
2181 	_SEH2_END;
2182 
2183 	return ret == return_positive() + return_one();
2184 }
2185 
2186 DEFINE_TEST(test_abnorm_7)
2187 {
2188 	static int ret;
2189 
2190 	ret = return_zero();
2191 
2192 	_SEH2_TRY
2193 	{
2194 		_SEH2_TRY
2195 		{
2196 			_SEH2_YIELD(goto leave);
2197 		}
2198 		_SEH2_FINALLY
2199 		{
2200 			ret = _SEH2_AbnormalTermination() ? return_positive() : return_zero();
2201 		}
2202 		_SEH2_END;
2203 	}
2204 	_SEH2_FINALLY
2205 	{
2206 		ret = ret == return_positive() && _SEH2_AbnormalTermination() ? return_positive() + return_one() : ret;
2207 	}
2208 	_SEH2_END;
2209 
2210 leave:
2211 	return ret == return_positive() + return_one();
2212 }
2213 
2214 DEFINE_TEST(test_abnorm_8)
2215 {
2216 	static int ret;
2217 
2218 	ret = return_zero();
2219 
2220 	_SEH2_TRY
2221 	{
2222 		_SEH2_TRY
2223 		{
2224 			_SEH2_TRY
2225 			{
2226 				RaiseException(0xE00DEAD0, 0, 0, NULL);
2227 				ret = return_zero();
2228 			}
2229 			_SEH2_FINALLY
2230 			{
2231 				ret = _SEH2_AbnormalTermination() ? return_positive() : return_zero();
2232 			}
2233 			_SEH2_END;
2234 		}
2235 		_SEH2_FINALLY
2236 		{
2237 			ret = ret == return_positive() && _SEH2_AbnormalTermination() ? return_positive() + return_one() : ret;
2238 		}
2239 		_SEH2_END;
2240 	}
2241 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2242 	{
2243 		ret = return_arg(ret);
2244 	}
2245 	_SEH2_END;
2246 
2247 	return ret == return_positive() + return_one();
2248 }
2249 //}}}
2250 
2251 /* Use of local variables from _SEH2_EXCEPT(...) and _SEH2_FINALLY { ... } *///{{{
2252 DEFINE_TEST(test_nested_locals_1)
2253 {
2254 	int var1 = return_one();
2255 
2256 	_SEH2_TRY
2257 	{
2258 		RaiseException(0xE00DEAD0, 0, 0, 0);
2259 	}
2260 	_SEH2_EXCEPT((var1 = (var1 == return_one() ? return_positive() : var1)), EXCEPTION_EXECUTE_HANDLER)
2261 	{
2262 		if(var1 == return_positive())
2263 			var1 = return_positive() + 1;
2264 	}
2265 	_SEH2_END;
2266 
2267 	return var1 == return_positive() + 1;
2268 }
2269 
2270 DEFINE_TEST(test_nested_locals_2)
2271 {
2272 	int var1 = return_positive();
2273 
2274 	_SEH2_TRY
2275 	{
2276 	}
2277 	_SEH2_FINALLY
2278 	{
2279 		if(var1 == return_positive())
2280 			var1 = return_positive() + 1;
2281 	}
2282 	_SEH2_END;
2283 
2284 	return var1 == return_positive() + 1;
2285 }
2286 
2287 DEFINE_TEST(test_nested_locals_3)
2288 {
2289 	int var1 = return_zero();
2290 
2291 	_SEH2_TRY
2292 	{
2293 		_SEH2_TRY
2294 		{
2295 			var1 = return_one();
2296 			RaiseException(0xE00DEAD0, 0, 0, 0);
2297 		}
2298 		_SEH2_FINALLY
2299 		{
2300 			if(var1 == return_one())
2301 				var1 = return_positive();
2302 		}
2303 		_SEH2_END;
2304 	}
2305 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2306 	{
2307 		if(var1 == return_positive())
2308 			var1 = return_positive() + 1;
2309 	}
2310 	_SEH2_END;
2311 
2312 	return var1 == return_positive() + 1;
2313 }
2314 //}}}
2315 
2316 /* System support *///{{{
2317 // TODO
2318 //}}}
2319 
2320 /* CPU faults *///{{{
2321 // TODO
2322 //}}}
2323 
2324 /* Past bugs, to detect regressions *///{{{
2325 /* #4004: volatile registers clobbered when catching across frames (originally misreported) *///{{{
2326 static
2327 void test_bug_4004_helper_1(void)
2328 {
2329 	int i1, i2, i3;
2330 
2331 	i1 = return_positive();
2332 	i2 = return_positive();
2333 	i3 = return_positive();
2334 	(void)return_arg(i1 + i2 + i3);
2335 
2336 	_SEH2_TRY
2337 	{
2338 		RaiseException(0xE00DEAD0, 0, 0, NULL);
2339 	}
2340 	_SEH2_FINALLY
2341 	{
2342 	}
2343 	_SEH2_END;
2344 }
2345 
2346 static
2347 void test_bug_4004_helper_2(void)
2348 {
2349 	_SEH2_TRY
2350 	{
2351 		test_bug_4004_helper_1();
2352 	}
2353 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2354 	{
2355 	}
2356 	_SEH2_END;
2357 }
2358 
2359 DEFINE_TEST(test_bug_4004)
2360 {
2361 	int i1, i2, i3;
2362 
2363 	i1 = return_positive();
2364 	i2 = return_positive();
2365 	i3 = return_positive();
2366 
2367 	test_bug_4004_helper_2();
2368 
2369 	return return_arg(i1) + return_arg(i2) + return_arg(i3) == return_positive() * 3;
2370 }
2371 //}}}
2372 
2373 /* #4663: *///{{{
2374 DEFINE_TEST(test_bug_4663)
2375 {
2376 	int i1, i2;
2377 
2378 	i1 = return_positive();
2379 	i2 = return_positive();
2380 
2381 	_SEH2_TRY
2382 	{
2383 		_SEH2_TRY
2384 		{
2385 			RaiseException(0xE00DEAD0, 0, 0, 0);
2386 		}
2387 		_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2388 		{
2389 			if (i1 == return_positive())
2390 			{
2391 				i1 = return_positive() + 1;
2392 			}
2393 		}
2394 		_SEH2_END;
2395 
2396 		if (i1 == return_positive() + 1)
2397 		{
2398 			i1 = return_negative();
2399 			RaiseException(0xE00DEAD0, 0, 0, 0);
2400 		}
2401 	}
2402 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2403 	{
2404 		i2 = return_negative();
2405 	}
2406 	_SEH2_END;
2407 
2408 	return ((i1 == return_negative()) && (i2 == return_negative()));
2409 }
2410 //}}}
2411 //}}}
2412 
2413 DEFINE_TEST(test_unvolatile)
2414 {
2415     int val = 0;
2416 
2417     _SEH2_TRY
2418     {
2419         val = return_one();
2420         *((char*)(intptr_t)0xc0000000) = 0;
2421     }
2422     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2423     {
2424         val = val + 3;
2425     }
2426     _SEH2_END;
2427 
2428     return (val == 4);
2429 }
2430 
2431 DEFINE_TEST(test_unvolatile_2)
2432 {
2433     int val = 0;
2434 
2435     _SEH2_TRY
2436     {
2437         val = 1;
2438         *((char*)(intptr_t)0xc0000000) = 0;
2439         val = 2;
2440     }
2441     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2442     {
2443         val = val + 3;
2444     }
2445     _SEH2_END;
2446 
2447     return (val == 3) || (val == 4) || (val == 5);
2448 }
2449 
2450 /* This test is mainly for documentation purpose. As can be seen it doesn't
2451    provide a satisfying result. In fact the compiler could do even more
2452    crazy things like reusing val1 between the assignment to 0 and the last
2453    assignment to 3. This DOES happen with C++ and it's NOT a PSEH bug, but
2454    rather an unavoidable consequence of how the compiler works.
2455    The conclusion: Do not use assignments to a variable inside a __try block
2456    that is being used later inside the __except block, unless it is declared
2457    volatile! */
2458 #ifndef __cplusplus
2459 DEFINE_TEST(test_unvolatile_3)
2460 {
2461     register int val1 = 0, val2 = 0;
2462 
2463     _SEH2_TRY
2464     {
2465         val1 = 1;
2466 
2467         _SEH2_TRY
2468         {
2469             val2 = 1;
2470             *((char*)(intptr_t)0xc0000000) = 0;
2471             val2 = 2;
2472         }
2473         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2474         {
2475             val2 |= 4;
2476         }
2477         _SEH2_END;
2478 
2479         val1 = 2;
2480         *((int*)(intptr_t)0xc0000000) = 1;
2481         val1 = 3;
2482     }
2483     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2484     {
2485         val1 = val1 * val2;
2486     }
2487     _SEH2_END;
2488 
2489     /* The expected case */
2490     if ((val1 == 10) && (val2 == 5))
2491         return TRUE;
2492 
2493     /* The compiler can optimize away "val1 = 1" and "val1 = 2" and
2494        only use the last "val1 = 3", in this case val1 is still 0
2495        when the outer exception handler kicks in */
2496     if ((val1 == 0) && (val2 == 5))
2497         return TRUE;
2498 
2499     /* Same as above, but this time val2 optimized away */
2500     if (((val1 == 8) && (val2 == 4)) ||
2501         ((val1 == 0) && (val2 == 4)))
2502         return TRUE;
2503 
2504     return FALSE;
2505 }
2506 #endif // __cplusplus
2507 
2508 DEFINE_TEST(test_unvolatile_4)
2509 {
2510     unsigned result = 0xdeadbeef;
2511 
2512     _SEH2_TRY
2513     {
2514         *(char*)(intptr_t)0x80000000 = 1;
2515     }
2516     _SEH2_EXCEPT(result == 0xdeadbeef)
2517     {
2518         result = 2;
2519     }
2520     _SEH2_END;
2521 
2522     result = (result == 0xdeadbeef) ? 0 : result + 1;
2523 
2524     return result == 3;
2525 }
2526 
2527 DEFINE_TEST(test_finally_goto)
2528 {
2529     volatile int val = 0;
2530 
2531     _SEH2_TRY
2532     {
2533         val |= 1;
2534         _SEH2_TRY
2535         {
2536             val |= 2;
2537             goto next;
2538         }
2539         _SEH2_FINALLY
2540         {
2541             val |= 4;
2542             *((char*)(intptr_t)0xdeadc0de) = 0;
2543             val |= 8;
2544         }
2545         _SEH2_END;
2546 
2547         val |= 16;
2548 next:
2549         val |= 32;
2550         *((char*)(intptr_t)0xdeadc0de) = 0;
2551         val |= 64;
2552     }
2553     _SEH2_EXCEPT(1)
2554     {
2555         val |= 128;
2556     }
2557     _SEH2_END;
2558 
2559     return (val == (128|4|2|1));
2560 }
2561 
2562 DEFINE_TEST(test_nested_exception)
2563 {
2564     volatile int val = 0;
2565 
2566     _SEH2_TRY
2567     {
2568         val |= 1;
2569         _SEH2_TRY
2570         {
2571             val |= 2;
2572             *((char*)(intptr_t)0xdeadc0de) = 0;
2573             val |= 4;
2574         }
2575         _SEH2_EXCEPT(1)
2576         {
2577             val |= 8;
2578             *((char*)(intptr_t)0xdeadc0de) = 0;
2579             val |= 16;
2580         }
2581         _SEH2_END;
2582 
2583         val |= 32;
2584         *((char*)(intptr_t)0xdeadc0de) = 0;
2585         val |= 64;
2586     }
2587     _SEH2_EXCEPT(1)
2588     {
2589         val |= 128;
2590     }
2591     _SEH2_END;
2592 
2593     return (val == (1|2|8|128));
2594 }
2595 
2596 static
2597 LONG WINAPI unhandled_exception(PEXCEPTION_POINTERS ExceptionInfo)
2598 {
2599 	trace("unhandled exception %08lX thrown from %p\n", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress);
2600 	return EXCEPTION_CONTINUE_SEARCH;
2601 }
2602 
2603 #if defined(_M_IX86)
2604 struct volatile_context
2605 {
2606 	void * esp;
2607 	void * ebp;
2608 	void * ebx;
2609 	void * esi;
2610 	void * edi;
2611 };
2612 #else
2613 struct volatile_context
2614 {
2615 	int _ignore;
2616 };
2617 #endif
2618 
2619 static
2620 DECLSPEC_NOINLINE
2621 int sanity_check(int ret, struct volatile_context * before, struct volatile_context * after)
2622 {
2623 	if(ret && memcmp(before, after, sizeof(*before)))
2624 	{
2625 		trace("volatile context corrupted\n");
2626 		return 0;
2627 	}
2628 
2629 	return ret;
2630 }
2631 
2632 #ifndef _PSEH3_H_
2633 static
2634 int passthrough_handler(struct _EXCEPTION_RECORD * e, void * f, struct _CONTEXT * c, void * d)
2635 {
2636 	return ExceptionContinueSearch;
2637 }
2638 #endif
2639 
2640 static
2641 DECLSPEC_NOINLINE
2642 int call_test(int (* func)(void))
2643 {
2644 	static int ret;
2645 	static struct volatile_context before, after;
2646 	static LPTOP_LEVEL_EXCEPTION_FILTER prev_unhandled_exception;
2647 #if defined(_X86_) && !defined(_PSEH3_H_) && !defined(_MSC_VER)
2648 	static _SEH2Registration_t * prev_frame;
2649 	_SEH2Registration_t passthrough_frame;
2650 #endif
2651 
2652 	prev_unhandled_exception = SetUnhandledExceptionFilter(&unhandled_exception);
2653 
2654 #if defined(_X86_) && !defined(_PSEH3_H_) && !defined(_MSC_VER)
2655 	prev_frame = (_SEH2Registration_t *)__readfsdword(0);
2656 	passthrough_frame.SER_Prev = prev_frame;
2657 	passthrough_frame.SER_Handler = passthrough_handler;
2658 	__writefsdword(0, (unsigned long)&passthrough_frame);
2659 #endif
2660 
2661 #if defined(__GNUC__) && defined(__i386__)
2662 	__asm__ __volatile__
2663 	(
2664 		"mov %%esp, 0x00 + %c[before]\n"
2665 		"mov %%ebp, 0x04 + %c[before]\n"
2666 		"mov %%ebx, 0x08 + %c[before]\n"
2667 		"mov %%esi, 0x0c + %c[before]\n"
2668 		"mov %%edi, 0x10 + %c[before]\n"
2669 		"call *%[test]\n"
2670 		"mov %%esp, 0x00 + %c[after]\n"
2671 		"mov %%ebp, 0x04 + %c[after]\n"
2672 		"mov %%ebx, 0x08 + %c[after]\n"
2673 		"mov %%esi, 0x0c + %c[after]\n"
2674 		"mov %%edi, 0x10 + %c[after]\n"
2675 		"push %[after]\n"
2676 		"push %[before]\n"
2677 		"push %[ret]\n"
2678 		"call %c[sanity_check]\n"
2679 		"pop %%ecx\n"
2680 		"pop %%ecx\n"
2681 		"pop %%ecx\n" :
2682 		[ret] "=a" (ret) :
2683 		[test] "r" (func), [before] "i" (&before), [after] "i" (&after), [sanity_check] "i" (&sanity_check) :
2684 		"ebx", "ecx", "edx", "esi", "edi", "flags", "memory"
2685 	);
2686 #else
2687 	ret = func();
2688 #endif
2689 
2690 #if defined(_X86_) && !defined(_PSEH3_H_) && !defined(_MSC_VER)
2691 	if((_SEH2Registration_t *)__readfsdword(0) != &passthrough_frame || passthrough_frame.SER_Prev != prev_frame)
2692 	{
2693 		trace("exception registration list corrupted\n");
2694 		ret = 0;
2695 	}
2696 
2697 	__writefsdword(0, (unsigned long)prev_frame);
2698 #endif
2699 
2700 	SetUnhandledExceptionFilter(prev_unhandled_exception);
2701 	return ret;
2702 }
2703 
2704 DEFINE_TEST(test_PSEH3_bug)
2705 {
2706     volatile int count = 0;
2707     int dummy = 0;
2708 
2709     _SEH2_TRY
2710     {
2711         if (count++ == 0)
2712         {
2713             *(volatile int*)0x12345678 = 0x12345678;
2714         }
2715     }
2716     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2717     {
2718         dummy = 0;
2719     }
2720     _SEH2_END;
2721 
2722     (void)dummy;
2723     return (count == 1);
2724 }
2725 
2726 void
2727 use_lots_of_stack(void)
2728 {
2729     int i;
2730     volatile int arr[512];
2731     for (i = 0; i < 512; i++)
2732         arr[i] = 123;
2733     (void)arr;
2734 }
2735 
2736 DEFINE_TEST(test_PSEH3_bug2)
2737 {
2738     unsigned long status = 0;
2739     _SEH2_TRY
2740     {
2741         *(volatile int*)0x12345678 = 0x12345678;
2742     }
2743     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2744     {
2745         use_lots_of_stack();
2746         status = _SEH2_GetExceptionCode();
2747     }
2748     _SEH2_END;
2749 
2750     return (status == STATUS_ACCESS_VIOLATION);
2751 }
2752 
2753 #define USE_TEST_NAME_(NAME_) # NAME_
2754 #define USE_TEST_NAME(NAME_) USE_TEST_NAME_(NAME_)
2755 #define USE_TEST(NAME_) { USE_TEST_NAME(NAME_), NAME_ }
2756 
2757 struct subtest
2758 {
2759 	const char * name;
2760 	int (* func)(void);
2761 };
2762 
2763 START_TEST(pseh)
2764 {
2765 	const struct subtest testsuite[] =
2766 	{
2767 		USE_TEST(test_empty_1),
2768 		USE_TEST(test_empty_2),
2769 		USE_TEST(test_empty_3),
2770 		USE_TEST(test_empty_4),
2771 		USE_TEST(test_empty_5),
2772 		USE_TEST(test_empty_6),
2773 		USE_TEST(test_empty_7),
2774 		USE_TEST(test_empty_8),
2775 
2776 		USE_TEST(test_execute_handler_1),
2777 		USE_TEST(test_continue_execution_1),
2778 		USE_TEST(test_continue_search_1),
2779 		USE_TEST(test_execute_handler_2),
2780 		USE_TEST(test_continue_execution_2),
2781 
2782 		USE_TEST(test_execute_handler_3),
2783 		USE_TEST(test_continue_execution_3),
2784 		USE_TEST(test_continue_search_2),
2785 		USE_TEST(test_execute_handler_4),
2786 		USE_TEST(test_continue_execution_4),
2787 
2788 		USE_TEST(test_execute_handler_5),
2789 		USE_TEST(test_continue_execution_5),
2790 		USE_TEST(test_continue_search_3),
2791 		USE_TEST(test_execute_handler_6),
2792 		USE_TEST(test_continue_execution_6),
2793 
2794 		USE_TEST(test_execute_handler_7),
2795 		USE_TEST(test_continue_execution_7),
2796 		USE_TEST(test_continue_search_4),
2797 		USE_TEST(test_execute_handler_8),
2798 		USE_TEST(test_continue_execution_8),
2799 
2800 		USE_TEST(test_execute_handler_9),
2801 		USE_TEST(test_continue_execution_9),
2802 		USE_TEST(test_continue_search_5),
2803 		USE_TEST(test_execute_handler_10),
2804 		USE_TEST(test_continue_execution_10),
2805 
2806 		USE_TEST(test_execute_handler_11),
2807 		USE_TEST(test_continue_execution_11),
2808 		USE_TEST(test_continue_search_6),
2809 		USE_TEST(test_execute_handler_12),
2810 		USE_TEST(test_continue_execution_12),
2811 
2812 		USE_TEST(test_leave_1),
2813 		USE_TEST(test_leave_2),
2814 		USE_TEST(test_leave_3),
2815 		USE_TEST(test_leave_4),
2816 		USE_TEST(test_leave_5),
2817 		USE_TEST(test_leave_6),
2818 
2819 		USE_TEST(test_yield_1),
2820 		USE_TEST(test_yield_2),
2821 		USE_TEST(test_yield_3),
2822 		USE_TEST(test_yield_4),
2823 		USE_TEST(test_yield_5),
2824 		USE_TEST(test_yield_6),
2825 
2826 		USE_TEST(test_finally_1),
2827 		USE_TEST(test_finally_2),
2828 		USE_TEST(test_finally_3),
2829 		USE_TEST(test_finally_4),
2830 		USE_TEST(test_finally_5),
2831 		USE_TEST(test_finally_6),
2832 		USE_TEST(test_finally_7),
2833 		USE_TEST(test_finally_8),
2834 		USE_TEST(test_finally_9),
2835 		USE_TEST(test_finally_10),
2836 		USE_TEST(test_finally_11),
2837 		USE_TEST(test_finally_12),
2838 		USE_TEST(test_finally_13),
2839 		USE_TEST(test_finally_14),
2840 
2841 		USE_TEST(test_xpointers_1),
2842 		USE_TEST(test_xpointers_2),
2843 		USE_TEST(test_xpointers_3),
2844 		USE_TEST(test_xpointers_4),
2845 		USE_TEST(test_xpointers_5),
2846 		USE_TEST(test_xpointers_6),
2847 		USE_TEST(test_xpointers_7),
2848 		USE_TEST(test_xpointers_8),
2849 		USE_TEST(test_xpointers_9),
2850 		USE_TEST(test_xpointers_10),
2851 		USE_TEST(test_xpointers_11),
2852 		USE_TEST(test_xpointers_12),
2853 		USE_TEST(test_xpointers_13),
2854 		USE_TEST(test_xpointers_14),
2855 		USE_TEST(test_xpointers_15),
2856 		USE_TEST(test_xpointers_16),
2857 
2858 		USE_TEST(test_xcode_1),
2859 		USE_TEST(test_xcode_2),
2860 		USE_TEST(test_xcode_3),
2861 
2862 		USE_TEST(test_abnorm_1),
2863 		USE_TEST(test_abnorm_2),
2864 		USE_TEST(test_abnorm_3),
2865 		USE_TEST(test_abnorm_4),
2866 		USE_TEST(test_abnorm_5),
2867 		USE_TEST(test_abnorm_6),
2868 		USE_TEST(test_abnorm_7),
2869 		USE_TEST(test_abnorm_8),
2870 
2871 		USE_TEST(test_nested_locals_1),
2872 		USE_TEST(test_nested_locals_2),
2873 		USE_TEST(test_nested_locals_3),
2874 
2875 		USE_TEST(test_bug_4004),
2876 		USE_TEST(test_bug_4663),
2877 
2878 		USE_TEST(test_unvolatile),
2879 		USE_TEST(test_unvolatile_2),
2880 #ifndef __cplusplus
2881 		USE_TEST(test_unvolatile_3),
2882 #endif
2883 		USE_TEST(test_unvolatile_4),
2884 		USE_TEST(test_finally_goto),
2885 		USE_TEST(test_nested_exception),
2886 		USE_TEST(test_PSEH3_bug),
2887 		USE_TEST(test_PSEH3_bug2),
2888 	};
2889 
2890 	size_t i;
2891 
2892 	for(i = 0; i < sizeof(testsuite) / sizeof(testsuite[0]); ++ i)
2893 		ok(call_test(testsuite[i].func), "%s failed\n", testsuite[i].name);
2894 }
2895 
2896 /* EOF */
2897