61800b17cf656c7ab64369ead5183562e049141e
[reactos.git] / modules / rostests / apitests / compiler / pseh.c
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(_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 */