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