using System.Runtime.InteropServices;
using System.Runtime.Versioning;

namespace Kompas.Mcp.Core.Interop;

/// <summary>
/// Нативные функции для attach к уже запущенному COM-серверу.
/// В .NET 5+ <c>Marshal.GetActiveObject</c> отсутствует, поэтому используем
/// <c>CLSIDFromProgID</c> (ole32) + <c>GetActiveObject</c> (oleaut32) напрямую.
/// </summary>
[SupportedOSPlatform("windows")]
internal static class NativeMethods
{
    [DllImport("ole32.dll", PreserveSig = false)]
    private static extern void CLSIDFromProgID(
        [MarshalAs(UnmanagedType.LPWStr)] string progId, out Guid clsid);

    [DllImport("oleaut32.dll", PreserveSig = false)]
    private static extern void GetActiveObject(
        ref Guid rclsid, IntPtr pvReserved,
        [MarshalAs(UnmanagedType.IUnknown)] out object ppunk);

    /// <summary>
    /// Подключиться к запущенному экземпляру COM-сервера по ProgID.
    /// Возвращает <c>null</c>, если ProgID не зарегистрирован или экземпляр не запущен.
    /// </summary>
    public static object? GetActiveObject(string progId)
    {
        try
        {
            CLSIDFromProgID(progId, out Guid clsid);
            GetActiveObject(ref clsid, IntPtr.Zero, out object obj);
            return obj;
        }
        catch (COMException)
        {
            return null; // MK_E_UNAVAILABLE / CO_E_CLASSSTRING и т.п.
        }
    }
}
