-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Convert more COM interop MethodDescCallSite to UCO #125508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
96197f1
83f8dd6
3247c98
e4b6de6
3e5088f
988e82a
68e943f
dc0cc4a
dd50f41
5057a6a
3ed9700
f1fc86a
81e4f93
61f5e70
792f177
140e394
dfc2a5d
7397553
e25f424
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1492,6 +1492,156 @@ internal static void SetPendingExceptionObject(Exception? exception) | |||||||||||||||||||
| [SupportedOSPlatform("windows")] | ||||||||||||||||||||
| internal static object GetIEnumeratorToEnumVariantMarshaler() => EnumeratorToEnumVariantMarshaler.GetInstance(string.Empty); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| private const int DispatchExPropertyCanRead = 1; | ||||||||||||||||||||
| private const int DispatchExPropertyCanWrite = 2; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| [SupportedOSPlatform("windows")] | ||||||||||||||||||||
| [UnmanagedCallersOnly] | ||||||||||||||||||||
| private static unsafe void GetDispatchExPropertyFlags(PropertyInfo* pMemberInfo, int* pResult, Exception* pException) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| try | ||||||||||||||||||||
| { | ||||||||||||||||||||
| int result = 0; | ||||||||||||||||||||
| PropertyInfo property = *pMemberInfo; | ||||||||||||||||||||
| if (property.CanRead) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| result |= DispatchExPropertyCanRead; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (property.CanWrite) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| result |= DispatchExPropertyCanWrite; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| *pResult = result; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| catch (Exception ex) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| *pException = ex; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| [SupportedOSPlatform("windows")] | ||||||||||||||||||||
| [UnmanagedCallersOnly] | ||||||||||||||||||||
| private static unsafe void CallICustomQueryInterface(ICustomQueryInterface* pObject, Guid* pIid, IntPtr* ppObject, int* pResult, Exception* pException) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| try | ||||||||||||||||||||
| { | ||||||||||||||||||||
| *pResult = (int)pObject->GetInterface(ref *pIid, out *ppObject); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| catch (Exception ex) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| *pException = ex; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| private static unsafe ulong InvokeArgSlotMethodWithOneArg(object target, RuntimeMethodHandle methodHandle, nint methodEntryPoint, object? arg0) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| IRuntimeMethodInfo methodInfo = methodHandle.GetMethodInfo(); | ||||||||||||||||||||
| Signature signature = new(methodInfo, RuntimeMethodHandle.GetDeclaringType(methodInfo)); | ||||||||||||||||||||
| RuntimeType returnType = signature.ReturnType; | ||||||||||||||||||||
| Debug.Assert(methodEntryPoint != 0); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (returnType == typeof(void)) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| ((delegate*<object, object?, void>)methodEntryPoint)(target, arg0); | ||||||||||||||||||||
| return 0; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (returnType == typeof(bool)) | ||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How did you come up with this list of supported return types?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The return-type list was not based on a separate runtime contract; it was a conservative subset of ARG_SLOT-sized primitives chosen while removing
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not following. Why are byte, double or enums missing in the list? is it not possible for COM events to return these types? It looks suspect to me that there is
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I reduced the full set of types after your comment: #125508 (comment). I think we need some test coverage for non-void types under src/test/Inerop/COM before modifying it further.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we need to understand the exact set of the types that this supports currently. |
||||||||||||||||||||
| { | ||||||||||||||||||||
| return ((delegate*<object, object?, bool>)methodEntryPoint)(target, arg0) ? 1UL : 0UL; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (returnType == typeof(int)) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| return unchecked((ulong)((delegate*<object, object?, int>)methodEntryPoint)(target, arg0)); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (returnType == typeof(uint)) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| return ((delegate*<object, object?, uint>)methodEntryPoint)(target, arg0); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (returnType == typeof(long)) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| return unchecked((ulong)((delegate*<object, object?, long>)methodEntryPoint)(target, arg0)); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (returnType == typeof(ulong)) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| return ((delegate*<object, object?, ulong>)methodEntryPoint)(target, arg0); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (returnType == typeof(IntPtr)) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| return (ulong)(nuint)((delegate*<object, object?, nint>)methodEntryPoint)(target, arg0); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (returnType == typeof(UIntPtr)) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| return (ulong)((delegate*<object, object?, nuint>)methodEntryPoint)(target, arg0); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| throw new NotSupportedException(); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| [SupportedOSPlatform("windows")] | ||||||||||||||||||||
| [UnmanagedCallersOnly] | ||||||||||||||||||||
| private static unsafe void InvokeConnectionPointProviderMethod( | ||||||||||||||||||||
| object* pProvider, | ||||||||||||||||||||
| IntPtr pProviderMethodPtr, | ||||||||||||||||||||
| object* pDelegate, | ||||||||||||||||||||
| IntPtr pDelegateCtorMethodPtr, | ||||||||||||||||||||
| object* pSubscriber, | ||||||||||||||||||||
| IntPtr pEventMethodCodePtr, | ||||||||||||||||||||
| bool useUIntPtrCtor, | ||||||||||||||||||||
| Exception* pException) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| try | ||||||||||||||||||||
| { | ||||||||||||||||||||
| nint delegateCtorMethodEntryPoint = (nint)pDelegateCtorMethodPtr; | ||||||||||||||||||||
| Debug.Assert(delegateCtorMethodEntryPoint != 0); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Construct the delegate before invoking the provider method. | ||||||||||||||||||||
| if (useUIntPtrCtor) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| ((delegate*<object, object?, nuint, void>)delegateCtorMethodEntryPoint)(*pDelegate, *pSubscriber, (nuint)pEventMethodCodePtr); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| else | ||||||||||||||||||||
| { | ||||||||||||||||||||
| ((delegate*<object, object?, nint, void>)delegateCtorMethodEntryPoint)(*pDelegate, *pSubscriber, (nint)pEventMethodCodePtr); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
Comment on lines
+1607
to
+1614
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think it would be ok to always call this using |
||||||||||||||||||||
|
|
||||||||||||||||||||
| nint providerMethodEntryPoint = (nint)pProviderMethodPtr; | ||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||
| Debug.Assert(providerMethodEntryPoint != 0); | ||||||||||||||||||||
| ((delegate*<object, object?, void>)providerMethodEntryPoint)(*pProvider, *pDelegate); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| catch (Exception ex) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| *pException = ex; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| [SupportedOSPlatform("windows")] | ||||||||||||||||||||
| [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2062:Value passed to parameter cannot be statically determined", Justification = "The runtime passes a RuntimeType describing the COM event provider. The dynamic constructor access requirements are enforced by runtime callsite semantics.")] | ||||||||||||||||||||
| [UnmanagedCallersOnly] | ||||||||||||||||||||
| // pResult is an unmanaged ARG_SLOT* (see vm/callhelpers.h). ARG_SLOT is always 8 bytes, | ||||||||||||||||||||
| // so we use ulong purely as a fixed-width bit container, not for numeric semantics. | ||||||||||||||||||||
| private static unsafe void InvokeClrToComEventProviderMethod(__ComObject* pComObject, RuntimeType* pProviderType, IntPtr pMethodDesc, IntPtr pMethodEntryPoint, Delegate* pEventHandler, ulong* pResult, Exception* pException) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| try | ||||||||||||||||||||
| { | ||||||||||||||||||||
| object eventProvider = pComObject->GetEventProvider(*pProviderType); | ||||||||||||||||||||
| RuntimeMethodHandle methodHandle = RuntimeMethodHandle.FromIntPtr(pMethodDesc); | ||||||||||||||||||||
| *pResult = InvokeArgSlotMethodWithOneArg(eventProvider, methodHandle, (nint)pMethodEntryPoint, *pEventHandler); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| catch (Exception ex) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| *pException = ex; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| [SupportedOSPlatform("windows")] | ||||||||||||||||||||
| [UnmanagedCallersOnly] | ||||||||||||||||||||
| private static unsafe void GetIEnumeratorToEnumVariantMarshaler(object* pResult, Exception* pException) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -297,11 +297,9 @@ UINT32 CLRToCOMEventCallWorker(CLRToCOMMethodFrame* pFrame, CLRToCOMCallMethodDe | |
|
|
||
| struct { | ||
| OBJECTREF EventProviderTypeObj; | ||
| OBJECTREF EventProviderObj; | ||
| OBJECTREF ThisObj; | ||
| } gc; | ||
| gc.EventProviderTypeObj = NULL; | ||
| gc.EventProviderObj = NULL; | ||
| gc.ThisObj = NULL; | ||
|
|
||
| LOG((LF_STUBS, LL_INFO1000, "Calling CLRToCOMEventCallWorker %s::%s \n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName)); | ||
|
|
@@ -316,32 +314,28 @@ UINT32 CLRToCOMEventCallWorker(CLRToCOMMethodFrame* pFrame, CLRToCOMCallMethodDe | |
| gc.EventProviderTypeObj = pEvProvMT->GetManagedClassObject(); | ||
| gc.ThisObj = pFrame->GetThis(); | ||
|
|
||
| UnmanagedCallersOnlyCaller getEventProvider(METHOD__COM_OBJECT__GET_EVENT_PROVIDER); | ||
|
|
||
| // Retrieve the event provider for the event interface type. | ||
| getEventProvider.InvokeThrowing(&gc.ThisObj, &gc.EventProviderTypeObj, &gc.EventProviderObj); | ||
|
|
||
| // Set up an arg iterator to retrieve the arguments from the frame. | ||
| MetaSig mSig(pMD); | ||
| ArgIterator ArgItr(&mSig); | ||
|
|
||
| // Make the call on the event provider method desc. | ||
| MethodDescCallSite eventProvider(pEvProvMD, &gc.EventProviderObj); | ||
|
|
||
| // Retrieve the event handler passed in. | ||
| OBJECTREF EventHandlerObj = ObjectToOBJECTREF(*(Object**)(pFrame->GetTransitionBlock() + ArgItr.GetNextOffset())); | ||
|
|
||
| ARG_SLOT EventMethArgs[] = | ||
| { | ||
| ObjToArgSlot(gc.EventProviderObj), | ||
| ObjToArgSlot(EventHandlerObj) | ||
| }; | ||
| ARG_SLOT eventProviderResult = 0; | ||
| UnmanagedCallersOnlyCaller invokeClrToComEventProviderMethod(METHOD__STUBHELPERS__INVOKE_CLR_TO_COM_EVENT_PROVIDER_METHOD); | ||
am11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| invokeClrToComEventProviderMethod.InvokeThrowing( | ||
| &gc.ThisObj, | ||
| &gc.EventProviderTypeObj, | ||
| (INT_PTR)pEvProvMD, | ||
| (INT_PTR)pEvProvMD->GetMultiCallableAddrOfCode(), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These can use |
||
| &EventHandlerObj, | ||
| &eventProviderResult); | ||
|
|
||
| // | ||
| // If this can ever return something bigger than an INT64 byval | ||
| // then this code is broken. Currently, however, it cannot. | ||
| // | ||
| *(ARG_SLOT *)(pFrame->GetReturnValuePtr()) = eventProvider.Call_RetArgSlot(EventMethArgs); | ||
| *(ARG_SLOT *)(pFrame->GetReturnValuePtr()) = eventProviderResult; | ||
|
|
||
| // The COM event call worker does not support value returned in | ||
| // floating point registers. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.