XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 0
UTF-8
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace XFEEliteDangerous.Bootstrapper;

/// <summary>Owns a private diagnostic desktop or a read-only lease on the explicitly requested visible desktop.
/// Never switches desktops, sends input or changes the shared desktop's security.</summary>
internal sealed class PrivateDesktopLease : IDisposable
{
    private nint handle;
    internal string Name { get; }
    internal string StartupName=>"winsta0\\"+Name;
    internal nint BorrowedHandle=>handle;
    internal bool IsSharedVisible {get;}
    internal PrivateDesktopLease(string appContainerSid,string id,bool visible=false)
    {
        if(!Guid.TryParseExact(id,"N",out _)) throw new ArgumentException("A random private desktop ID is required.");
        if(visible)
        {
            var current=Native.GetThreadDesktop(Native.GetCurrentThreadId());
            var name=new System.Text.StringBuilder(256);
            if(current==0||!Native.GetUserObjectInformationW(current,2,name,512,out _)
                ||!string.Equals(name.ToString(),"Default",StringComparison.OrdinalIgnoreCase))
                throw new InvalidOperationException("Visible startup requires the ordinary Default desktop.");
            Name=name.ToString();IsSharedVisible=true;
            // Parent inspection only: READOBJECTS|ENUMERATE. No ACL or integrity-label changes.
            handle=OpenDesktopW(Name,0,false,0x0001|0x0040);
            if(handle==0) throw new Win32Exception(Marshal.GetLastPInvokeError());
            return;
        }
        Name="XFEEliteDangerous_Diagnostic_"+id;
        var user=WindowsIdentity.GetCurrent().User?.Value??throw new InvalidOperationException("Missing caller SID.");
        // The app gets object/window creation, not SwitchDesktop, hooks or journal access.
        var descriptor=$"D:P(A;;GA;;;SY)(A;;GA;;;{user})(A;;0x000200c7;;;{appContainerSid})S:(ML;;NW;;;LW)";
        if(!Native.ConvertStringSecurityDescriptorToSecurityDescriptorW(descriptor,1,out var security,out _)) throw new Win32Exception();
        try
        {
            var attributes=new Native.SecurityAttributes{Length=Marshal.SizeOf<Native.SecurityAttributes>(),Descriptor=security};
            handle=Native.CreateDesktopW(Name,0,0,0,0x000f01ff,ref attributes);
            if(handle==0) throw new Win32Exception();
        }
        finally { Native.LocalFree(security); }
    }
    public void Dispose() { var value=Interlocked.Exchange(ref handle,0); if(value!=0&&!Native.CloseDesktop(value)) throw new Win32Exception(); }
    [DllImport("user32",CharSet=CharSet.Unicode,SetLastError=true)]
    private static extern nint OpenDesktopW(string name,uint flags,[MarshalAs(UnmanagedType.Bool)]bool inherit,uint access);
}