diff --git a/stl/src/xonce.cpp b/stl/src/xonce.cpp index 5c6a5f9c2f9..5815b531471 100644 --- a/stl/src/xonce.cpp +++ b/stl/src/xonce.cpp @@ -13,8 +13,17 @@ _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Execute_once( once_flag& _Flag, _Execute_once_fp_t _Callback, void* _Pv) noexcept { // wrap Win32 InitOnceExecuteOnce() static_assert(sizeof(_Flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); + // _Execute_once_fp_t and PINIT_ONCE_FN differ in type signature, therefore + // we introduce _Xfg_trampoline which has PINIT_ONCE_FN's type signature and + // calls into _Callback as an _Execute_once_fp_t for XFG compatibility. + + PINIT_ONCE_FN _Xfg_trampoline = [](PINIT_ONCE _InitOnce, PVOID _Parameter, PVOID* _Context) { + const auto _Callback = reinterpret_cast<_Execute_once_fp_t>(_Context); + return static_cast(_Callback(_InitOnce, _Parameter, nullptr)); + }; + return __crtInitOnceExecuteOnce( - reinterpret_cast(&_Flag._Opaque), reinterpret_cast(_Callback), _Pv, nullptr); + reinterpret_cast(&_Flag._Opaque), _Xfg_trampoline, _Pv, reinterpret_cast(_Callback)); } [[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL