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 @@ -20,28 +20,67 @@ internal static unsafe class WindowsRuntimeActivationHelper
/// Activates a new Windows Runtime sealed instance.
/// </summary>
/// <param name="activationFactoryObjectReference">The <see cref="WindowsRuntimeObjectReference"/> for the <c>IActivationFactory</c> instance.</param>
/// <param name="defaultInterface">The resulting default interface pointer.</param>
/// <param name="inspectableInterface">The resulting <c>IInspectable</c> interface pointer.</param>
/// <exception cref="Exception">Thrown if activating the instance fails.</exception>
/// <remarks>
/// This shared factory helper can be used to activate Windows Runtime sealed types that have a parameterless constructor.
/// If additional parameters are needed, separate factory stubs should be used, to marshal them and update the signature.
/// </remarks>
/// <see href="https://learn.microsoft.com/uwp/winrt-cref/winrt-type-system#composable-activation"/>
[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);
}
}

/// <param name="iid">The IID of the default interface pointer (from the activation factory) to return.</param>
/// <param name="defaultInterface">The resulting default interface pointer.</param>
/// <inheritdoc cref="ActivateInstanceUnsafe(WindowsRuntimeObjectReference, out void*)"/>
[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);
}
}

/// <summary>
/// Activates a new Windows Runtime instance.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/WinRT.Runtime2/WindowsRuntimeObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down