File: Interop\WrapperPolicy.cs
Web Access
Project: src\src\VisualStudio\Core\Def\Microsoft.VisualStudio.LanguageServices_pxr0p0dn_wpftmp.csproj (Microsoft.VisualStudio.LanguageServices)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
 
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Interop;
 
internal static class WrapperPolicy
{
    /// <summary>
    /// Factory object for creating IComWrapperFixed instances.
    /// Internal and not readonly so that unit tests can provide an alternative implementation.
    /// </summary>
    internal static IComWrapperFactory s_ComWrapperFactory =
        (IComWrapperFactory)PackageUtilities.CreateInstance(typeof(IComWrapperFactory).GUID);
 
    internal static object CreateAggregatedObject(object managedObject) => s_ComWrapperFactory.CreateAggregatedObject(managedObject);
 
    /// <summary>
    /// Return the RCW for the native IComWrapperFixed instance aggregating "managedObject"
    /// if there is one. Return "null" if "managedObject" is not aggregated.
    /// </summary>
    internal static IComWrapperFixed? TryGetWrapper(object managedObject)
    {
        // Note: this method should be "return managedObject" once we can get rid of this while IComWrapperFixed
        // business.
 
        // This force the CLR to retrieve the "outer" object of "managedObject"
        // if "managedObject" has been aggregated
        var ptr = Marshal.GetIUnknownForObject(managedObject);
        try
        {
            // This asks the CLR to return the RCW corresponding to the
            // aggregator object.
            var wrapper = Marshal.GetObjectForIUnknown(ptr);
 
            // The aggregator (if there is one) implement IComWrapperFixed!
            return wrapper as IComWrapperFixed;
        }
        finally
        {
            Marshal.Release(ptr);
        }
    }
}