File: Windows\Win32\System\Com\ComClassFactory.cs
Web Access
Project: src\src\System.Windows.Forms.Primitives\tests\TestUtilities\System.Windows.Forms.Primitives.TestUtilities.csproj (System.Windows.Forms.Primitives.TestUtilities)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.ComponentModel;
using System.Runtime.InteropServices;
 
namespace Windows.Win32.System.Com;
 
/// <summary>
///  Wraps an <see cref="IClassFactory"/> from a dynamically loaded assembly.
/// </summary>
internal unsafe class ComClassFactory : IDisposable
{
    private readonly string _filePath;
    public Guid ClassId { get; }
    private readonly HINSTANCE _instance;
    private readonly IClassFactory* _classFactory;
 
    private const string ExportMethodName = "DllGetClassObject";
 
    public ComClassFactory(
        string filePath,
        Guid classId)
    {
        _filePath = filePath;
        ClassId = classId;
        _instance = PInvoke.LoadLibraryEx(filePath, default);
        if (_instance.IsNull)
        {
            throw new Win32Exception();
        }
 
        // Dynamically get the class factory method.
 
        // HRESULT DllGetClassObject(
        //   [in] REFCLSID rclsid,
        //   [in] REFIID riid,
        //   [out] LPVOID* ppv
        // );
 
        FARPROC proc = PInvoke.GetProcAddress(_instance, ExportMethodName);
        IClassFactory* classFactory;
        ((delegate* unmanaged<Guid*, Guid*, void**, HRESULT>)proc.Value)(
            &classId, IID.Get<IClassFactory>(),
            (void**)&classFactory).ThrowOnFailure();
        _classFactory = classFactory;
    }
 
    internal HRESULT CreateInstance(out IUnknown* unknown)
    {
        unknown = default;
        fixed (IUnknown** u = &unknown)
        {
            return _classFactory->CreateInstance(null, IID.Get<IUnknown>(), (void**)u);
        }
    }
 
    internal HRESULT CreateInstance(out object unknown)
    {
        HRESULT result = CreateInstance(out IUnknown* punk);
        unknown = punk is null ? null : Marshal.GetObjectForIUnknown((nint)punk);
        return result;
    }
 
    public void Dispose()
    {
        _classFactory->Release();
        PInvokeCore.FreeLibrary(_instance);
    }
}