From 4d4d028a67ac91b8b7c07d55b6376d16b1c512f2 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Wed, 28 Nov 2018 11:19:48 -0800 Subject: [PATCH] Switch to preemptive mode before calling COM (#21238) * Switch to preemptive mode before calling COM COM can call back the runtime via RCW that leads to contract violations Fixes #20373 * Fix one places --- src/vm/olevariant.cpp | 153 ++++++++++++++++++++++++++------------------------ 1 file changed, 81 insertions(+), 72 deletions(-) diff --git a/src/vm/olevariant.cpp b/src/vm/olevariant.cpp index 330710b..4188a22 100644 --- a/src/vm/olevariant.cpp +++ b/src/vm/olevariant.cpp @@ -2543,7 +2543,10 @@ void OleVariant::MarshalRecordVariantOleToCom(VARIANT *pOleVariant, // Go to the registry to find the value class associated // with the record's guid. GUID guid; - IfFailThrow(pRecInfo->GetGuid(&guid)); + { + GCX_PREEMP(); + IfFailThrow(pRecInfo->GetGuid(&guid)); + } MethodTable *pValueClass = GetValueTypeForGUID(guid); if (!pValueClass) COMPlusThrow(kArgumentException, IDS_EE_CANNOT_MAP_TO_MANAGED_VC); @@ -4256,87 +4259,89 @@ SAFEARRAY *OleVariant::CreateSafeArrayDescriptorForArrayRef(BASEARRAYREF *pArray ULONG nRank = (*pArrayRef)->GetRank(); SafeArrayPtrHolder pSafeArray = NULL; - SafeComHolder pITI = NULL; - SafeComHolder pRecInfo = NULL; - IfFailThrow(SafeArrayAllocDescriptorEx(vt, nRank, &pSafeArray)); + IfFailThrow(SafeArrayAllocDescriptorEx(vt, nRank, &pSafeArray)); - switch (vt) + switch (vt) + { + case VT_VARIANT: { - case VT_VARIANT: - { - // OleAut32.dll only sets FADF_HASVARTYPE, but VB says we also need to set - // the FADF_VARIANT bit for this safearray to destruct properly. OleAut32 - // doesn't want to change their code unless there's a strong reason, since - // it's all "black magic" anyway. - pSafeArray->fFeatures |= FADF_VARIANT; - break; - } + // OleAut32.dll only sets FADF_HASVARTYPE, but VB says we also need to set + // the FADF_VARIANT bit for this safearray to destruct properly. OleAut32 + // doesn't want to change their code unless there's a strong reason, since + // it's all "black magic" anyway. + pSafeArray->fFeatures |= FADF_VARIANT; + break; + } - case VT_BSTR: - { - pSafeArray->fFeatures |= FADF_BSTR; - break; - } + case VT_BSTR: + { + pSafeArray->fFeatures |= FADF_BSTR; + break; + } - case VT_UNKNOWN: - { - pSafeArray->fFeatures |= FADF_UNKNOWN; - break; - } + case VT_UNKNOWN: + { + pSafeArray->fFeatures |= FADF_UNKNOWN; + break; + } - case VT_DISPATCH: - { - pSafeArray->fFeatures |= FADF_DISPATCH; - break; - } + case VT_DISPATCH: + { + pSafeArray->fFeatures |= FADF_DISPATCH; + break; + } - case VT_RECORD: - { - pSafeArray->fFeatures |= FADF_RECORD; - break; - } + case VT_RECORD: + { + pSafeArray->fFeatures |= FADF_RECORD; + break; } + } - // - // Fill in bounds - // + // + // Fill in bounds + // - SAFEARRAYBOUND *bounds = pSafeArray->rgsabound; - SAFEARRAYBOUND *boundsEnd = bounds + nRank; - SIZE_T cElements; + SAFEARRAYBOUND *bounds = pSafeArray->rgsabound; + SAFEARRAYBOUND *boundsEnd = bounds + nRank; + SIZE_T cElements; - if (!(*pArrayRef)->IsMultiDimArray()) - { - bounds[0].cElements = nElem; - bounds[0].lLbound = 0; - cElements = nElem; - } - else - { - const INT32 *count = (*pArrayRef)->GetBoundsPtr() + nRank - 1; - const INT32 *lower = (*pArrayRef)->GetLowerBoundsPtr() + nRank - 1; + if (!(*pArrayRef)->IsMultiDimArray()) + { + bounds[0].cElements = nElem; + bounds[0].lLbound = 0; + cElements = nElem; + } + else + { + const INT32 *count = (*pArrayRef)->GetBoundsPtr() + nRank - 1; + const INT32 *lower = (*pArrayRef)->GetLowerBoundsPtr() + nRank - 1; - cElements = 1; - while (bounds < boundsEnd) - { - bounds->lLbound = *lower--; - bounds->cElements = *count--; - cElements *= bounds->cElements; - bounds++; - } + cElements = 1; + while (bounds < boundsEnd) + { + bounds->lLbound = *lower--; + bounds->cElements = *count--; + cElements *= bounds->cElements; + bounds++; } + } - pSafeArray->cbElements = (unsigned)GetElementSizeForVarType(vt, pInterfaceMT); + pSafeArray->cbElements = (unsigned)GetElementSizeForVarType(vt, pInterfaceMT); - // If the SAFEARRAY contains VT_RECORD's, then we need to set the - // IRecordInfo. - if (vt == VT_RECORD) - { - IfFailThrow(GetITypeInfoForEEClass(pInterfaceMT, &pITI)); - IfFailThrow(GetRecordInfoFromTypeInfo(pITI, &pRecInfo)); - IfFailThrow(SafeArraySetRecordInfo(pSafeArray, pRecInfo)); - } + // If the SAFEARRAY contains VT_RECORD's, then we need to set the + // IRecordInfo. + if (vt == VT_RECORD) + { + GCX_PREEMP(); + + SafeComHolder pITI; + SafeComHolder pRecInfo; + IfFailThrow(GetITypeInfoForEEClass(pInterfaceMT, &pITI)); + IfFailThrow(GetRecordInfoFromTypeInfo(pITI, &pRecInfo)); + IfFailThrow(SafeArraySetRecordInfo(pSafeArray, pRecInfo)); + } pSafeArray.SuppressRelease(); RETURN pSafeArray; @@ -5027,14 +5032,18 @@ TypeHandle OleVariant::GetElementTypeForRecordSafeArray(SAFEARRAY* pSafeArray) CONTRACTL_END; HRESULT hr = S_OK; - SafeComHolder pRecInfo = NULL; - GUID guid; + GUID guid; + { + GCX_PREEMP(); + + SafeComHolder pRecInfo; IfFailThrow(SafeArrayGetRecordInfo(pSafeArray, &pRecInfo)); IfFailThrow(pRecInfo->GetGuid(&guid)); - MethodTable *pValueClass = GetValueTypeForGUID(guid); - if (!pValueClass) - COMPlusThrow(kArgumentException, IDS_EE_CANNOT_MAP_TO_MANAGED_VC); + } + MethodTable *pValueClass = GetValueTypeForGUID(guid); + if (!pValueClass) + COMPlusThrow(kArgumentException, IDS_EE_CANNOT_MAP_TO_MANAGED_VC); return TypeHandle(pValueClass); } -- 2.7.4