Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,47 @@ private bool CanSetRemoteStackTrace()
return true;
}

#if FEATURE_COMINTEROP
// used by vm
internal string? GetHelpContext(out uint helpContext)
[UnmanagedCallersOnly]
internal static unsafe IntPtr GetDescriptionBstr(Exception* obj, Exception* pException)
{
try
{
string message = obj->Message;
if (string.IsNullOrEmpty(message))
message = obj->GetClassName();

// Allocate the description BSTR.
return Interop.OleAut32.SysAllocStringLen(message, (uint)message.Length);
}
catch (Exception ex)
{
*pException = ex;
return IntPtr.Zero;
}
}

// used by vm
[UnmanagedCallersOnly]
internal static unsafe IntPtr GetSourceBstr(Exception* obj, Exception* pException)
{
try
{
string? source = obj->Source;

return source != null
? Interop.OleAut32.SysAllocStringLen(source, (uint)source.Length)
: IntPtr.Zero;
}
catch (Exception ex)
{
*pException = ex;
return IntPtr.Zero;
}
}

private string? GetHelpContext(out uint helpContext)
{
helpContext = 0;
string? helpFile = HelpLink;
Expand All @@ -283,5 +322,24 @@ private bool CanSetRemoteStackTrace()

return helpFile;
}

// used by vm
[UnmanagedCallersOnly]
internal static unsafe void GetHelpContextBstr(Exception* obj, IntPtr* bstr, uint* helpContext, Exception* pException)
{
try
{
string? helpFile = obj->GetHelpContext(out *helpContext);

*bstr = helpFile != null
? Interop.OleAut32.SysAllocStringLen(helpFile, (uint)helpFile.Length)
: IntPtr.Zero;
}
catch (Exception ex)
{
*pException = ex;
}
}
#endif
}
}
51 changes: 51 additions & 0 deletions src/coreclr/vm/callhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,57 @@ class UnmanagedCallersOnlyCaller final

GCPROTECT_END();
}

template<typename Ret, typename... Args>
Ret InvokeThrowing_Ret(Args... args)
{
CONTRACTL
{
THROWS;
GC_TRIGGERS;
MODE_COOPERATIVE;
}
CONTRACTL_END;

// Sanity check - UnmanagedCallersOnly methods must be in CoreLib.
// See below load level override.
_ASSERTE(_pMD->GetModule()->IsSystem());

// We're invoking an CoreLib method, so lift the restriction on type load limits. These calls are
// limited to CoreLib and only into UnmanagedCallersOnly methods.
OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);

Ret ret;

struct
{
OBJECTREF Exception;
} gc;
gc.Exception = NULL;
GCPROTECT_BEGIN(gc);

{
GCX_PREEMP();

PCODE methodEntry = _pMD->GetSingleCallableAddrOfCodeForUnmanagedCallersOnly();
_ASSERTE(methodEntry != (PCODE)NULL);

// Cast the function pointer to the appropriate type.
// Note that we append the exception handle argument.
auto fptr = reinterpret_cast<Ret(*)(Args..., OBJECTREF*)>(methodEntry);

// The last argument is the implied exception handle for any exceptions.
ret = fptr(args..., &gc.Exception);
}

// If an exception was thrown, propagate it
if (gc.Exception != NULL)
COMPlusThrow(gc.Exception);

GCPROTECT_END();

return ret;
}
};

#endif //!DACCESS_COMPILE
Expand Down
82 changes: 14 additions & 68 deletions src/coreclr/vm/comutilnative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,30 +124,6 @@ extern "C" void QCALLTYPE ExceptionNative_GetFrozenStackTrace(QCall::ObjectHandl

#ifdef FEATURE_COMINTEROP

static BSTR BStrFromString(STRINGREF s)
{
CONTRACTL
{
THROWS;
}
CONTRACTL_END;

WCHAR *wz;
int cch;
BSTR bstr;

if (s == NULL)
return NULL;

s->RefInterpretGetStringValuesDangerousForGC(&wz, &cch);

bstr = SysAllocString(wz);
if (bstr == NULL)
COMPlusThrowOM();

return bstr;
}

static BSTR GetExceptionDescription(OBJECTREF objException)
{
CONTRACTL
Expand All @@ -161,31 +137,12 @@ static BSTR GetExceptionDescription(OBJECTREF objException)

BSTR bstrDescription;

STRINGREF MessageString = NULL;
GCPROTECT_BEGIN(MessageString)
GCPROTECT_BEGIN(objException)
{
// read Exception.Message property
MethodDescCallSite getMessage(METHOD__EXCEPTION__GET_MESSAGE, &objException);

ARG_SLOT GetMessageArgs[] = { ObjToArgSlot(objException)};
MessageString = getMessage.Call_RetSTRINGREF(GetMessageArgs);

// if the message string is empty then use the exception classname.
if (MessageString == NULL || MessageString->GetStringLength() == 0) {
// call GetClassName
MethodDescCallSite getClassName(METHOD__EXCEPTION__GET_CLASS_NAME, &objException);
ARG_SLOT GetClassNameArgs[] = { ObjToArgSlot(objException)};
MessageString = getClassName.Call_RetSTRINGREF(GetClassNameArgs);
_ASSERTE(MessageString != NULL && MessageString->GetStringLength() != 0);
}

// Allocate the description BSTR.
int DescriptionLen = MessageString->GetStringLength();
bstrDescription = SysAllocStringLen(MessageString->GetBuffer(), DescriptionLen);
UnmanagedCallersOnlyCaller getDescriptionBstr(METHOD__EXCEPTION__GET_DESCRIPTION_BSTR);
bstrDescription = getDescriptionBstr.InvokeThrowing_Ret<BSTR>(&objException);
}
GCPROTECT_END();
GCPROTECT_END();

return bstrDescription;
}
Expand All @@ -200,19 +157,17 @@ static BSTR GetExceptionSource(OBJECTREF objException)
PRECONDITION( IsException(objException->GetMethodTable()) );
}
CONTRACTL_END;

BSTR bstrSource;

STRINGREF refRetVal;
GCPROTECT_BEGIN(objException)

// read Exception.Source property
MethodDescCallSite getSource(METHOD__EXCEPTION__GET_SOURCE, &objException);

ARG_SLOT GetSourceArgs[] = { ObjToArgSlot(objException)};

refRetVal = getSource.Call_RetSTRINGREF(GetSourceArgs);

{
UnmanagedCallersOnlyCaller getSourceBstr(METHOD__EXCEPTION__GET_SOURCE_BSTR);
bstrSource = getSourceBstr.InvokeThrowing_Ret<BSTR>(&objException);
}
GCPROTECT_END();
return BStrFromString(refRetVal);

return bstrSource;
}

static void GetExceptionHelp(OBJECTREF objException, BSTR *pbstrHelpFile, DWORD *pdwHelpContext)
Expand All @@ -229,20 +184,11 @@ static void GetExceptionHelp(OBJECTREF objException, BSTR *pbstrHelpFile, DWORD
}
CONTRACTL_END;

*pdwHelpContext = 0;

GCPROTECT_BEGIN(objException);

// call managed code to parse help context
MethodDescCallSite getHelpContext(METHOD__EXCEPTION__GET_HELP_CONTEXT, &objException);

ARG_SLOT GetHelpContextArgs[] =
GCPROTECT_BEGIN(objException)
{
ObjToArgSlot(objException),
PtrToArgSlot(pdwHelpContext)
};
*pbstrHelpFile = BStrFromString(getHelpContext.Call_RetSTRINGREF(GetHelpContextArgs));

UnmanagedCallersOnlyCaller getHelpContextBstr(METHOD__EXCEPTION__GET_HELP_CONTEXT_BSTR);
getHelpContextBstr.InvokeThrowing(&objException, pbstrHelpFile, pdwHelpContext);
}
GCPROTECT_END();
}

Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/vm/corelib.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,11 +301,11 @@ DEFINE_FIELD_U(_xcode, ExceptionObject, _xcode)
DEFINE_FIELD_U(_HResult, ExceptionObject, _HResult)
DEFINE_CLASS(EXCEPTION, System, Exception)
DEFINE_METHOD(EXCEPTION, INTERNAL_PRESERVE_STACK_TRACE, InternalPreserveStackTrace, IM_RetVoid)
// Following Exception members are only used when FEATURE_COMINTEROP
DEFINE_METHOD(EXCEPTION, GET_CLASS_NAME, GetClassName, IM_RetStr)
DEFINE_PROPERTY(EXCEPTION, MESSAGE, Message, Str)
DEFINE_PROPERTY(EXCEPTION, SOURCE, Source, Str)
DEFINE_METHOD(EXCEPTION, GET_HELP_CONTEXT, GetHelpContext, IM_RefUInt_RetStr)
#ifdef FEATURE_COMINTEROP
DEFINE_METHOD(EXCEPTION, GET_DESCRIPTION_BSTR, GetDescriptionBstr, SM_PtrException_PtrException_RetIntPtr)
DEFINE_METHOD(EXCEPTION, GET_SOURCE_BSTR, GetSourceBstr, SM_PtrException_PtrException_RetIntPtr)
DEFINE_METHOD(EXCEPTION, GET_HELP_CONTEXT_BSTR, GetHelpContextBstr, SM_PtrException_PtrIntPtr_PtrUInt_PtrException_RetVoid)
#endif // FEATURE_COMINTEROP


DEFINE_CLASS(SYSTEM_EXCEPTION, System, SystemException)
Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/vm/metasig.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,10 @@ DEFINE_METASIG_T(SM(IntPtr_RetRuntimeType, I , C(CLASS)))
DEFINE_METASIG_T(IM(RuntimeArgumentHandle_PtrVoid_RetVoid, g(ARGUMENT_HANDLE) P(v), v))

// Exception
DEFINE_METASIG(IM(RefUInt_RetStr, r(K), s))
#ifdef FEATURE_COMINTEROP
DEFINE_METASIG_T(SM(PtrException_PtrException_RetIntPtr, P(C(EXCEPTION)) P(C(EXCEPTION)), I))
DEFINE_METASIG_T(SM(PtrException_PtrIntPtr_PtrUInt_PtrException_RetVoid, P(C(EXCEPTION)) P(I) P(K) P(C(EXCEPTION)), v))
#endif //FEATURE_COMINTEROP

#ifdef FEATURE_COMINTEROP
// The signature of the method System.Runtime.InteropServices.ICustomQueryInterface.GetInterface
Expand Down
Loading