diff --git a/src/WinRT.Runtime2/InteropServices/Activation/WindowsRuntimeActivationHelper.cs b/src/WinRT.Runtime2/InteropServices/Activation/WindowsRuntimeActivationHelper.cs index c16f258c0..cccb36366 100644 --- a/src/WinRT.Runtime2/InteropServices/Activation/WindowsRuntimeActivationHelper.cs +++ b/src/WinRT.Runtime2/InteropServices/Activation/WindowsRuntimeActivationHelper.cs @@ -20,7 +20,7 @@ internal static unsafe class WindowsRuntimeActivationHelper /// Activates a new Windows Runtime sealed instance. /// /// The for the IActivationFactory instance. - /// The resulting default interface pointer. + /// The resulting IInspectable interface pointer. /// Thrown if activating the instance fails. /// /// This shared factory helper can be used to activate Windows Runtime sealed types that have a parameterless constructor. @@ -28,20 +28,59 @@ internal static unsafe class WindowsRuntimeActivationHelper /// /// [MethodImpl(MethodImplOptions.NoInlining)] - public static void ActivateInstanceUnsafe(WindowsRuntimeObjectReference activationFactoryObjectReference, out void* defaultInterface) + public static void ActivateInstanceUnsafe(WindowsRuntimeObjectReference activationFactoryObjectReference, out void* inspectableInterface) { using WindowsRuntimeObjectReferenceValue activationFactoryValue = activationFactoryObjectReference.AsValue(); - fixed (void** defaultInterfacePtr = &defaultInterface) + fixed (void** inspectableInterfacePtr = &inspectableInterface) { HRESULT hresult = IActivationFactoryVftbl.ActivateInstanceUnsafe( thisPtr: activationFactoryValue.GetThisPtrUnsafe(), - instance: defaultInterfacePtr); + instance: inspectableInterfacePtr); RestrictedErrorInfo.ThrowExceptionForHR(hresult); } } + /// The IID of the default interface pointer (from the activation factory) to return. + /// The resulting default interface pointer. + /// + [MethodImpl(MethodImplOptions.NoInlining)] + public static void ActivateInstanceUnsafe( + WindowsRuntimeObjectReference activationFactoryObjectReference, + in Guid iid, + out void* defaultInterface) + { + void* inspectableInterface; + + // Get the 'IInspectable' object from the activation factory (same as above) + using (WindowsRuntimeObjectReferenceValue activationFactoryValue = activationFactoryObjectReference.AsValue()) + { + HRESULT hresult = IActivationFactoryVftbl.ActivateInstanceUnsafe( + thisPtr: activationFactoryValue.GetThisPtrUnsafe(), + instance: &inspectableInterface); + + RestrictedErrorInfo.ThrowExceptionForHR(hresult); + } + + // Query the 'IInspectable' object for the default interface, which is what callers expect. + // We only need this when using the parameterless constructor, since in this case we must + // go through 'IActivationFactory', which only declares 'IInspectable' as the return type + // for 'CreateInstance'. For other constructors instead, those would be declared on each + // specialized factory type, and would return the default interface directly. + try + { + fixed (void** defaultInterfacePtr = &defaultInterface) + { + IUnknownVftbl.QueryInterfaceUnsafe(inspectableInterface, in iid, out defaultInterface).Assert(); + } + } + finally + { + _ = IUnknownVftbl.ReleaseUnsafe(inspectableInterface); + } + } + /// /// Activates a new Windows Runtime instance. /// diff --git a/src/WinRT.Runtime2/WindowsRuntimeObject.cs b/src/WinRT.Runtime2/WindowsRuntimeObject.cs index 0f634f2ac..208550833 100644 --- a/src/WinRT.Runtime2/WindowsRuntimeObject.cs +++ b/src/WinRT.Runtime2/WindowsRuntimeObject.cs @@ -90,6 +90,7 @@ protected WindowsRuntimeObject( // See additional notes in the overload below for more details about how and when that parameter is necessary. WindowsRuntimeActivationHelper.ActivateInstanceUnsafe( activationFactoryObjectReference: activationFactoryObjectReference, + iid: in iid, defaultInterface: out void* defaultInterface); // The inner interface pointer isn't used for non-composable types, so we just pass 'null'