- Based on !463 - _RunAndWait and exception handling implemented in later commits
@piotr
-- v2: msvcr100: Implement _StructuredTaskCollection::_Schedule and _Schedule_loc. msvcr100: Make ExternalContextBase reference-counted. msvcr100: Factor out the mapping of a context to a scheduler. msvcr100: Factor out EXCEPTION_RECORD to exception_ptr conversion. msvcr100: Move exception_ptr functions to a separate file. msvcr100: Implement invalid_multiple_scheduling exception.
From: Torge Matthies tmatthies@codeweavers.com
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/concrt140/concrt140.spec | 12 ++++----- dlls/msvcr100/msvcr100.spec | 8 +++--- dlls/msvcr110/msvcr110.spec | 12 ++++----- dlls/msvcr120/msvcr120.spec | 12 ++++----- dlls/msvcr120_app/msvcr120_app.spec | 12 ++++----- dlls/msvcrt/concurrency.c | 42 +++++++++++++++++++++++++++++ 6 files changed, 70 insertions(+), 28 deletions(-)
diff --git a/dlls/concrt140/concrt140.spec b/dlls/concrt140/concrt140.spec index 9370566bb2c..64da684f415 100644 --- a/dlls/concrt140/concrt140.spec +++ b/dlls/concrt140/concrt140.spec @@ -144,12 +144,12 @@ @ stub -arch=arm ??0invalid_link_target@Concurrency@@QAA@XZ @ stub -arch=i386 ??0invalid_link_target@Concurrency@@QAE@XZ @ stub -arch=win64 ??0invalid_link_target@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@PBD@Z -@ stub -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z -@ stub -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z -@ stub -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@XZ -@ stub -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@PBD@Z(ptr ptr) invalid_multiple_scheduling_ctor_str +@ thiscall -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z(ptr ptr) invalid_multiple_scheduling_ctor_str +@ cdecl -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z(ptr ptr) invalid_multiple_scheduling_ctor_str +@ cdecl -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@XZ(ptr) invalid_multiple_scheduling_ctor +@ thiscall -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@XZ(ptr) invalid_multiple_scheduling_ctor +@ cdecl -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ(ptr) invalid_multiple_scheduling_ctor @ stub -arch=arm ??0invalid_oversubscribe_operation@Concurrency@@QAA@PBD@Z @ stub -arch=i386 ??0invalid_oversubscribe_operation@Concurrency@@QAE@PBD@Z @ stub -arch=win64 ??0invalid_oversubscribe_operation@Concurrency@@QEAA@PEBD@Z diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index 0d38005c13a..c0bbbc5b86d 100644 --- a/dlls/msvcr100/msvcr100.spec +++ b/dlls/msvcr100/msvcr100.spec @@ -94,10 +94,10 @@ @ stub -arch=win64 ??0invalid_link_target@Concurrency@@QEAA@PEBD@Z @ stub -arch=win32 ??0invalid_link_target@Concurrency@@QAE@XZ @ stub -arch=win64 ??0invalid_link_target@Concurrency@@QEAA@XZ -@ stub -arch=win32 ??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z -@ stub -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z -@ stub -arch=win32 ??0invalid_multiple_scheduling@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ +@ thiscall -arch=win32 ??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z(ptr ptr) invalid_multiple_scheduling_ctor_str +@ cdecl -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z(ptr ptr) invalid_multiple_scheduling_ctor_str +@ thiscall -arch=win32 ??0invalid_multiple_scheduling@Concurrency@@QAE@XZ(ptr) invalid_multiple_scheduling_ctor +@ cdecl -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ(ptr) invalid_multiple_scheduling_ctor @ stub -arch=win32 ??0invalid_operation@Concurrency@@QAE@PBD@Z @ stub -arch=win64 ??0invalid_operation@Concurrency@@QEAA@PEBD@Z @ stub -arch=win32 ??0invalid_operation@Concurrency@@QAE@XZ diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 24e7630194c..a272ae98a1c 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -167,12 +167,12 @@ @ stub -arch=arm ??0invalid_link_target@Concurrency@@QAA@XZ @ stub -arch=i386 ??0invalid_link_target@Concurrency@@QAE@XZ @ stub -arch=win64 ??0invalid_link_target@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@PBD@Z -@ stub -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z -@ stub -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z -@ stub -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@XZ -@ stub -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@PBD@Z(ptr ptr) invalid_multiple_scheduling_ctor_str +@ thiscall -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z(ptr ptr) invalid_multiple_scheduling_ctor_str +@ cdecl -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z(ptr ptr) invalid_multiple_scheduling_ctor_str +@ cdecl -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@XZ(ptr) invalid_multiple_scheduling_ctor +@ thiscall -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@XZ(ptr) invalid_multiple_scheduling_ctor +@ cdecl -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ(ptr) invalid_multiple_scheduling_ctor @ stub -arch=arm ??0invalid_operation@Concurrency@@QAA@PBD@Z @ stub -arch=i386 ??0invalid_operation@Concurrency@@QAE@PBD@Z @ stub -arch=win64 ??0invalid_operation@Concurrency@@QEAA@PEBD@Z diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index b1258dad5de..d16316e7e05 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -164,12 +164,12 @@ @ stub -arch=arm ??0invalid_link_target@Concurrency@@QAA@XZ @ stub -arch=i386 ??0invalid_link_target@Concurrency@@QAE@XZ @ stub -arch=win64 ??0invalid_link_target@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@PBD@Z -@ stub -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z -@ stub -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z -@ stub -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@XZ -@ stub -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@PBD@Z(ptr ptr) invalid_multiple_scheduling_ctor_str +@ thiscall -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z(ptr ptr) invalid_multiple_scheduling_ctor_str +@ cdecl -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z(ptr ptr) invalid_multiple_scheduling_ctor_str +@ cdecl -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@XZ(ptr) invalid_multiple_scheduling_ctor +@ thiscall -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@XZ(ptr) invalid_multiple_scheduling_ctor +@ cdecl -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ(ptr) invalid_multiple_scheduling_ctor @ stub -arch=arm ??0invalid_operation@Concurrency@@QAA@PBD@Z @ stub -arch=i386 ??0invalid_operation@Concurrency@@QAE@PBD@Z @ stub -arch=win64 ??0invalid_operation@Concurrency@@QEAA@PEBD@Z diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index 93ce779ea69..aa5d8ccf968 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -162,12 +162,12 @@ @ stub -arch=arm ??0invalid_link_target@Concurrency@@QAA@XZ @ stub -arch=i386 ??0invalid_link_target@Concurrency@@QAE@XZ @ stub -arch=win64 ??0invalid_link_target@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@PBD@Z -@ stub -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z -@ stub -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z -@ stub -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@XZ -@ stub -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@PBD@Z(ptr ptr) msvcr120.??0invalid_multiple_scheduling@Concurrency@@QAA@PBD@Z +@ thiscall -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z(ptr ptr) msvcr120.??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z +@ cdecl -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z(ptr ptr) msvcr120.??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z +@ cdecl -arch=arm ??0invalid_multiple_scheduling@Concurrency@@QAA@XZ(ptr) msvcr120.??0invalid_multiple_scheduling@Concurrency@@QAA@XZ +@ thiscall -arch=i386 ??0invalid_multiple_scheduling@Concurrency@@QAE@XZ(ptr) msvcr120.??0invalid_multiple_scheduling@Concurrency@@QAE@XZ +@ cdecl -arch=win64 ??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ(ptr) msvcr120.??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ @ stub -arch=arm ??0invalid_operation@Concurrency@@QAA@PBD@Z @ stub -arch=i386 ??0invalid_operation@Concurrency@@QAE@PBD@Z @ stub -arch=win64 ??0invalid_operation@Concurrency@@QEAA@PEBD@Z diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index c982e367749..06348173eef 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -329,6 +329,9 @@ extern const vtable_ptr improper_scheduler_attach_vtable; typedef exception improper_scheduler_detach; extern const vtable_ptr improper_scheduler_detach_vtable;
+typedef exception invalid_multiple_scheduling; +extern const vtable_ptr invalid_multiple_scheduling_vtable; + typedef exception invalid_scheduler_policy_key; extern const vtable_ptr invalid_scheduler_policy_key_vtable;
@@ -451,6 +454,35 @@ improper_scheduler_detach * __thiscall improper_scheduler_detach_copy_ctor( return __exception_copy_ctor(_this, rhs, &improper_scheduler_detach_vtable); }
+/* ??0invalid_multiple_scheduling@Concurrency@@QAA@PBD@Z */ +/* ??0invalid_multiple_scheduling@Concurrency@@QAE@PBD@Z */ +/* ??0invalid_multiple_scheduling@Concurrency@@QEAA@PEBD@Z */ +DEFINE_THISCALL_WRAPPER(invalid_multiple_scheduling_ctor_str, 8) +invalid_multiple_scheduling* __thiscall invalid_multiple_scheduling_ctor_str( + invalid_multiple_scheduling *this, const char *str) +{ + TRACE("(%p %p)\n", this, str); + return __exception_ctor(this, str, &invalid_multiple_scheduling_vtable); +} + +/* ??0invalid_multiple_scheduling@Concurrency@@QAA@XZ */ +/* ??0invalid_multiple_scheduling@Concurrency@@QAE@XZ */ +/* ??0invalid_multiple_scheduling@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(invalid_multiple_scheduling_ctor, 4) +invalid_multiple_scheduling* __thiscall invalid_multiple_scheduling_ctor( + invalid_multiple_scheduling *this) +{ + return invalid_multiple_scheduling_ctor_str(this, NULL); +} + +DEFINE_THISCALL_WRAPPER(invalid_multiple_scheduling_copy_ctor,8) +invalid_multiple_scheduling * __thiscall invalid_multiple_scheduling_copy_ctor( + invalid_multiple_scheduling * _this, const invalid_multiple_scheduling * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + return __exception_copy_ctor(_this, rhs, &invalid_multiple_scheduling_vtable); +} + /* ??0invalid_scheduler_policy_key@Concurrency@@QAE@PBD@Z */ /* ??0invalid_scheduler_policy_key@Concurrency@@QEAA@PEBD@Z */ DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_key_ctor_str, 8) @@ -583,6 +615,8 @@ DEFINE_RTTI_DATA1(improper_scheduler_attach, 0, &cexception_rtti_base_descriptor ".?AVimproper_scheduler_attach@Concurrency@@") DEFINE_RTTI_DATA1(improper_scheduler_detach, 0, &cexception_rtti_base_descriptor, ".?AVimproper_scheduler_detach@Concurrency@@") +DEFINE_RTTI_DATA1(invalid_multiple_scheduling, 0, &cexception_rtti_base_descriptor, + ".?AVinvalid_multiple_scheduling@Concurrency@@") DEFINE_RTTI_DATA1(invalid_scheduler_policy_key, 0, &cexception_rtti_base_descriptor, ".?AVinvalid_scheduler_policy_key@Concurrency@@") DEFINE_RTTI_DATA1(invalid_scheduler_policy_thread_specification, 0, &cexception_rtti_base_descriptor, @@ -595,6 +629,9 @@ DEFINE_RTTI_DATA1(scheduler_resource_allocation_error, 0, &cexception_rtti_base_ DEFINE_CXX_DATA1(improper_lock, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(improper_scheduler_attach, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(improper_scheduler_detach, &cexception_cxx_type_info, cexception_dtor) +#ifdef __x86_64__ +DEFINE_CXX_DATA1(invalid_multiple_scheduling, &cexception_cxx_type_info, cexception_dtor) +#endif DEFINE_CXX_DATA1(invalid_scheduler_policy_key, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(invalid_scheduler_policy_thread_specification, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(invalid_scheduler_policy_value, &cexception_cxx_type_info, cexception_dtor) @@ -610,6 +647,9 @@ __ASM_BLOCK_BEGIN(concurrency_exception_vtables) __ASM_VTABLE(improper_scheduler_detach, VTABLE_ADD_FUNC(cexception_vector_dtor) VTABLE_ADD_FUNC(cexception_what)); + __ASM_VTABLE(invalid_multiple_scheduling, + VTABLE_ADD_FUNC(cexception_vector_dtor) + VTABLE_ADD_FUNC(cexception_what)); __ASM_VTABLE(invalid_scheduler_policy_key, VTABLE_ADD_FUNC(cexception_vector_dtor) VTABLE_ADD_FUNC(cexception_what)); @@ -3042,6 +3082,7 @@ void msvcrt_init_concurrency(void *base) init_improper_lock_rtti(base); init_improper_scheduler_attach_rtti(base); init_improper_scheduler_detach_rtti(base); + init_invalid_multiple_scheduling_rtti(base); init_invalid_scheduler_policy_key_rtti(base); init_invalid_scheduler_policy_thread_specification_rtti(base); init_invalid_scheduler_policy_value_rtti(base); @@ -3058,6 +3099,7 @@ void msvcrt_init_concurrency(void *base) init_improper_lock_cxx(base); init_improper_scheduler_attach_cxx(base); init_improper_scheduler_detach_cxx(base); + init_invalid_multiple_scheduling_cxx(base); init_invalid_scheduler_policy_key_cxx(base); init_invalid_scheduler_policy_thread_specification_cxx(base); init_invalid_scheduler_policy_value_cxx(base);
From: Torge Matthies tmatthies@codeweavers.com
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/crtdll/Makefile.in | 1 + dlls/msvcr100/Makefile.in | 1 + dlls/msvcr110/Makefile.in | 1 + dlls/msvcr120/Makefile.in | 1 + dlls/msvcrt/Makefile.in | 1 + dlls/msvcrt/cpp.c | 344 +---------------------------------- dlls/msvcrt/cxx.h | 6 + dlls/msvcrt/exception_ptr.c | 346 ++++++++++++++++++++++++++++++++++++ dlls/msvcrt/main.c | 1 + dlls/msvcrt/msvcrt.h | 1 + dlls/msvcrtd/Makefile.in | 1 + dlls/ucrtbase/Makefile.in | 1 + 12 files changed, 364 insertions(+), 341 deletions(-) create mode 100644 dlls/msvcrt/exception_ptr.c
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/msvcr100/Makefile.in b/dlls/msvcr100/Makefile.in index a48ae314257..d17aa79b3d7 100644 --- a/dlls/msvcr100/Makefile.in +++ b/dlls/msvcr100/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/msvcr110/Makefile.in b/dlls/msvcr110/Makefile.in index 26db1d46f7a..0bc15e27d94 100644 --- a/dlls/msvcr110/Makefile.in +++ b/dlls/msvcr110/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/msvcr120/Makefile.in b/dlls/msvcr120/Makefile.in index d2957c2f1d3..cc3d5b2bdff 100644 --- a/dlls/msvcr120/Makefile.in +++ b/dlls/msvcr120/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/msvcrt/Makefile.in b/dlls/msvcrt/Makefile.in index e8a510d9937..8cd0c4ea7f4 100644 --- a/dlls/msvcrt/Makefile.in +++ b/dlls/msvcrt/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 \ diff --git a/dlls/msvcrt/cpp.c b/dlls/msvcrt/cpp.c index f3200e046cb..6b2e0dbb20c 100644 --- a/dlls/msvcrt/cpp.c +++ b/dlls/msvcrt/cpp.c @@ -583,7 +583,9 @@ DEFINE_RTTI_DATA1( bad_cast, 0, &exception_rtti_base_descriptor, ".?AVbad_cast@@ DEFINE_RTTI_DATA2( __non_rtti_object, 0, &bad_typeid_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AV__non_rtti_object@@" ) #endif
+#ifdef __x86_64__ DEFINE_CXX_EXCEPTION0( exception, exception_dtor ) +#endif DEFINE_CXX_DATA1( bad_typeid, &exception_cxx_type_info, bad_typeid_dtor ) DEFINE_CXX_DATA1( bad_cast, &exception_cxx_type_info, bad_cast_dtor ) DEFINE_CXX_DATA2( __non_rtti_object, &bad_typeid_cxx_type_info, @@ -1128,351 +1130,11 @@ const char * __thiscall type_info_name_internal_method(type_info * _this, struct return type_info_name(_this); }
-#endif /* _MSVCR_VER >= 80 */ - -/* std::exception_ptr class helpers */ -typedef struct -{ - EXCEPTION_RECORD *rec; - LONG *ref; /* not binary compatible with native msvcr100 */ -} exception_ptr; - -#if _MSVCR_VER >= 100 - -/********************************************************************* - * ?__ExceptionPtrCreate@@YAXPAX@Z - * ?__ExceptionPtrCreate@@YAXPEAX@Z - */ -void __cdecl __ExceptionPtrCreate(exception_ptr *ep) -{ - TRACE("(%p)\n", ep); - - ep->rec = NULL; - ep->ref = NULL; -} - -#ifdef __ASM_USE_THISCALL_WRAPPER -extern void call_dtor(const cxx_exception_type *type, void *func, void *object); - -__ASM_GLOBAL_FUNC( call_dtor, - "movl 12(%esp),%ecx\n\t" - "call *8(%esp)\n\t" - "ret" ); -#elif __x86_64__ -static inline void call_dtor(const cxx_exception_type *type, unsigned int dtor, void *object) -{ - char *base = RtlPcToFileHeader((void*)type, (void**)&base); - void (__cdecl *func)(void*) = (void*)(base + dtor); - func(object); -} -#else -#define call_dtor(type, func, object) ((void (__thiscall*)(void*))(func))(object) -#endif - -/********************************************************************* - * ?__ExceptionPtrDestroy@@YAXPAX@Z - * ?__ExceptionPtrDestroy@@YAXPEAX@Z - */ -void __cdecl __ExceptionPtrDestroy(exception_ptr *ep) -{ - TRACE("(%p)\n", ep); - - if (!ep->rec) - return; - - if (!InterlockedDecrement(ep->ref)) - { - if (ep->rec->ExceptionCode == CXX_EXCEPTION) - { - const cxx_exception_type *type = (void*)ep->rec->ExceptionInformation[2]; - void *obj = (void*)ep->rec->ExceptionInformation[1]; - - if (type && type->destructor) call_dtor(type, type->destructor, obj); - HeapFree(GetProcessHeap(), 0, obj); - } - - HeapFree(GetProcessHeap(), 0, ep->rec); - HeapFree(GetProcessHeap(), 0, ep->ref); - } -} - -/********************************************************************* - * ?__ExceptionPtrCopy@@YAXPAXPBX@Z - * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z - */ -void __cdecl __ExceptionPtrCopy(exception_ptr *ep, const exception_ptr *copy) -{ - TRACE("(%p %p)\n", ep, copy); - - /* don't destroy object stored in ep */ - *ep = *copy; - if (ep->ref) - InterlockedIncrement(copy->ref); -} - -/********************************************************************* - * ?__ExceptionPtrAssign@@YAXPAXPBX@Z - * ?__ExceptionPtrAssign@@YAXPEAXPEBX@Z - */ -void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign) -{ - TRACE("(%p %p)\n", ep, assign); - - /* don't destroy object stored in ep */ - if (ep->ref) - InterlockedDecrement(ep->ref); - - *ep = *assign; - if (ep->ref) - InterlockedIncrement(ep->ref); -} - -#endif /* _MSVCR_VER >= 100 */ - -/********************************************************************* - * ?__ExceptionPtrRethrow@@YAXPBX@Z - * ?__ExceptionPtrRethrow@@YAXPEBX@Z - */ -void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep) -{ - TRACE("(%p)\n", ep); - - if (!ep->rec) - { - static const char *exception_msg = "bad exception"; - exception e; - - exception_ctor(&e, &exception_msg); - _CxxThrowException(&e, &exception_exception_type); - return; - } - - RaiseException(ep->rec->ExceptionCode, ep->rec->ExceptionFlags & (~EH_UNWINDING), - ep->rec->NumberParameters, ep->rec->ExceptionInformation); -} - -#if _MSVCR_VER >= 100 - -#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 - -/********************************************************************* - * ?__ExceptionPtrCurrentException@@YAXPAX@Z - * ?__ExceptionPtrCurrentException@@YAXPEAX@Z - */ -#ifndef __x86_64__ -void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep) -{ - EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record; - - TRACE("(%p)\n", ep); - - if (!rec) - { - ep->rec = NULL; - ep->ref = NULL; - return; - } - - ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); - ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); - - *ep->rec = *rec; - *ep->ref = 1; - - if (ep->rec->ExceptionCode == CXX_EXCEPTION) - { - const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2]; - const cxx_type_info *ti; - void **data, *obj; - - ti = et->type_info_table->info[0]; - data = HeapAlloc(GetProcessHeap(), 0, ti->size); - - obj = (void*)ep->rec->ExceptionInformation[1]; - if (ti->flags & CLASS_IS_SIMPLE_TYPE) - { - memcpy(data, obj, ti->size); - if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); - } - else if (ti->copy_ctor) - { - call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj), - ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); - } - else - memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size); - ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; - } - return; -} -#else -void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep) -{ - EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record; - - TRACE("(%p)\n", ep); - - if (!rec) - { - ep->rec = NULL; - ep->ref = NULL; - return; - } - - ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); - ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); - - *ep->rec = *rec; - *ep->ref = 1; - - if (ep->rec->ExceptionCode == CXX_EXCEPTION) - { - const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2]; - const cxx_type_info *ti; - void **data, *obj; - char *base = RtlPcToFileHeader((void*)et, (void**)&base); - - ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + et->type_info_table))->info[0]); - data = HeapAlloc(GetProcessHeap(), 0, ti->size); - - obj = (void*)ep->rec->ExceptionInformation[1]; - if (ti->flags & CLASS_IS_SIMPLE_TYPE) - { - memcpy(data, obj, ti->size); - if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); - } - else if (ti->copy_ctor) - { - call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj), - ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); - } - else - memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size); - ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; - } - return; -} -#endif - -#endif /* _MSVCR_VER >= 100 */ - -#if _MSVCR_VER >= 110 -/********************************************************************* - * ?__ExceptionPtrToBool@@YA_NPBX@Z - * ?__ExceptionPtrToBool@@YA_NPEBX@Z - */ -bool __cdecl __ExceptionPtrToBool(exception_ptr *ep) -{ - return !!ep->rec; -} -#endif - -#if _MSVCR_VER >= 100 - -/********************************************************************* - * ?__ExceptionPtrCopyException@@YAXPAXPBX1@Z - * ?__ExceptionPtrCopyException@@YAXPEAXPEBX1@Z - */ -#ifndef __x86_64__ -void __cdecl __ExceptionPtrCopyException(exception_ptr *ep, - exception *object, const cxx_exception_type *type) -{ - const cxx_type_info *ti; - void **data; - - __ExceptionPtrDestroy(ep); - - ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); - ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); - *ep->ref = 1; - - memset(ep->rec, 0, sizeof(EXCEPTION_RECORD)); - ep->rec->ExceptionCode = CXX_EXCEPTION; - ep->rec->ExceptionFlags = EH_NONCONTINUABLE; - ep->rec->NumberParameters = 3; - ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6; - ep->rec->ExceptionInformation[2] = (ULONG_PTR)type; - - ti = type->type_info_table->info[0]; - data = HeapAlloc(GetProcessHeap(), 0, ti->size); - if (ti->flags & CLASS_IS_SIMPLE_TYPE) - { - memcpy(data, object, ti->size); - if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); - } - else if (ti->copy_ctor) - { - call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, object), - ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); - } - else - memcpy(data, get_this_pointer(&ti->offsets, object), ti->size); - ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; -} -#else -void __cdecl __ExceptionPtrCopyException(exception_ptr *ep, - exception *object, const cxx_exception_type *type) -{ - const cxx_type_info *ti; - void **data; - char *base; - - RtlPcToFileHeader((void*)type, (void**)&base); - __ExceptionPtrDestroy(ep); - - ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); - ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); - *ep->ref = 1; - - memset(ep->rec, 0, sizeof(EXCEPTION_RECORD)); - ep->rec->ExceptionCode = CXX_EXCEPTION; - ep->rec->ExceptionFlags = EH_NONCONTINUABLE; - ep->rec->NumberParameters = 4; - ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6; - ep->rec->ExceptionInformation[2] = (ULONG_PTR)type; - ep->rec->ExceptionInformation[3] = (ULONG_PTR)base; - - ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + type->type_info_table))->info[0]); - data = HeapAlloc(GetProcessHeap(), 0, ti->size); - if (ti->flags & CLASS_IS_SIMPLE_TYPE) - { - memcpy(data, object, ti->size); - if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); - } - else if (ti->copy_ctor) - { - call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, object), - ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); - } - else - memcpy(data, get_this_pointer(&ti->offsets, object), ti->size); - ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; -} -#endif - -bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr *ep2) -{ - return ep1->rec == ep2->rec; -} - -#endif /* _MSVCR_VER >= 100 */ - -#if _MSVCR_VER >= 80 void* __cdecl __AdjustPointer(void *obj, const this_ptr_offsets *off) { return get_this_pointer(off, obj); } + #endif
#if _MSVCR_VER >= 140 diff --git a/dlls/msvcrt/cxx.h b/dlls/msvcrt/cxx.h index cacbb1524b6..047bd5610a9 100644 --- a/dlls/msvcrt/cxx.h +++ b/dlls/msvcrt/cxx.h @@ -308,3 +308,9 @@ __ASM_BLOCK_BEGIN(type_info_vtables) \ __ASM_VTABLE(type_info, \ VTABLE_ADD_FUNC(type_info_vector_dtor)); \ __ASM_BLOCK_END + +typedef struct +{ + EXCEPTION_RECORD *rec; + LONG *ref; /* not binary compatible with native msvcr100 */ +} exception_ptr; diff --git a/dlls/msvcrt/exception_ptr.c b/dlls/msvcrt/exception_ptr.c new file mode 100644 index 00000000000..7eddfb98341 --- /dev/null +++ b/dlls/msvcrt/exception_ptr.c @@ -0,0 +1,346 @@ +#include <stdarg.h> +#include <stdbool.h> + +#include "windef.h" +#include "winternl.h" +#include "wine/exception.h" +#include "wine/debug.h" +#include "msvcrt.h" +#include "cxx.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); + +/* std::exception_ptr class helpers */ + +typedef exception eexception; +CREATE_EXCEPTION_OBJECT(eexception) + +DEFINE_CXX_EXCEPTION0( eexception, eexception_dtor ) + +void msvcrt_init_exception_ptr(void *base) +{ +#ifdef __x86_64__ + init_eexception_rtti(base); + + init_eexception_cxx(base); +#endif +} + +/********************************************************************* + * ?__ExceptionPtrCreate@@YAXPAX@Z + * ?__ExceptionPtrCreate@@YAXPEAX@Z + */ +void __cdecl __ExceptionPtrCreate(exception_ptr *ep) +{ + TRACE("(%p)\n", ep); + + ep->rec = NULL; + ep->ref = NULL; +} + +#ifdef __ASM_USE_THISCALL_WRAPPER +extern void call_dtor(const cxx_exception_type *type, void *func, void *object); + +__ASM_GLOBAL_FUNC( call_dtor, + "movl 12(%esp),%ecx\n\t" + "call *8(%esp)\n\t" + "ret" ); +#elif __x86_64__ +static inline void call_dtor(const cxx_exception_type *type, unsigned int dtor, void *object) +{ + char *base = RtlPcToFileHeader((void*)type, (void**)&base); + void (__cdecl *func)(void*) = (void*)(base + dtor); + func(object); +} +#else +#define call_dtor(type, func, object) ((void (__thiscall*)(void*))(func))(object) +#endif + +/********************************************************************* + * ?__ExceptionPtrDestroy@@YAXPAX@Z + * ?__ExceptionPtrDestroy@@YAXPEAX@Z + */ +void __cdecl __ExceptionPtrDestroy(exception_ptr *ep) +{ + TRACE("(%p)\n", ep); + + if (!ep->rec) + return; + + if (!InterlockedDecrement(ep->ref)) + { + if (ep->rec->ExceptionCode == CXX_EXCEPTION) + { + const cxx_exception_type *type = (void*)ep->rec->ExceptionInformation[2]; + void *obj = (void*)ep->rec->ExceptionInformation[1]; + + if (type && type->destructor) call_dtor(type, type->destructor, obj); + HeapFree(GetProcessHeap(), 0, obj); + } + + HeapFree(GetProcessHeap(), 0, ep->rec); + HeapFree(GetProcessHeap(), 0, ep->ref); + } +} + +/********************************************************************* + * ?__ExceptionPtrCopy@@YAXPAXPBX@Z + * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z + */ +void __cdecl __ExceptionPtrCopy(exception_ptr *ep, const exception_ptr *copy) +{ + TRACE("(%p %p)\n", ep, copy); + + /* don't destroy object stored in ep */ + *ep = *copy; + if (ep->ref) + InterlockedIncrement(copy->ref); +} + +/********************************************************************* + * ?__ExceptionPtrAssign@@YAXPAXPBX@Z + * ?__ExceptionPtrAssign@@YAXPEAXPEBX@Z + */ +void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign) +{ + TRACE("(%p %p)\n", ep, assign); + + /* don't destroy object stored in ep */ + if (ep->ref) + InterlockedDecrement(ep->ref); + + *ep = *assign; + if (ep->ref) + InterlockedIncrement(ep->ref); +} + +/********************************************************************* + * ?__ExceptionPtrRethrow@@YAXPBX@Z + * ?__ExceptionPtrRethrow@@YAXPEBX@Z + */ +void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep) +{ + TRACE("(%p)\n", ep); + + if (!ep->rec) + { + static const char *exception_msg = "bad exception"; + exception e; + + exception_ctor(&e, &exception_msg); + _CxxThrowException(&e, &eexception_exception_type); + return; + } + + RaiseException(ep->rec->ExceptionCode, ep->rec->ExceptionFlags & (~EH_UNWINDING), + 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 + +/********************************************************************* + * ?__ExceptionPtrCurrentException@@YAXPAX@Z + * ?__ExceptionPtrCurrentException@@YAXPEAX@Z + */ +#ifndef __x86_64__ +void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep) +{ + EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record; + + TRACE("(%p)\n", ep); + + if (!rec) + { + ep->rec = NULL; + ep->ref = NULL; + return; + } + + ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); + ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); + + *ep->rec = *rec; + *ep->ref = 1; + + if (ep->rec->ExceptionCode == CXX_EXCEPTION) + { + const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2]; + const cxx_type_info *ti; + void **data, *obj; + + ti = et->type_info_table->info[0]; + data = HeapAlloc(GetProcessHeap(), 0, ti->size); + + obj = (void*)ep->rec->ExceptionInformation[1]; + if (ti->flags & CLASS_IS_SIMPLE_TYPE) + { + memcpy(data, obj, ti->size); + if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); + } + else if (ti->copy_ctor) + { + call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj), + ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); + } + else + memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size); + ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; + } + return; +} +#else +void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep) +{ + EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record; + + TRACE("(%p)\n", ep); + + if (!rec) + { + ep->rec = NULL; + ep->ref = NULL; + return; + } + + ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); + ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); + + *ep->rec = *rec; + *ep->ref = 1; + + if (ep->rec->ExceptionCode == CXX_EXCEPTION) + { + const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2]; + const cxx_type_info *ti; + void **data, *obj; + char *base = RtlPcToFileHeader((void*)et, (void**)&base); + + ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + et->type_info_table))->info[0]); + data = HeapAlloc(GetProcessHeap(), 0, ti->size); + + obj = (void*)ep->rec->ExceptionInformation[1]; + if (ti->flags & CLASS_IS_SIMPLE_TYPE) + { + memcpy(data, obj, ti->size); + if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); + } + else if (ti->copy_ctor) + { + call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj), + ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); + } + else + memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size); + ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; + } + return; +} +#endif + +#if _MSVCR_VER >= 110 +/********************************************************************* + * ?__ExceptionPtrToBool@@YA_NPBX@Z + * ?__ExceptionPtrToBool@@YA_NPEBX@Z + */ +bool __cdecl __ExceptionPtrToBool(exception_ptr *ep) +{ + return !!ep->rec; +} +#endif + +/********************************************************************* + * ?__ExceptionPtrCopyException@@YAXPAXPBX1@Z + * ?__ExceptionPtrCopyException@@YAXPEAXPEBX1@Z + */ +#ifndef __x86_64__ +void __cdecl __ExceptionPtrCopyException(exception_ptr *ep, + exception *object, const cxx_exception_type *type) +{ + const cxx_type_info *ti; + void **data; + + __ExceptionPtrDestroy(ep); + + ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); + ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); + *ep->ref = 1; + + memset(ep->rec, 0, sizeof(EXCEPTION_RECORD)); + ep->rec->ExceptionCode = CXX_EXCEPTION; + ep->rec->ExceptionFlags = EH_NONCONTINUABLE; + ep->rec->NumberParameters = 3; + ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6; + ep->rec->ExceptionInformation[2] = (ULONG_PTR)type; + + ti = type->type_info_table->info[0]; + data = HeapAlloc(GetProcessHeap(), 0, ti->size); + if (ti->flags & CLASS_IS_SIMPLE_TYPE) + { + memcpy(data, object, ti->size); + if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); + } + else if (ti->copy_ctor) + { + call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, object), + ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); + } + else + memcpy(data, get_this_pointer(&ti->offsets, object), ti->size); + ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; +} +#else +void __cdecl __ExceptionPtrCopyException(exception_ptr *ep, + exception *object, const cxx_exception_type *type) +{ + const cxx_type_info *ti; + void **data; + char *base; + + RtlPcToFileHeader((void*)type, (void**)&base); + __ExceptionPtrDestroy(ep); + + ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); + ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); + *ep->ref = 1; + + memset(ep->rec, 0, sizeof(EXCEPTION_RECORD)); + ep->rec->ExceptionCode = CXX_EXCEPTION; + ep->rec->ExceptionFlags = EH_NONCONTINUABLE; + ep->rec->NumberParameters = 4; + ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6; + ep->rec->ExceptionInformation[2] = (ULONG_PTR)type; + ep->rec->ExceptionInformation[3] = (ULONG_PTR)base; + + ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + type->type_info_table))->info[0]); + data = HeapAlloc(GetProcessHeap(), 0, ti->size); + if (ti->flags & CLASS_IS_SIMPLE_TYPE) + { + memcpy(data, object, ti->size); + if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); + } + else if (ti->copy_ctor) + { + call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, object), + ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); + } + else + memcpy(data, get_this_pointer(&ti->offsets, object), ti->size); + ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; +} +#endif + +bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr *ep2) +{ + return ep1->rec == ep2->rec; +} diff --git a/dlls/msvcrt/main.c b/dlls/msvcrt/main.c index db8554668ad..607962807fd 100644 --- a/dlls/msvcrt/main.c +++ b/dlls/msvcrt/main.c @@ -117,6 +117,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) msvcrt_init_signals(); #if _MSVCR_VER >= 100 && _MSVCR_VER <= 120 msvcrt_init_concurrency(hinstDLL); + msvcrt_init_exception_ptr(hinstDLL); #endif #if _MSVCR_VER == 0 /* don't allow unloading msvcrt, we can't setup file handles twice */ diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 1d965ff8ffc..5117b52cd2b 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -235,6 +235,7 @@ extern void msvcrt_init_clock(void) DECLSPEC_HIDDEN; #if _MSVCR_VER >= 100 extern void msvcrt_init_concurrency(void*) DECLSPEC_HIDDEN; extern void msvcrt_free_concurrency(void) DECLSPEC_HIDDEN; +extern void msvcrt_init_exception_ptr(void*) DECLSPEC_HIDDEN; extern void msvcrt_free_scheduler_thread(void) DECLSPEC_HIDDEN; #endif
diff --git a/dlls/msvcrtd/Makefile.in b/dlls/msvcrtd/Makefile.in index bd4f78729d0..045b9092766 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 \
From: Torge Matthies tmatthies@codeweavers.com
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/msvcrt/exception_ptr.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/dlls/msvcrt/exception_ptr.c b/dlls/msvcrt/exception_ptr.c index 7eddfb98341..74eb49e3618 100644 --- a/dlls/msvcrt/exception_ptr.c +++ b/dlls/msvcrt/exception_ptr.c @@ -149,15 +149,9 @@ static inline void call_copy_ctor( void *func, void *this, void *src, int has_vb } #endif
-/********************************************************************* - * ?__ExceptionPtrCurrentException@@YAXPAX@Z - * ?__ExceptionPtrCurrentException@@YAXPEAX@Z - */ #ifndef __x86_64__ -void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep) +static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) { - EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record; - TRACE("(%p)\n", ep);
if (!rec) @@ -200,10 +194,8 @@ void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep) return; } #else -void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep) +static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) { - EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record; - TRACE("(%p)\n", ep);
if (!rec) @@ -248,6 +240,16 @@ void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep) } #endif
+/********************************************************************* + * ?__ExceptionPtrCurrentException@@YAXPAX@Z + * ?__ExceptionPtrCurrentException@@YAXPEAX@Z + */ +void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep) +{ + TRACE("(%p)\n", ep); + exception_ptr_from_record(ep, msvcrt_get_thread_data()->exc_record); +} + #if _MSVCR_VER >= 110 /********************************************************************* * ?__ExceptionPtrToBool@@YA_NPBX@Z
From: Torge Matthies tmatthies@codeweavers.com
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/msvcrt/concurrency.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-)
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 06348173eef..08a56bf11d7 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -700,29 +700,38 @@ static Context* get_current_context(void) return ret; }
+static Scheduler* get_scheduler_from_context(Context *ctx) +{ + ExternalContextBase *context = (ExternalContextBase*)ctx; + + if (context->context.vtable != &ExternalContextBase_vtable) + return NULL; + return context->scheduler.scheduler; +} + static Scheduler* try_get_current_scheduler(void) { - ExternalContextBase *context = (ExternalContextBase*)try_get_current_context(); + Context *context = try_get_current_context(); + Scheduler *ret;
if (!context) return NULL;
- if (context->context.vtable != &ExternalContextBase_vtable) { + ret = get_scheduler_from_context(context); + if (!ret) ERR("unknown context set\n"); - return NULL; - } - return context->scheduler.scheduler; + return ret; }
static Scheduler* get_current_scheduler(void) { - ExternalContextBase *context = (ExternalContextBase*)get_current_context(); + Context *context = get_current_context(); + Scheduler *ret;
- if (context->context.vtable != &ExternalContextBase_vtable) { + ret = get_scheduler_from_context(context); + if (!ret) ERR("unknown context set\n"); - return NULL; - } - return context->scheduler.scheduler; + return ret; }
/* ?CurrentContext@Context@Concurrency@@SAPAV12@XZ */
From: Torge Matthies tmatthies@codeweavers.com
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/msvcrt/concurrency.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 08a56bf11d7..615b2bef4a1 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -91,6 +91,7 @@ struct scheduler_list {
typedef struct { Context context; + LONG refcount; struct scheduler_list scheduler; unsigned int id; union allocator_cache_entry *allocator_cache[8]; @@ -848,6 +849,11 @@ static void ExternalContextBase_dtor(ExternalContextBase *this) union allocator_cache_entry *next, *cur; int i;
+ if (InterlockedDecrement(&this->refcount)) { + TRACE("skipping dtor: refcount not zero\n"); + return; + } + /* TODO: move the allocator cache to scheduler so it can be reused */ for(i=0; i<ARRAY_SIZE(this->allocator_cache); i++) { for(cur = this->allocator_cache[i]; cur; cur=next) { @@ -893,6 +899,7 @@ static void ExternalContextBase_ctor(ExternalContextBase *this)
memset(this, 0, sizeof(*this)); this->context.vtable = &ExternalContextBase_vtable; + this->refcount = 1; this->id = InterlockedIncrement(&context_id);
create_default_scheduler();
From: Torge Matthies tmatthies@codeweavers.com
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/concrt140/Makefile.in | 4 +- dlls/msvcr120/tests/msvcr120.c | 6 +- dlls/msvcrt/concurrency.c | 166 +++++++++++++++++++++++++++++++-- dlls/msvcrt/cxx.h | 5 + dlls/msvcrt/exception_ptr.c | 32 ++++++- 5 files changed, 199 insertions(+), 14 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/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index ac35076af03..24e4914d98a 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -170,7 +170,7 @@ typedef struct _StructuredTaskCollection Context *context; volatile LONG count; volatile LONG finished; - void *unk4; + void *exception; void *event; } _StructuredTaskCollection;
@@ -1439,8 +1439,8 @@ static void test_StructuredTaskCollection(void) "_StructuredTaskCollection ctor set wrong count: %ld != 0\n", task_coll.count); ok(task_coll.finished == LONG_MIN, "_StructuredTaskCollection ctor set wrong finished: %ld != %ld\n", task_coll.finished, LONG_MIN); - ok(task_coll.unk4 == NULL, - "_StructuredTaskCollection ctor set wrong unk4: %p != NULL\n", task_coll.unk4); + ok(task_coll.exception == NULL, + "_StructuredTaskCollection ctor set wrong exception: %p != NULL\n", task_coll.exception);
chore_start_evt = CreateEventW(NULL, TRUE, FALSE, NULL); ok(chore_start_evt != NULL, "CreateEvent failed: 0x%lx\n", GetLastError()); diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 615b2bef4a1..6adc5e90d73 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -20,10 +20,14 @@
#include <stdarg.h> #include <stdbool.h> +#include <malloc.h>
#include "windef.h" +#include "winbase.h" #include "winternl.h" #include "wine/debug.h" +#include "wine/exception.h" +#include "wine/list.h" #include "msvcrt.h" #include "cxx.h"
@@ -89,12 +93,21 @@ struct scheduler_list { struct scheduler_list *next; };
+struct _UnrealizedChore; + +struct scheduled_chore { + struct list entry; + struct _UnrealizedChore *chore; +}; + typedef struct { Context context; LONG refcount; struct scheduler_list scheduler; unsigned int id; union allocator_cache_entry *allocator_cache[8]; + struct list scheduled_chores; + CRITICAL_SECTION scheduled_chores_cs; } ExternalContextBase; extern const vtable_ptr ExternalContextBase_vtable; static void ExternalContextBase_ctor(ExternalContextBase*); @@ -165,14 +178,27 @@ typedef struct yield_func yield_func; } SpinWait;
-typedef struct +struct _StructuredTaskCollection; + +typedef struct _UnrealizedChore { - char dummy; + const vtable_ptr *vtable; + void (__cdecl *chore_proc)(struct _UnrealizedChore*); + struct _StructuredTaskCollection *task_collection; + void (__cdecl *chore_wrapper)(struct _UnrealizedChore*); + void *unk[6]; } _UnrealizedChore;
-typedef struct +typedef struct _StructuredTaskCollection { - char dummy; + void *unk1; + unsigned int unk2; + void *unk3; + Context *context; + volatile LONG count; + volatile LONG finished; + void *exception; + void *event; } _StructuredTaskCollection;
/* keep in sync with msvcp90/msvcp90.h */ @@ -630,9 +656,7 @@ DEFINE_RTTI_DATA1(scheduler_resource_allocation_error, 0, &cexception_rtti_base_ DEFINE_CXX_DATA1(improper_lock, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(improper_scheduler_attach, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(improper_scheduler_detach, &cexception_cxx_type_info, cexception_dtor) -#ifdef __x86_64__ DEFINE_CXX_DATA1(invalid_multiple_scheduling, &cexception_cxx_type_info, cexception_dtor) -#endif DEFINE_CXX_DATA1(invalid_scheduler_policy_key, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(invalid_scheduler_policy_thread_specification, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(invalid_scheduler_policy_value, &cexception_cxx_type_info, cexception_dtor) @@ -843,6 +867,11 @@ bool __thiscall ExternalContextBase_IsSynchronouslyBlocked(const ExternalContext return FALSE; }
+static void ExternalContextBase_addref(ExternalContextBase *this) +{ + InterlockedIncrement(&this->refcount); +} + static void ExternalContextBase_dtor(ExternalContextBase *this) { struct scheduler_list *scheduler_cur, *scheduler_next; @@ -871,6 +900,12 @@ static void ExternalContextBase_dtor(ExternalContextBase *this) operator_delete(scheduler_cur); } } + + EnterCriticalSection(&this->scheduled_chores_cs); + if (!list_empty(&this->scheduled_chores)) + ERR("scheduled chore list is not empty\n"); + LeaveCriticalSection(&this->scheduled_chores_cs); + DeleteCriticalSection(&this->scheduled_chores_cs); }
DEFINE_THISCALL_WRAPPER(ExternalContextBase_vector_dtor, 8) @@ -901,6 +936,8 @@ static void ExternalContextBase_ctor(ExternalContextBase *this) this->context.vtable = &ExternalContextBase_vtable; this->refcount = 1; this->id = InterlockedIncrement(&context_id); + list_init(&this->scheduled_chores); + InitializeCriticalSection(&this->scheduled_chores_cs);
create_default_scheduler(); this->scheduler.scheduler = &default_scheduler->scheduler; @@ -1830,10 +1867,109 @@ DEFINE_THISCALL_WRAPPER(_StructuredTaskCollection_dtor, 4) void __thiscall _StructuredTaskCollection_dtor(_StructuredTaskCollection *this) { FIXME("(%p): stub!\n", this); + if (this->context && this->context->vtable == &ExternalContextBase_vtable) + ExternalContextBase_dtor((ExternalContextBase*)this->context); }
#endif /* _MSVCR_VER >= 120 */
+static void CALLBACK chore_wrapper_finally(BOOL normal, void *data) +{ + _UnrealizedChore *chore = data; + LONG prev_finished, new_finished; + volatile LONG *ptr; + + TRACE("(%u %p)\n", normal, data); + + if (!chore->task_collection) + return; + ptr = &chore->task_collection->finished; + chore->task_collection = NULL; + + do { + prev_finished = *ptr; + if (prev_finished == 0x80000000) + new_finished = 1; + else + new_finished = prev_finished + 1; + } while (InterlockedCompareExchange(ptr, new_finished, prev_finished) + != prev_finished); +} + +static void __cdecl chore_wrapper(_UnrealizedChore *chore) +{ + TRACE("(%p)\n", chore); + + __TRY + { + if (chore->chore_proc) + chore->chore_proc(chore); + } + __FINALLY_CTX(chore_wrapper_finally, chore) +} + +static void __cdecl _StructuredTaskCollection_scheduler_cb(void *data) +{ + ExternalContextBase *context = data; + struct list *entry; + struct scheduled_chore *sc; + _UnrealizedChore *chore; + + TRACE("(%p)\n", context); + + EnterCriticalSection(&context->scheduled_chores_cs); + entry = list_head(&context->scheduled_chores); + if (entry) + list_remove(entry); + LeaveCriticalSection(&context->scheduled_chores_cs); + if (!entry) + return; + ExternalContextBase_dtor(context); + + sc = LIST_ENTRY(entry, struct scheduled_chore, entry); + chore = sc->chore; + operator_delete(sc); + + chore->chore_wrapper(chore); +} + +static bool schedule_chore(_StructuredTaskCollection *this, + _UnrealizedChore *chore, ExternalContextBase **context) +{ + struct scheduled_chore *sc; + + if (chore->task_collection) { + invalid_multiple_scheduling e; + invalid_multiple_scheduling_ctor_str(&e, "Chore scheduled multiple times"); + _CxxThrowException(&e, &invalid_multiple_scheduling_exception_type); + return FALSE; + } + + *context = (ExternalContextBase*)this->context; + if (!*context) { + *context = (ExternalContextBase*)get_current_context(); + if ((*context)->context.vtable != &ExternalContextBase_vtable) { + ERR("unknown context set\n"); + return FALSE; + } + ExternalContextBase_addref(*context); + this->context = (Context*)*context; + } + + sc = operator_new(sizeof(*sc)); + sc->chore = chore; + + chore->task_collection = this; + chore->chore_wrapper = chore_wrapper; + InterlockedIncrement(&this->count); + + ExternalContextBase_addref(*context); + EnterCriticalSection(&(*context)->scheduled_chores_cs); + list_add_head(&(*context)->scheduled_chores, &sc->entry); + LeaveCriticalSection(&(*context)->scheduled_chores_cs); + return TRUE; +} + #if _MSVCR_VER >= 110
/* ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAAXPAV_UnrealizedChore@23@PAVlocation@3@@Z */ @@ -1844,7 +1980,14 @@ void __thiscall _StructuredTaskCollection__Schedule_loc( _StructuredTaskCollection *this, _UnrealizedChore *chore, /*location*/void *placement) { - FIXME("(%p %p %p): stub!\n", this, chore, placement); + ExternalContextBase *context; + + FIXME("(%p %p %p): semi-stub\n", this, chore, placement); + + if (schedule_chore(this, chore, &context)) + call_Scheduler_ScheduleTask_loc( + get_scheduler_from_context((Context*)context), + _StructuredTaskCollection_scheduler_cb, context, placement); }
#endif /* _MSVCR_VER >= 110 */ @@ -1856,7 +1999,14 @@ DEFINE_THISCALL_WRAPPER(_StructuredTaskCollection__Schedule, 8) void __thiscall _StructuredTaskCollection__Schedule( _StructuredTaskCollection *this, _UnrealizedChore *chore) { - FIXME("(%p %p): stub!\n", this, chore); + ExternalContextBase *context; + + TRACE("(%p %p)\n", this, chore); + + if (schedule_chore(this, chore, &context)) + call_Scheduler_ScheduleTask( + get_scheduler_from_context((Context*)context), + _StructuredTaskCollection_scheduler_cb, context); }
/* ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z */ diff --git a/dlls/msvcrt/cxx.h b/dlls/msvcrt/cxx.h index 047bd5610a9..7bbdc4a2a77 100644 --- a/dlls/msvcrt/cxx.h +++ b/dlls/msvcrt/cxx.h @@ -314,3 +314,8 @@ typedef struct EXCEPTION_RECORD *rec; LONG *ref; /* not binary compatible with native msvcr100 */ } exception_ptr; + +void exception_ptr_from_record(exception_ptr*,EXCEPTION_RECORD*) DECLSPEC_HIDDEN; + +void __cdecl __ExceptionPtrCreate(exception_ptr*); +void __cdecl __ExceptionPtrDestroy(exception_ptr*); diff --git a/dlls/msvcrt/exception_ptr.c b/dlls/msvcrt/exception_ptr.c index 74eb49e3618..675ea7664f7 100644 --- a/dlls/msvcrt/exception_ptr.c +++ b/dlls/msvcrt/exception_ptr.c @@ -12,6 +12,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
/* std::exception_ptr class helpers */
+#ifndef _CONCRT + typedef exception eexception; CREATE_EXCEPTION_OBJECT(eexception)
@@ -26,6 +28,8 @@ void msvcrt_init_exception_ptr(void *base) #endif }
+#endif + /********************************************************************* * ?__ExceptionPtrCreate@@YAXPAX@Z * ?__ExceptionPtrCreate@@YAXPEAX@Z @@ -83,6 +87,8 @@ void __cdecl __ExceptionPtrDestroy(exception_ptr *ep) } }
+#ifndef _CONCRT + /********************************************************************* * ?__ExceptionPtrCopy@@YAXPAXPBX@Z * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z @@ -136,8 +142,26 @@ void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep) ep->rec->NumberParameters, ep->rec->ExceptionInformation); }
+#endif + #ifdef __i386__ extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase ); +#ifdef _CONCRT +__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" ); +#endif #else static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase ) { @@ -150,7 +174,7 @@ static inline void call_copy_ctor( void *func, void *this, void *src, int has_vb #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);
@@ -194,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);
@@ -240,6 +264,8 @@ static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) } #endif
+#ifndef _CONCRT + /********************************************************************* * ?__ExceptionPtrCurrentException@@YAXPAX@Z * ?__ExceptionPtrCurrentException@@YAXPEAX@Z @@ -346,3 +372,5 @@ bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr { return ep1->rec == ep2->rec; } + +#endif