@@ -364,7 +364,7 @@ UINT32 CLRToCOMEventCallWorker(ComPlusMethodFrame* pFrame, ComPlusCallMethodDesc
364364 return 0 ;
365365}
366366
367- CallsiteDetails CreateCallsiteDetails (_In_ FramedMethodFrame *pFrame)
367+ static CallsiteDetails CreateCallsiteDetails (_In_ FramedMethodFrame *pFrame)
368368{
369369 CONTRACTL
370370 {
@@ -442,10 +442,20 @@ CallsiteDetails CreateCallsiteDetails(_In_ FramedMethodFrame *pFrame)
442442 SigTypeContext::InitTypeContext (pMD, actualType, &typeContext);
443443 }
444444
445+ // If the signature is marked preserve sig, then the return
446+ // is required to be an HRESULT, per COM rules. We set a flag to
447+ // indicate this state to avoid issues when a C# developer defines
448+ // an HRESULT in C# as a ValueClass with a single int field. This
449+ // is convenient but does violate the COM ABI. Setting the flag
450+ // lets us permit this convention and allow either a 4 byte primitive
451+ // or the commonly used C# type "struct HResult { int Value; }".
452+ if (IsMiPreserveSig (pMD->GetImplAttrs ()))
453+ callsiteFlags |= CallsiteDetails::HResultReturn;
454+
445455 _ASSERTE (!signature.IsEmpty () && pModule != nullptr );
446456
447457 // Create details
448- return CallsiteDetails{ { signature, pModule, &typeContext }, pFrame, pMD, fIsDelegate };
458+ return CallsiteDetails{ { signature, pModule, &typeContext }, pFrame, pMD, fIsDelegate , callsiteFlags };
449459}
450460
451461UINT32 CLRToCOMLateBoundWorker (
0 commit comments