From: Torge Matthies tmatthies@codeweavers.com
--- dlls/concrt140/Makefile.in | 4 ++- dlls/concrt140/concrt140.c | 10 +++++- dlls/crtdll/Makefile.in | 1 + dlls/msvcr70/Makefile.in | 1 + dlls/msvcr71/Makefile.in | 1 + dlls/msvcr80/Makefile.in | 1 + dlls/msvcr90/Makefile.in | 1 + dlls/msvcrt/concurrency.c | 71 +++++++++++++++++++++++++++++++++++-- dlls/msvcrt/cxx.h | 5 +++ dlls/msvcrt/except_i386.c | 15 -------- dlls/msvcrt/exception_ptr.c | 56 +++++++++++++++++++++-------- dlls/msvcrtd/Makefile.in | 1 + dlls/ucrtbase/Makefile.in | 1 + 13 files changed, 134 insertions(+), 34 deletions(-)
diff --git a/dlls/concrt140/Makefile.in b/dlls/concrt140/Makefile.in index aac1ed7b34a..05258adf7ee 100644 --- a/dlls/concrt140/Makefile.in +++ b/dlls/concrt140/Makefile.in @@ -1,7 +1,9 @@ +EXTRADEFS = -D_CONCRT= MODULE = concrt140.dll PARENTSRC = ../msvcrt
C_SRCS = \ concrt140.c \ concurrency.c \ - details.c + details.c \ + exception_ptr.c diff --git a/dlls/concrt140/concrt140.c b/dlls/concrt140/concrt140.c index 0a770c9dae6..758fbb52ad9 100644 --- a/dlls/concrt140/concrt140.c +++ b/dlls/concrt140/concrt140.c @@ -91,6 +91,7 @@ __ASM_VTABLE(range_error, VTABLE_ADD_FUNC(exception_what)); __ASM_BLOCK_END
+DEFINE_CXX_EXCEPTION0( exception, exception_dtor ) DEFINE_RTTI_DATA1(runtime_error, 0, &exception_rtti_base_descriptor, ".?AVruntime_error@std@@") DEFINE_CXX_TYPE_INFO(runtime_error) DEFINE_RTTI_DATA2(range_error, 0, &runtime_error_rtti_base_descriptor, @@ -105,6 +106,13 @@ void DECLSPEC_NORETURN throw_range_error(const char *str) _CxxThrowException(&e, &range_error_exception_type); }
+void DECLSPEC_NORETURN throw_exception(const char* msg) +{ + exception e; + __exception_ctor(&e, msg, &exception_vtable); + _CxxThrowException(&e, &exception_exception_type); +} + static BOOL init_cxx_funcs(void) { msvcp140 = LoadLibraryA("msvcp140.dll"); @@ -138,7 +146,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) init_runtime_error_rtti((char*)inst); init_type_info_rtti((char*)inst);
- init_exception_cxx_type_info((char*)inst); + init_exception_cxx((char*)inst); init_runtime_error_cxx_type_info((char*)inst); init_range_error_cxx((char*)inst); #endif diff --git a/dlls/crtdll/Makefile.in b/dlls/crtdll/Makefile.in index ffdbb2ab7a1..d54e8d49964 100644 --- a/dlls/crtdll/Makefile.in +++ b/dlls/crtdll/Makefile.in @@ -17,6 +17,7 @@ C_SRCS = \ except_arm64.c \ except_i386.c \ except_x86_64.c \ + exception_ptr.c \ exit.c \ file.c \ heap.c \ diff --git a/dlls/msvcr70/Makefile.in b/dlls/msvcr70/Makefile.in index 4383c5ccb87..5782a64bf03 100644 --- a/dlls/msvcr70/Makefile.in +++ b/dlls/msvcr70/Makefile.in @@ -18,6 +18,7 @@ C_SRCS = \ except_arm64.c \ except_i386.c \ except_x86_64.c \ + exception_ptr.c \ exit.c \ file.c \ heap.c \ diff --git a/dlls/msvcr71/Makefile.in b/dlls/msvcr71/Makefile.in index 5a83c81c547..f849158e2ee 100644 --- a/dlls/msvcr71/Makefile.in +++ b/dlls/msvcr71/Makefile.in @@ -18,6 +18,7 @@ C_SRCS = \ except_arm64.c \ except_i386.c \ except_x86_64.c \ + exception_ptr.c \ exit.c \ file.c \ heap.c \ diff --git a/dlls/msvcr80/Makefile.in b/dlls/msvcr80/Makefile.in index 2153949b41e..b3c44b3a530 100644 --- a/dlls/msvcr80/Makefile.in +++ b/dlls/msvcr80/Makefile.in @@ -18,6 +18,7 @@ C_SRCS = \ except_arm64.c \ except_i386.c \ except_x86_64.c \ + exception_ptr.c \ exit.c \ file.c \ heap.c \ diff --git a/dlls/msvcr90/Makefile.in b/dlls/msvcr90/Makefile.in index 96176a12553..1f7ba4cdcde 100644 --- a/dlls/msvcr90/Makefile.in +++ b/dlls/msvcr90/Makefile.in @@ -18,6 +18,7 @@ C_SRCS = \ except_arm64.c \ except_i386.c \ except_x86_64.c \ + exception_ptr.c \ exit.c \ file.c \ heap.c \ diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 3f0fbe6b62c..fd38948bba3 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -1900,13 +1900,57 @@ static ThreadScheduler *get_thread_scheduler_from_context(Context *context) return NULL; }
+struct execute_chore_data { + _UnrealizedChore *chore; + _StructuredTaskCollection *task_collection; +}; + +static LONG CALLBACK execute_chore_except(EXCEPTION_POINTERS *pexc, + void *_data) +{ + struct execute_chore_data *data = _data; + void *prev_exception, *new_exception; + exception_ptr *ptr; + + if (pexc->ExceptionRecord->ExceptionCode != CXX_EXCEPTION) + return EXCEPTION_CONTINUE_SEARCH; + + ptr = operator_new(sizeof(*ptr)); + __ExceptionPtrCreate(ptr); + exception_ptr_from_record(ptr, pexc->ExceptionRecord); + + new_exception = data->task_collection->exception; + do { + if ((ULONG_PTR)new_exception & ~0x7) { + __ExceptionPtrDestroy(ptr); + operator_delete(ptr); + break; + } + prev_exception = new_exception; + new_exception = (void*)((ULONG_PTR)new_exception | (ULONG_PTR)ptr); + } while ((new_exception = InterlockedCompareExchangePointer( + &data->task_collection->exception, new_exception, + prev_exception)) != prev_exception); + data->task_collection->event = 0; + return EXCEPTION_EXECUTE_HANDLER; +} + static void execute_chore(_UnrealizedChore *chore, _StructuredTaskCollection *task_collection) { + struct execute_chore_data data = { chore, task_collection }; + TRACE("(%p %p)\n", chore, task_collection);
- if (chore->chore_proc) - chore->chore_proc(chore); + __TRY + { + if (chore->chore_proc) + chore->chore_proc(chore); + } + __EXCEPT_CTX(execute_chore_except, &data) + { + } + __ENDTRY }
static void CALLBACK chore_wrapper_finally(BOOL normal, void *data) @@ -2053,6 +2097,16 @@ void __thiscall _StructuredTaskCollection__Schedule( } }
+static void CALLBACK exception_ptr_rethrow_finally(BOOL normal, void *data) +{ + exception_ptr *ep = data; + + TRACE("(%u %p)\n", normal, data); + + __ExceptionPtrDestroy(ep); + operator_delete(ep); +} + /* ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z */ /* ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z */ /* ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z */ @@ -2060,6 +2114,7 @@ void __thiscall _StructuredTaskCollection__Schedule( _StructuredTaskCollection *this, _UnrealizedChore *chore) { LONG expected, val; + ULONG_PTR exception;
TRACE("(%p %p)\n", this, chore);
@@ -2085,6 +2140,18 @@ void __thiscall _StructuredTaskCollection__Schedule(
this->finished = 0; this->count = 0; + + exception = (ULONG_PTR)this->exception; + if (exception & ~0x7) + this->exception = 0; + if (exception & ~0x7) { + exception_ptr *ep = (exception_ptr*)(exception & ~0x7); + __TRY + { + __ExceptionPtrRethrow(ep); + } + __FINALLY_CTX(exception_ptr_rethrow_finally, ep) + } return 1; }
diff --git a/dlls/msvcrt/cxx.h b/dlls/msvcrt/cxx.h index 4051229c626..c2558974b73 100644 --- a/dlls/msvcrt/cxx.h +++ b/dlls/msvcrt/cxx.h @@ -316,3 +316,8 @@ typedef struct } exception_ptr;
void throw_exception(const char*) DECLSPEC_HIDDEN; +void exception_ptr_from_record(exception_ptr*,EXCEPTION_RECORD*) DECLSPEC_HIDDEN; + +void __cdecl __ExceptionPtrCreate(exception_ptr*); +void __cdecl __ExceptionPtrDestroy(exception_ptr*); +void __cdecl __ExceptionPtrRethrow(const exception_ptr*); diff --git a/dlls/msvcrt/except_i386.c b/dlls/msvcrt/except_i386.c index eb41af36d7e..662b4ebadb0 100644 --- a/dlls/msvcrt/except_i386.c +++ b/dlls/msvcrt/except_i386.c @@ -149,21 +149,6 @@ DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame /* call a copy constructor */ extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase );
-__ASM_GLOBAL_FUNC( call_copy_ctor, - "pushl %ebp\n\t" - __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") - __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") - "movl %esp, %ebp\n\t" - __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") - "pushl $1\n\t" - "movl 12(%ebp), %ecx\n\t" - "pushl 16(%ebp)\n\t" - "call *8(%ebp)\n\t" - "leave\n" - __ASM_CFI(".cfi_def_cfa %esp,4\n\t") - __ASM_CFI(".cfi_same_value %ebp\n\t") - "ret" ); - /* continue execution to the specified address after exception is caught */ extern void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr );
diff --git a/dlls/msvcrt/exception_ptr.c b/dlls/msvcrt/exception_ptr.c index 8238baec548..bd341ac49a1 100644 --- a/dlls/msvcrt/exception_ptr.c +++ b/dlls/msvcrt/exception_ptr.c @@ -28,6 +28,37 @@ #include "msvcrt.h" #include "cxx.h"
+#ifdef __i386__ + +extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase ); + +__ASM_GLOBAL_FUNC( call_copy_ctor, + "pushl %ebp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") + "movl %esp, %ebp\n\t" + __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") + "pushl $1\n\t" + "movl 12(%ebp), %ecx\n\t" + "pushl 16(%ebp)\n\t" + "call *8(%ebp)\n\t" + "leave\n" + __ASM_CFI(".cfi_def_cfa %esp,4\n\t") + __ASM_CFI(".cfi_same_value %ebp\n\t") + "ret" ); + +#elif _MSVCR_VER >= 100 + +static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase ) +{ + if (has_vbase) + ((void (__cdecl*)(void*, void*, BOOL))func)(this, src, 1); + else + ((void (__cdecl*)(void*, void*))func)(this, src); +} + +#endif + #if _MSVCR_VER >= 100
WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); @@ -89,6 +120,8 @@ void __cdecl __ExceptionPtrDestroy(exception_ptr *ep) } }
+#ifndef _CONCRT + /********************************************************************* * ?__ExceptionPtrCopy@@YAXPAXPBX@Z * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z @@ -120,6 +153,8 @@ void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign InterlockedIncrement(ep->ref); }
+#endif + /********************************************************************* * ?__ExceptionPtrRethrow@@YAXPBX@Z * ?__ExceptionPtrRethrow@@YAXPEBX@Z @@ -138,21 +173,8 @@ void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep) ep->rec->NumberParameters, ep->rec->ExceptionInformation); }
-#ifdef __i386__ -extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase ); -#else -static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase ) -{ - TRACE( "calling copy ctor %p object %p src %p\n", func, this, src ); - if (has_vbase) - ((void (__cdecl*)(void*, void*, BOOL))func)(this, src, 1); - else - ((void (__cdecl*)(void*, void*))func)(this, src); -} -#endif - #ifndef __x86_64__ -static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) +void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) { TRACE("(%p)\n", ep);
@@ -196,7 +218,7 @@ static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) return; } #else -static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) +void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) { TRACE("(%p)\n", ep);
@@ -242,6 +264,8 @@ static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) } #endif
+#ifndef _CONCRT + /********************************************************************* * ?__ExceptionPtrCurrentException@@YAXPAX@Z * ?__ExceptionPtrCurrentException@@YAXPEAX@Z @@ -349,4 +373,6 @@ bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr return ep1->rec == ep2->rec; }
+#endif + #endif /* _MSVCR_VER >= 100 */ diff --git a/dlls/msvcrtd/Makefile.in b/dlls/msvcrtd/Makefile.in index 97743e99062..95f0bca93b4 100644 --- a/dlls/msvcrtd/Makefile.in +++ b/dlls/msvcrtd/Makefile.in @@ -19,6 +19,7 @@ C_SRCS = \ except_arm64.c \ except_i386.c \ except_x86_64.c \ + exception_ptr.c \ exit.c \ file.c \ heap.c \ diff --git a/dlls/ucrtbase/Makefile.in b/dlls/ucrtbase/Makefile.in index bf7f62ada8a..4e7cfc03b5c 100644 --- a/dlls/ucrtbase/Makefile.in +++ b/dlls/ucrtbase/Makefile.in @@ -23,6 +23,7 @@ C_SRCS = \ except_arm64.c \ except_i386.c \ except_x86_64.c \ + exception_ptr.c \ exit.c \ file.c \ heap.c \