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