File: TrayApplication.StopConfirmation.cs
Web Access
Project: src\src\Aspire.Tray\Windows\Aspire.Tray.Windows.csproj (aspire-tray)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
 
namespace Aspire.Tray;
 
internal sealed unsafe partial class TrayApplication
{
    private const int StopSuppressionId = 2101;
    private const int StopDetailId = 2102;
    private string? _stopDetail;
    private bool _suppressStopConfirmation;
 
    private bool ConfirmStop(AppHostInfo host)
    {
        _suppressStopConfirmation = false;
        if (!controller.ConfirmStop)
        {
            return true;
        }
        var previousOwner = _modalOwner;
        _modalOwner = _settingsWindow != 0 ? _settingsWindow : _window;
        _modalDepth++;
        _stopDetail = $"Stop {AppHostPresentation.GetTitle(host)} (PID {host.AppHostPid})?\r\n\r\n"
            + "This stops the AppHost and its running resources.";
        try
        {
            if (smokeSeconds is not null && !_interactiveSmoke)
            {
                var accept = ConfirmForSmoke?.Invoke("Stop AppHost", _stopDetail, NativeMethods.SafeConfirmation)
                    ?? throw new InvalidOperationException("Smoke confirmation handler is missing.");
                _smokeDialog = new(2, accept ? 1 : 2);
            }
            var template = CreateDialogTemplate("Stop AppHost", 310, 126, 9);
            nint result;
            fixed (byte* pointer = template)
            {
                result = NativeMethods.DialogBoxIndirectParam(_module, pointer, _modalOwner, &StopDialogProcedure, 0);
            }
            NativeCallException.Require(result != -1, "DialogBoxIndirectParamW(Stop)");
            if (_callbackFailure is not null)
            {
                throw _callbackFailure;
            }
            if (result != 1 || _quitRequested)
            {
                return false;
            }
            return true;
        }
        finally
        {
            _stopDetail = null;
            _smokeDialog = null;
            DialogReadyForSmoke = null;
            _modalDepth--;
            _modalOwner = previousOwner;
            RequestRefresh();
        }
    }
 
    private nint HandleStopDialog(nint dialog, uint message, nuint wParam)
    {
        switch (message)
        {
            case NativeMethods.WmInitDialog:
                AddDialogControl(dialog, "STATIC", _stopDetail!, 0, StopDetailId, 12, 12, 286, 48);
                AddDialogControl(dialog, "BUTTON", "&Don't ask again", 0x10000 | 0x3,
                    StopSuppressionId, 12, 68, 286, 16); // BS_AUTOCHECKBOX, initially unchecked.
                AddDialogControl(dialog, "BUTTON", "&Stop AppHost", 0x10000, 1, 150, 98, 80, 18);
                var cancel = AddDialogControl(dialog, "BUTTON", "Cancel", 0x10000 | 0x1, 2, 238, 98, 60, 18);
                NativeMethods.SendMessage(dialog, 0x401, 2, 0); // DM_SETDEFID.
                NativeMethods.SetFocus(cancel);
                return 0;
            case NativeMethods.WmCommand when (wParam & 0xFFFF) is 1 or 2:
                var result = (int)(wParam & 0xFFFF);
                _suppressStopConfirmation = result == 1
                    && NativeMethods.SendMessage(NativeMethods.GetDlgItem(dialog, StopSuppressionId),
                        NativeMethods.BmGetCheck, 0, 0) == 1;
                NativeCallException.Require(NativeMethods.EndDialog(dialog, result) != 0, "EndDialog(Stop)");
                return 1;
            case NativeMethods.WmClose:
                NativeCallException.Require(NativeMethods.EndDialog(dialog, 2) != 0, "EndDialog(Cancel)");
                return 1;
            default:
                return 0;
        }
    }
 
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])]
    private static nint StopDialogProcedure(nint dialog, uint message, nuint wParam, nint lParam)
    {
        try
        {
            return s_current?.HandleStopDialog(dialog, message, wParam) ?? 0;
        }
        catch (Exception ex)
        {
            // Never unwind a managed exception through the Win32 modal loop.
            if (s_current is { } application)
            {
                application._callbackFailure ??= ex;
                Program.Log($"Stop dialog failed: {ex.Message}");
            }
            NativeMethods.EndDialog(dialog, 2);
            return 1;
        }
    }
}