未验证 提交 8f481c0e 编写于 作者: H Huo Yaoyuan 提交者: GitHub

Guard COM exception marshaling under FEATURE_COMINTEROP (#70431)

* Guard FillVariant under FEATURE_COMINTEROP

* Guard COM exception information under FEATURE_COMINTEROP

* Remove TypeNameBuilder::ToString(BSTR)

* Remove the whole EECOMException type when COM interop is disabled

* Guard more ExceptionData usage under FEATURE_COMINTEROP

* Guard BSTRHolder under FEATURE_COMINTEROP

* Remove Unix BSTR simulation in palrt

* Add guard to COMException::GetMessage
上级 1fe9c0bb
......@@ -165,8 +165,6 @@ nativeStringResourceTable_mscorrc
#Sleep
#SleepEx
#SwitchToThread
#SysAllocStringLen
#SysFreeString
#TerminateProcess
#VirtualAlloc
#VirtualAllocExNuma
......
......@@ -444,7 +444,9 @@ class COMException : public HRException
// Virtual overrides
IErrorInfo *GetErrorInfo();
#ifdef FEATURE_COMINTEROP
void GetMessage(SString &result);
#endif
protected:
virtual Exception *CloneHelper()
......
......@@ -4262,9 +4262,11 @@ INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);)
BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommitedStack);
#ifdef FEATURE_COMINTEROP
FORCEINLINE void HolderSysFreeString(BSTR str) { CONTRACT_VIOLATION(ThrowsViolation); SysFreeString(str); }
typedef Wrapper<BSTR, DoNothing, HolderSysFreeString> BSTRHolder;
#endif
BOOL IsIPInModule(PTR_VOID pModuleBaseAddress, PCODE ip);
......
......@@ -3147,87 +3147,6 @@ mdModule MDInternalRO::GetModuleFromScope(void)
return TokenFromRid(1, mdtModule);
} // MDInternalRO::GetModuleFromScope
//*****************************************************************************
// Fill a variant given a MDDefaultValue
// This routine will create a bstr if the ELEMENT_TYPE of default value is STRING
//*****************************************************************************
__checkReturn
HRESULT _FillVariant(
MDDefaultValue *pMDDefaultValue,
VARIANT *pvar)
{
HRESULT hr = NOERROR;
_ASSERTE(pMDDefaultValue);
switch (pMDDefaultValue->m_bType)
{
case ELEMENT_TYPE_BOOLEAN:
V_VT(pvar) = VT_BOOL;
V_BOOL(pvar) = !!pMDDefaultValue->m_bValue ? VARIANT_TRUE : VARIANT_FALSE;
break;
case ELEMENT_TYPE_I1:
V_VT(pvar) = VT_I1;
V_I1(pvar) = pMDDefaultValue->m_cValue;
break;
case ELEMENT_TYPE_U1:
V_VT(pvar) = VT_UI1;
V_UI1(pvar) = pMDDefaultValue->m_byteValue;
break;
case ELEMENT_TYPE_I2:
V_VT(pvar) = VT_I2;
V_I2(pvar) = pMDDefaultValue->m_sValue;
break;
case ELEMENT_TYPE_U2:
case ELEMENT_TYPE_CHAR: // char is stored as UI2 internally
V_VT(pvar) = VT_UI2;
V_UI2(pvar) = pMDDefaultValue->m_usValue;
break;
case ELEMENT_TYPE_I4:
V_VT(pvar) = VT_I4;
V_I4(pvar) = pMDDefaultValue->m_lValue;
break;
case ELEMENT_TYPE_U4:
V_VT(pvar) = VT_UI4;
V_UI4(pvar) = pMDDefaultValue->m_ulValue;
break;
case ELEMENT_TYPE_R4:
V_VT(pvar) = VT_R4;
V_R4(pvar) = pMDDefaultValue->m_fltValue;
break;
case ELEMENT_TYPE_R8:
V_VT(pvar) = VT_R8;
V_R8(pvar) = pMDDefaultValue->m_dblValue;
break;
case ELEMENT_TYPE_STRING:
// allocated bstr here
V_BSTR(pvar) = ::SysAllocStringLen(pMDDefaultValue->m_wzValue, pMDDefaultValue->m_cbSize / sizeof(WCHAR));
if (V_BSTR(pvar) == NULL)
hr = E_OUTOFMEMORY;
V_VT(pvar) = VT_BSTR;
break;
case ELEMENT_TYPE_CLASS:
V_VT(pvar) = VT_UNKNOWN;
V_UNKNOWN(pvar) = pMDDefaultValue->m_unkValue;
break;
case ELEMENT_TYPE_I8:
V_VT(pvar) = VT_I8;
V_CY(pvar).int64 = pMDDefaultValue->m_llValue;
break;
case ELEMENT_TYPE_U8:
V_VT(pvar) = VT_UI8;
V_CY(pvar).int64 = pMDDefaultValue->m_ullValue;
break;
case ELEMENT_TYPE_VOID:
V_VT(pvar) = VT_EMPTY;
break;
default:
_ASSERTE(!"bad constant value type!");
}
return hr;
} // _FillVariant
//*****************************************************************************
// Fill a variant given a MDDefaultValue
......
......@@ -315,13 +315,6 @@ typedef const OLECHAR* LPCOLESTR;
typedef WCHAR *BSTR;
STDAPI_VIS(DLLEXPORT, BSTR) SysAllocString(const OLECHAR*);
STDAPI_VIS(DLLEXPORT, BSTR) SysAllocStringLen(const OLECHAR*, UINT);
STDAPI_VIS(DLLEXPORT, BSTR) SysAllocStringByteLen(const char *, UINT);
STDAPI_VIS(DLLEXPORT, void) SysFreeString(BSTR);
STDAPI_VIS(DLLEXPORT, UINT) SysStringLen(BSTR);
STDAPI_VIS(DLLEXPORT, UINT) SysStringByteLen(BSTR);
typedef double DATE;
typedef union tagCY {
......
......@@ -2,7 +2,6 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(PALRT_SOURCES
bstr.cpp
coguid.cpp
comem.cpp
guid.cpp
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//
//
// ===========================================================================
// File: bstr.cpp
//
// ===========================================================================
/*++
Abstract:
PALRT BSTR support
Revision History:
--*/
#include "common.h"
#include "intsafe.h"
#define CCH_BSTRMAX 0x7FFFFFFF // 4 + (0x7ffffffb + 1 ) * 2 ==> 0xFFFFFFFC
#define CB_BSTRMAX 0xFFFFFFFa // 4 + (0xfffffff6 + 2) ==> 0xFFFFFFFC
#define WIN32_ALLOC_ALIGN (16 - 1)
inline HRESULT CbSysStringSize(ULONG cchSize, BOOL isByteLen, ULONG *result)
{
if (result == NULL)
return E_INVALIDARG;
// +2 for the null terminator
// + DWORD_PTR to store the byte length of the string
int constant = sizeof(WCHAR) + sizeof(DWORD_PTR) + WIN32_ALLOC_ALIGN;
if (isByteLen)
{
if (SUCCEEDED(ULongAdd(constant, cchSize, result)))
{
*result = *result & ~WIN32_ALLOC_ALIGN;
return NOERROR;
}
}
else
{
ULONG temp = 0; // should not use in-place addition in ULongAdd
if (SUCCEEDED(ULongMult(cchSize, sizeof(WCHAR), &temp)) &&
SUCCEEDED(ULongAdd(temp, constant, result)))
{
*result = *result & ~WIN32_ALLOC_ALIGN;
return NOERROR;
}
}
return INTSAFE_E_ARITHMETIC_OVERFLOW;
}
/***
*BSTR SysAllocStringLen(char*, unsigned int)
*Purpose:
* Allocation a bstr of the given length and initialize with
* the pasted in string
*
*Entry:
* [optional]
*
*Exit:
* return value = BSTR, NULL if the allocation failed.
*
***********************************************************************/
STDAPI_(BSTR) SysAllocStringLen(const OLECHAR *psz, UINT len)
{
BSTR bstr;
DWORD cbTotal = 0;
if (FAILED(CbSysStringSize(len, FALSE, &cbTotal)))
return NULL;
bstr = (OLECHAR *)PAL_malloc(cbTotal);
if(bstr != NULL){
#if defined(HOST_64BIT)
// NOTE: There are some apps which peek back 4 bytes to look at the size of the BSTR. So, in case of 64-bit code,
// we need to ensure that the BSTR length can be found by looking one DWORD before the BSTR pointer.
*(DWORD_PTR *)bstr = (DWORD_PTR) 0;
bstr = (BSTR) ((char *) bstr + sizeof (DWORD));
#endif
*(DWORD FAR*)bstr = (DWORD)len * sizeof(OLECHAR);
bstr = (BSTR) ((char*) bstr + sizeof(DWORD));
if(psz != NULL){
memcpy(bstr, psz, len * sizeof(OLECHAR));
}
bstr[len] = '\0'; // always 0 terminate
}
return bstr;
}
/***
*BSTR SysAllocString(char*)
*Purpose:
* Allocation a bstr using the passed in string
*
*Entry:
* String to create a bstr for
*
*Exit:
* return value = BSTR, NULL if allocation failed
*
***********************************************************************/
STDAPI_(BSTR) SysAllocString(const OLECHAR* psz)
{
if(psz == NULL)
return NULL;
return SysAllocStringLen(psz, (DWORD)wcslen(psz));
}
STDAPI_(BSTR)
SysAllocStringByteLen(const char FAR* psz, unsigned int len)
{
BSTR bstr;
DWORD cbTotal = 0;
if (FAILED(CbSysStringSize(len, TRUE, &cbTotal)))
return FALSE;
bstr = (OLECHAR *)PAL_malloc(cbTotal);
if (bstr != NULL) {
#if defined(HOST_64BIT)
*(DWORD FAR*)((char *)bstr + sizeof (DWORD)) = (DWORD)len;
#else
*(DWORD FAR*)bstr = (DWORD)len;
#endif
bstr = (WCHAR*) ((char*) bstr + sizeof(DWORD_PTR));
if (psz != NULL) {
memcpy(bstr, psz, len);
}
// NULL-terminate with both a narrow and wide zero.
*((char *)bstr + len) = '\0';
*(WCHAR *)((char *)bstr + ((len + 1) & ~1)) = 0;
}
return bstr;
}
/***
*void SysFreeString(BSTR)
*Purpose:
* Free the given BSTR.
*
*Entry:
* bstr = the BSTR to free
*
*Exit:
* None
*
***********************************************************************/
STDAPI_(void) SysFreeString(BSTR bstr)
{
if(bstr == NULL)
return;
free((BYTE *)bstr-sizeof(DWORD_PTR));
}
/***
*unsigned int SysStringLen(BSTR)
*Purpose:
* return the length in characters of the given BSTR.
*
*Entry:
* bstr = the BSTR to return the length of
*
*Exit:
* return value = unsigned int, length in characters.
*
***********************************************************************/
STDAPI_(unsigned int)
SysStringLen(BSTR bstr)
{
if(bstr == NULL)
return 0;
return (unsigned int)((((DWORD FAR*)bstr)[-1]) / sizeof(OLECHAR));
}
/***
*unsigned int SysStringByteLen(BSTR)
*Purpose:
* return the size in bytes of the given BSTR.
*
*Entry:
* bstr = the BSTR to return the size of
*
*Exit:
* return value = unsigned int, size in bytes.
*
***********************************************************************/
STDAPI_(unsigned int)
SysStringByteLen(BSTR bstr)
{
if(bstr == NULL)
return 0;
return (unsigned int)(((DWORD FAR*)bstr)[-1]);
}
extern "C" HRESULT
ErrStringCopy(BSTR bstrSource, BSTR FAR *pbstrOut)
{
if (bstrSource == NULL) {
*pbstrOut = NULL;
return NOERROR;
}
if ((*pbstrOut = SysAllocStringLen(bstrSource,
SysStringLen(bstrSource))) == NULL)
return E_OUTOFMEMORY;
return NOERROR;
}
/***
*PRIVATE HRESULT ErrSysAllocString(char*, BSTR*)
*Purpose:
* This is an implementation of SysAllocString that check for the
* NULL return value and return the corresponding error - E_OUTOFMEMORY.
*
* This is simply a convenience, and this routine is only used
* internally by the oledisp component.
*
*Entry:
* psz = the source string
*
*Exit:
* return value = HRESULT
* S_OK
* E_OUTOFMEMORY
*
* *pbstrOut = the newly allocated BSTR
*
***********************************************************************/
extern "C" HRESULT
ErrSysAllocString(const OLECHAR FAR* psz, BSTR FAR* pbstrOut)
{
if(psz == NULL){
*pbstrOut = NULL;
return NOERROR;
}
if((*pbstrOut = SysAllocString(psz)) == NULL)
return E_OUTOFMEMORY;
return NOERROR;
}
......@@ -1179,7 +1179,9 @@ void MDInfo::DisplayParamInfo(mdParamDef inParamDef)
&nameLen, &flags, &dwCPlusFlags, &pValue, &cbValue);
if (FAILED(hr)) Error("GetParamProps failed.", hr);
#ifdef FEATURE_COMINTEROP
_FillVariant((BYTE)dwCPlusFlags, pValue, cbValue, &defValue);
#endif
char sFlags[STRING_BUFFER_LEN];
sFlags[0] = 0;
......@@ -2950,7 +2952,7 @@ void MDInfo::DisplayCorNativeLink(COR_NATIVE_LINK *pCorNLnk, const char *preFix)
// Fills given varaint with value given in pValue and of type in bCPlusTypeFlag
//
// Taken from MetaInternal.cpp
#ifdef FEATURE_COMINTEROP
HRESULT _FillVariant(
BYTE bCPlusTypeFlag,
const void *pValue,
......@@ -3043,6 +3045,7 @@ HRESULT _FillVariant(
return hr;
} // HRESULT _FillVariant()
#endif // FEATURE_COMINTEROP
void MDInfo::DisplayAssembly()
{
......
......@@ -35,6 +35,8 @@ IErrorInfo *COMException::GetErrorInfo()
return pErrorInfo;
}
#ifdef FEATURE_COMINTEROP
void COMException::GetMessage(SString &string)
{
STATIC_CONTRACT_THROWS;
......@@ -48,3 +50,4 @@ void COMException::GetMessage(SString &string)
}
}
#endif // FEATURE_COMINTEROP
......@@ -1785,6 +1785,7 @@ void DECLSPEC_NORETURN EEFileLoadException::Throw(PEAssembly *parent,
EX_THROW_WITH_INNER(EEFileLoadException, (name, hr), pInnerException);
}
#ifdef FEATURE_COMINTEROP
// ---------------------------------------------------------------------------
// EEComException methods
// ---------------------------------------------------------------------------
......@@ -1873,11 +1874,9 @@ EECOMException::EECOMException(
{
WRAPPER_NO_CONTRACT;
#ifdef FEATURE_COMINTEROP
// Must use another path for managed IErrorInfos...
// note that this doesn't cover out-of-proc managed IErrorInfos.
_ASSERTE(!bCheckInProcCCWTearOff || !IsInProcCCWTearOff(pErrInfo));
#endif // FEATURE_COMINTEROP
m_ED.hr = hr;
m_ED.bstrDescription = NULL;
......@@ -1980,6 +1979,7 @@ OBJECTREF EECOMException::CreateThrowable()
return throwable;
}
#endif // FEATURE_COMINTEROP
// ---------------------------------------------------------------------------
// ObjrefException methods
......
......@@ -379,6 +379,7 @@ private:
#endif // _DEBUG
};
#ifdef FEATURE_COMINTEROP
// ---------------------------------------------------------------------------
// EECOMException is an EE exception subclass composed of COM-generated data.
// Note that you must ensure that the COM data was not derived from a wrapper
......@@ -437,6 +438,7 @@ private:
}
#endif // _DEBUG
};
#endif // FEATURE_COMINTEROP
// ---------------------------------------------------------------------------
// EEFieldException is an EE exception subclass composed of a field
......
......@@ -260,6 +260,8 @@ FCIMPL3(VOID, ExceptionNative::SaveStackTracesFromDeepCopy, Object* pExceptionOb
}
FCIMPLEND
#ifdef FEATURE_COMINTEROP
BSTR BStrFromString(STRINGREF s)
{
CONTRACTL
......@@ -468,8 +470,6 @@ void ExceptionNative::GetExceptionData(OBJECTREF objException, ExceptionData *pE
return;
}
#ifdef FEATURE_COMINTEROP
HRESULT SimpleComCallWrapper::IErrorInfo_hr()
{
WRAPPER_NO_CONTRACT;
......
......@@ -31,7 +31,9 @@
//
//
#ifdef FEATURE_COMINTEROP
void FreeExceptionData(ExceptionData *pedata);
#endif
class ExceptionNative
{
......@@ -44,8 +46,10 @@ public:
static FCDECL3(VOID, SaveStackTracesFromDeepCopy, Object* pExceptionObjectUnsafe, Object *pStackTraceUnsafe, Object *pDynamicMethodsUnsafe);
#ifdef FEATURE_COMINTEROP
// NOTE: caller cleans up any partially initialized BSTRs in pED
static void GetExceptionData(OBJECTREF, ExceptionData *);
#endif
// Note: these are on the PInvoke class to hide these from the user.
static FCDECL0(EXCEPTION_POINTERS*, GetExceptionPointers);
......
......@@ -2959,6 +2959,7 @@ void ResMgrGetString(LPCWSTR wszResourceName, STRINGREF * ppMessage)
}
}
#ifdef FEATURE_COMINTEROP
void FreeExceptionData(ExceptionData *pedata)
{
CONTRACTL
......@@ -2984,6 +2985,7 @@ void FreeExceptionData(ExceptionData *pedata)
if (pedata->bstrHelpFile)
SysFreeString(pedata->bstrHelpFile);
}
#endif // FEATURE_COMINTEROP
void GetExceptionForHR(HRESULT hr, IErrorInfo* pErrInfo, OBJECTREF* pProtectedThrowable)
{
......@@ -8248,10 +8250,12 @@ bool DebugIsEECxxExceptionPointer(void* pv)
EEMessageException boilerplate7;
EEResourceException boilerplate8;
#ifdef FEATURE_COMINTEROP
// EECOMException::~EECOMException calls FreeExceptionData, which is GC_TRIGGERS,
// but it won't trigger in this case because EECOMException's members remain NULL.
CONTRACT_VIOLATION(GCViolation);
EECOMException boilerplate9;
#endif // FEATURE_COMINTEROP
EEFieldException boilerplate10;
EEMethodException boilerplate11;
......@@ -8270,7 +8274,9 @@ bool DebugIsEECxxExceptionPointer(void* pv)
*((TADDR*)&boilerplate6),
*((TADDR*)&boilerplate7),
*((TADDR*)&boilerplate8),
#ifdef FEATURE_COMINTEROP
*((TADDR*)&boilerplate9),
#endif // FEATURE_COMINTEROP
*((TADDR*)&boilerplate10),
*((TADDR*)&boilerplate11),
*((TADDR*)&boilerplate12),
......@@ -11485,27 +11491,14 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, IErrorInfo* pErrInfo, Exce
}
#endif // FEATURE_COMINTEROP
if (pErrInfo != NULL)
_ASSERTE((pErrInfo == NULL) || !"pErrInfo should always be null when FEATURE_COMINTEROP is disabled.");
if (pInnerException == NULL)
{
if (pInnerException == NULL)
{
EX_THROW(EECOMException, (hr, pErrInfo));
}
else
{
EX_THROW_WITH_INNER(EECOMException, (hr, pErrInfo), pInnerException);
}
EX_THROW(EEMessageException, (hr));
}
else
{
if (pInnerException == NULL)
{
EX_THROW(EEMessageException, (hr));
}
else
{
EX_THROW_WITH_INNER(EEMessageException, (hr), pInnerException);
}
EX_THROW_WITH_INNER(EEMessageException, (hr), pInnerException);
}
}
......
......@@ -179,6 +179,7 @@ HRESULT SetupErrorInfo(OBJECTREF pThrownObject)
return hr;
}
#if FEATURE_COMINTEROP
//-------------------------------------------------------------------
// Used to populate ExceptionData with COM data
//-------------------------------------------------------------------
......@@ -212,6 +213,7 @@ void FillExceptionData(
}
}
}
#endif // FEATURE_COMINTEROP
//---------------------------------------------------------------------------
// If pImport has the DefaultDllImportSearchPathsAttribute,
......
......@@ -55,11 +55,11 @@ struct IUnkEntry;
interface IStream;
class ComCallWrapper;
class InteropSyncBlockInfo;
struct ExceptionData;
#endif //FEATURE_COMINTEROP
class FieldDesc;
struct ExceptionData;
//------------------------------------------------------------------
// setup error info for exception object
......@@ -100,12 +100,14 @@ int InternalWideToAnsi(_In_reads_(iNumWideChars) LPCWSTR szWideString, int iNum
//---------------------------------------------------------
CorClassIfaceAttr ReadClassInterfaceTypeCustomAttribute(TypeHandle type);
#ifdef FEATURE_COMINTEROP
//-------------------------------------------------------------------
// Used to populate ExceptionData with COM data
//-------------------------------------------------------------------
void FillExceptionData(
_Inout_ ExceptionData* pedata,
_In_ IErrorInfo* pErrInfo);
#endif // FEATURE_COMINTEROP
//---------------------------------------------------------------------------
// If pImport has the DefaultDllImportSearchPathsAttribute,
......
......@@ -436,21 +436,6 @@ HRESULT TypeNameBuilder::AddAssemblySpec(LPCWSTR szAssemblySpec)
return hr;
}
HRESULT TypeNameBuilder::ToString(BSTR* pszStringRepresentation)
{
WRAPPER_NO_CONTRACT;
if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR | ParseStateBYREF | ParseStateASSEMSPEC))
return Fail();
if (m_instNesting)
return Fail();
*pszStringRepresentation = SysAllocString(m_pStr->GetUnicode());
return S_OK;
}
HRESULT TypeNameBuilder::Clear()
{
CONTRACTL
......
......@@ -48,7 +48,6 @@ private:
HRESULT AddSzArray();
HRESULT AddArray(DWORD rank);
HRESULT AddAssemblySpec(LPCWSTR szAssemblySpec);
HRESULT ToString(BSTR* pszStringRepresentation);
HRESULT Clear();
private:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册