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