UI/Console/HDTBootImage.xaml

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Windows PE"
    Height="760" Width="1180"
    MinHeight="520" MinWidth="880"
    WindowStartupLocation="Manual"
    Background="{DynamicResource HDTWindowBrush}">
 
    <!--
        THE WINDOWS PE WINDOW - Deployment Workbench's deployment share
        Properties, Windows PE tab, which is where an MDT admin has configured a
        boot image for fifteen years. Four tabs, and each one is the face of a
        command family that already exists:
 
          General Set-HDTWorkspaceProperty, Set-HDTBootImageUnattend,
                           New-HDTBootImageUnattend, Set-HDTBootImageBackground,
                           Set-HDTBootImageTimeZone, Get-HDTTimeZone,
                           Add/Remove-HDTBootImageCertificate,
                           Set-HDTBootImageClientCertificate,
                           Set-HDTBootImageCertificatePassword
          Features Get-HDTAdkComponent, Add/Remove-HDTBootImageComponent
          Drivers Get-HDTDriverGroup, Set-HDTBootImageDriver
          Customisations Add/Remove-HDTBootImageContent,
                           Add/Remove/Move-HDTBootImageStartCommand
 
        THE ENTRY COMMAND IS NOT ON THIS WINDOW. workspace.yaml carries one -
        the last line of startnet.cmd, which replaces the deployment payload for
        standalone media or a diagnostic image - and Set-HDTWorkspaceProperty
        sets it. It is off the General tab on purpose: the thing an
        administrator actually wants to run at boot is a start command, which
        the Customisations tab already holds, and a box next to it that also
        looks like "the command that runs" is how somebody puts run.cmd in the
        one place that stops the deployment ever starting.
 
        NOTHING ON THIS WINDOW EXISTS WITHOUT A COMMAND BEHIND IT, and that is
        the rule the console is built to: "if we don't have that command we
        can't do it using the WPF". Two things an MDT admin might look for are
        therefore ABSENT rather than drawn dead:
 
          - THE WELCOME-SCREEN SKIPS. workspace.yaml carries bootImage.skip
            (welcome, staticIp, deployRoot, credential) and there is no setter
            for it - Set-HDTWorkspaceProperty has no -Skip parameter. Four
            checkboxes here would be four controls with nothing to call.
        (Reordering start commands WAS one of them: Add took -First or appended
        and nothing moved a row, so the arrows could not exist. That is what
        Move-HDTBootImageStartCommand was written for - the window did not get
        the buttons until the command was there to call.)
 
        THE ARCHITECTURE BOX IS ON THIS WINDOW AND THE ADK LIST FOLLOWS IT.
        Get-HDTAdkComponent is asked per architecture, so amd64 and arm64 do not
        offer the same cabs - reading the box rather than assuming amd64 is what
        stops the Features tab describing an image nobody is building.
 
        UPDATE IS NOT SAVE, AND THEY ARE TWO BUTTONS. Save writes workspace.yaml
        - instant, and what every tab on this window edits. Update runs
        Update-HDTBootImage, which mounts, injects and rebuilds a WIM and an ISO
        and takes minutes. MDT splits them the same way: the Properties dialog
        has OK/Apply, and "Update Deployment Share" is its own action. One
        button doing both would mean an administrator who fixed a typo in the
        image name waits two and a half minutes for it.
 
        NO x:Class AND NO CODE-BEHIND, as HDTConsole.xaml and
        HDTSequenceEditor.xaml. Handlers attach in PowerShell, by name.
 
        NAMED CONTROLS ARE THE CONTRACT with New-HDTConsoleHost:
        HDTBootImageTitleText, HDTBootImagePathText, HDTBootImageNameBox,
        HDTBootImageArchitectureBox, HDTBootImageLanguageBox,
        HDTBootImageScratchBox, HDTBootImageUnattendBox,
        HDTBootImageUnattendBrowseButton,
        HDTBootImageUnattendTemplateButton, HDTBootImageUnattendOpenButton,
        HDTBootImageBackgroundBox,
        HDTBootImageBackgroundBrowseButton,
        HDTBootImageTimeZoneBox, HDTBootImageTimeZoneHintText,
        HDTComponentList, HDTComponentSizeText,
        HDTCertificateList, HDTCertificateBox, HDTCertificateBrowseButton,
        HDTCertificateAddButton,
        HDTCertificateRemoveButton, HDTCertificateSummaryText,
        HDTClientCertificateBox, HDTClientCertificateBrowseButton,
        HDTClientCertificatePasswordButton, HDTClientCertificateWarningText,
        HDTDriverGroupBox,
        HDTContentList, HDTContentSourceBox, HDTContentBrowseButton,
        HDTContentDestinationBox, HDTContentAddButton, HDTContentRemoveButton,
        HDTStartCommandList, HDTStartCommandBox, HDTStartCommandFirstCheck,
        HDTStartCommandAddButton, HDTStartCommandRemoveButton,
        HDTStartCommandUpButton, HDTStartCommandDownButton,
        HDTBootImageCommandText, HDTBootImageUpdateButton,
        HDTBootImageSaveButton and HDTBootImageCloseButton.
 
        THE PALETTE IS THE CONSOLE'S - every colour a DynamicResource under the
        keys HDTConsole.xaml declares, so Get-HDTConsoleTheme repaints this
        window with the others.
    -->
 
    <Window.Resources>
        <SolidColorBrush x:Key="HDTWindowBrush" Color="#FFF3F3F3" />
        <SolidColorBrush x:Key="HDTBannerBrush" Color="#FF0E639C" />
        <SolidColorBrush x:Key="HDTBannerTextBrush" Color="#FFFFFFFF" />
        <SolidColorBrush x:Key="HDTBannerLabelBrush" Color="#FFD6E9F5" />
        <SolidColorBrush x:Key="HDTPanelBrush" Color="#FFFFFFFF" />
        <SolidColorBrush x:Key="HDTPanelTextBrush" Color="#FF1B1B1B" />
        <SolidColorBrush x:Key="HDTBorderBrush" Color="#FFC8C8C8" />
        <SolidColorBrush x:Key="HDTLabelBrush" Color="#FF0E639C" />
        <SolidColorBrush x:Key="HDTHintBrush" Color="#FF6A6A6A" />
        <SolidColorBrush x:Key="HDTCommandBrush" Color="#FFF7F7F7" />
        <SolidColorBrush x:Key="HDTCommandTextBrush" Color="#FFA31515" />
        <SolidColorBrush x:Key="HDTFieldBrush" Color="#FFEDEDED" />
        <SolidColorBrush x:Key="HDTFooterBrush" Color="#FFE8E8E8" />
        <SolidColorBrush x:Key="HDTButtonBrush" Color="#FF0E639C" />
        <SolidColorBrush x:Key="HDTButtonTextBrush" Color="#FFFFFFFF" />
        <SolidColorBrush x:Key="HDTButtonHoverBrush" Color="#FFCCE4F7" />
        <SolidColorBrush x:Key="HDTButtonHoverTextBrush" Color="#FF000000" />
        <SolidColorBrush x:Key="HDTButtonPressedBrush" Color="#FFA9CFEC" />
 
        <!-- The console's button, template and all. See HDTConsole.xaml for why
             the colours are Setters inside a ControlTemplate rather than local
             values on the element. -->
        <Style TargetType="Button">
            <Setter Property="Background" Value="{DynamicResource HDTButtonBrush}" />
            <Setter Property="Foreground" Value="{DynamicResource HDTButtonTextBrush}" />
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="FontSize" Value="13" />
            <Setter Property="Padding" Value="14,6,14,6" />
            <Setter Property="Margin" Value="0,0,8,0" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border x:Name="HDTButtonSurface"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"
                                              Margin="{TemplateBinding Padding}" />
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="HDTButtonSurface" Property="Background"
                                        Value="{DynamicResource HDTButtonHoverBrush}" />
                                <Setter Property="Foreground"
                                        Value="{DynamicResource HDTButtonHoverTextBrush}" />
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter TargetName="HDTButtonSurface" Property="Background"
                                        Value="{DynamicResource HDTButtonPressedBrush}" />
                                <Setter Property="Foreground"
                                        Value="{DynamicResource HDTButtonHoverTextBrush}" />
                            </Trigger>
                            <!-- A disabled action must LOOK disabled. Remove
                                 means nothing until a row is selected, and a
                                 bright button that does nothing when pressed is
                                 how an administrator concludes the window is
                                 broken. -->
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter TargetName="HDTButtonSurface" Property="Background"
                                        Value="{DynamicResource HDTFooterBrush}" />
                                <Setter Property="Foreground"
                                        Value="{DynamicResource HDTBorderBrush}" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
 
        <Style TargetType="TextBlock">
            <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" />
            <Setter Property="FontFamily" Value="Segoe UI" />
            <Setter Property="FontSize" Value="13" />
        </Style>
 
        <!-- The hint under a field: the same size, deliberately quieter. It
             says what an EMPTY box means, which is the question every one of
             these fields raises and none of them can answer by itself. -->
        <Style x:Key="HDTHintText" TargetType="TextBlock">
            <Setter Property="Foreground" Value="{DynamicResource HDTHintBrush}" />
            <Setter Property="FontFamily" Value="Segoe UI" />
            <Setter Property="FontSize" Value="12" />
            <Setter Property="TextWrapping" Value="Wrap" />
        </Style>
 
        <!-- WHITE, BECAUSE THESE ARE TYPED INTO. HDTFieldBrush is the read-only
             wash the console's detail pane puts on rows that are a reading
             rather than a setting; every box on this window is a setting. It
             wore the wash for months and nobody could tell, because the wash
             was #FAFAFA and invisible against white - the moment it became a
             grey somebody could see, this window started claiming its image
             name could not be changed. -->
        <Style TargetType="TextBox">
            <Setter Property="Background" Value="{DynamicResource HDTPanelBrush}" />
            <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" />
            <Setter Property="BorderBrush" Value="{DynamicResource HDTBorderBrush}" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="FontFamily" Value="Segoe UI" />
            <Setter Property="FontSize" Value="13" />
            <Setter Property="Padding" Value="6,4,6,4" />
        </Style>
 
        <Style TargetType="ComboBox">
            <Setter Property="FontFamily" Value="Segoe UI" />
            <Setter Property="FontSize" Value="13" />
            <Setter Property="Padding" Value="6,4,6,4" />
        </Style>
 
        <Style TargetType="CheckBox">
            <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" />
            <Setter Property="FontFamily" Value="Segoe UI" />
            <Setter Property="FontSize" Value="13" />
        </Style>
 
        <Style TargetType="TabItem">
            <Setter Property="Foreground" Value="{DynamicResource HDTPanelTextBrush}" />
            <Setter Property="FontFamily" Value="Segoe UI" />
            <Setter Property="FontSize" Value="12" />
            <Setter Property="Padding" Value="14,5,14,5" />
        </Style>
    </Window.Resources>
 
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
 
        <!-- the banner: which image, and which workspace it is configured in -->
        <Border Grid.Row="0" Background="{DynamicResource HDTBannerBrush}" Padding="24,14,24,14">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
 
                <TextBlock Grid.Row="0" x:Name="HDTBootImageTitleText"
 
 Foreground="{DynamicResource HDTBannerTextBrush}"
 FontFamily="Segoe UI" FontSize="19" />
 
                <TextBlock Grid.Row="1" x:Name="HDTBootImagePathText"
                           Text=""
                           Foreground="{DynamicResource HDTBannerLabelBrush}"
                           FontFamily="Consolas, Courier New" FontSize="12"
                           Margin="0,4,0,0" />
            </Grid>
        </Border>
 
        <TabControl Grid.Row="1" Margin="24,18,24,0"
                    Background="{DynamicResource HDTPanelBrush}"
                    BorderBrush="{DynamicResource HDTBorderBrush}">
 
            <!-- ==================== General ==================== -->
            <TabItem x:Name="HDTBootImageGeneral" >
                <ScrollViewer VerticalScrollBarVisibility="Auto" Padding="18,16,18,16">
                    <!--
                        THE LABELS ARE TOP-ALIGNED, NOT CENTRED, and the 6px is
                        the box's own border and padding. Each field cell holds
                        a box AND the hint under it, so a centred label centres
                        against both and lands below the box it names - which
                        reads as a row that failed to line up rather than as a
                        label with an explanation beneath it.
                    -->
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="200" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
 
                        <TextBlock x:Name="HDTBootImageImageNameLabel" Grid.Row="0" Grid.Column="0"
 VerticalAlignment="Top" Margin="0,6,0,12" />
                        <StackPanel Grid.Row="0" Grid.Column="1" Margin="0,0,0,12">
                            <TextBox x:Name="HDTBootImageNameBox" Width="360" HorizontalAlignment="Left" />
                            <TextBlock x:Name="HDTBootImageImageNameHint" Style="{StaticResource HDTHintText}" Margin="0,5,0,0" MaxWidth="560"
 HorizontalAlignment="Left"
 />
                        </StackPanel>
 
                        <TextBlock x:Name="HDTBootImageArchitectureLabel" Grid.Row="1" Grid.Column="0"
 VerticalAlignment="Top" Margin="0,6,0,12" />
                        <StackPanel Grid.Row="1" Grid.Column="1" Margin="0,0,0,12">
                            <ComboBox x:Name="HDTBootImageArchitectureBox" Width="180"
                                      HorizontalAlignment="Left" SelectedValuePath="Tag">
                                <ComboBoxItem Tag="amd64" Content="amd64" />
                                <ComboBoxItem Tag="arm64" Content="arm64" />
                            </ComboBox>
                            <TextBlock x:Name="HDTBootImageArchitectureHint" Style="{StaticResource HDTHintText}" Margin="0,5,0,0" MaxWidth="560"
 HorizontalAlignment="Left"
 />
                        </StackPanel>
 
                        <TextBlock x:Name="HDTBootImageLanguageLabel" Grid.Row="2" Grid.Column="0"
 VerticalAlignment="Top" Margin="0,6,0,12" />
                        <StackPanel Grid.Row="2" Grid.Column="1" Margin="0,0,0,12">
                            <TextBox x:Name="HDTBootImageLanguageBox" Width="180" HorizontalAlignment="Left" />
                            <TextBlock x:Name="HDTBootImageLanguageHint" Style="{StaticResource HDTHintText}" Margin="0,5,0,0" MaxWidth="560"
 HorizontalAlignment="Left"
 />
                        </StackPanel>
 
                        <TextBlock x:Name="HDTBootImageScratchSpaceLabel" Grid.Row="3" Grid.Column="0"
 VerticalAlignment="Top" Margin="0,6,0,12" />
                        <StackPanel Grid.Row="3" Grid.Column="1" Margin="0,0,0,12">
                            <ComboBox x:Name="HDTBootImageScratchBox" Width="180"
                                      HorizontalAlignment="Left" SelectedValuePath="Tag">
                                <ComboBoxItem Tag="32" Content="32 MB" />
                                <ComboBoxItem Tag="64" Content="64 MB" />
                                <ComboBoxItem Tag="128" Content="128 MB" />
                                <ComboBoxItem Tag="256" Content="256 MB" />
                                <ComboBoxItem Tag="512" Content="512 MB" />
                                <ComboBoxItem Tag="1024" Content="1024 MB" />
                            </ComboBox>
                            <TextBlock x:Name="HDTBootImageScratchSpaceHint" Style="{StaticResource HDTHintText}" Margin="0,5,0,0" MaxWidth="560"
 HorizontalAlignment="Left"
 />
                        </StackPanel>
 
                        <!--
                            THE ANSWER FILE, AND IT IS wpeinit's ARGUMENT rather
                            than a line of its own. wpeinit processes it -
                            Display, EnableFirewall, EnableNetwork, LogPath,
                            PageFile, Restart, RunSynchronous, RunAsynchronous -
                            so the WinPE firewall is set HERE and not by a tool
                            in a start command. `wpeutil disablefirewall` is a
                            command for a technician at a prompt; this is how an
                            IMAGE is built with the setting.
                        -->
                        <TextBlock x:Name="HDTBootImageAnswerFileLabel" Grid.Row="4" Grid.Column="0"
 VerticalAlignment="Top" Margin="0,6,0,12" />
                        <StackPanel Grid.Row="4" Grid.Column="1" Margin="0,0,0,12">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="HDTBootImageUnattendBox" Width="470"
                                         HorizontalAlignment="Left" FontFamily="Consolas, Courier New"
                                         Margin="0,0,8,0" />
                                <Button x:Name="HDTBootImageUnattendBrowseButton" MinWidth="80" />
                            </StackPanel>
 
                            <!--
                                BROWSE ALONE ASSUMES THE FILE EXISTS, and on a
                                new share it does not: a windowsPE answer file
                                is a document written from Microsoft's schema,
                                and "go and write one" is not an answer a
                                properties page should give.
 
                                USE TEMPLATE writes the one this module ships
                                onto the share and names it here. OPEN is what
                                makes that worth doing - wpeinit also reads
                                EnableFirewall, EnableNetwork, LogPath, PageFile
                                and Restart, and every one of them is set by
                                editing this file. There is no page for those
                                and there should not be: they are wpeinit's
                                list, not HDT's, and it changes with WinPE.
                            -->
                            <StackPanel Orientation="Horizontal" Margin="0,8,0,0">
                                <Button x:Name="HDTBootImageUnattendTemplateButton"
 MinWidth="110" Margin="0,0,8,0" />
                                <Button x:Name="HDTBootImageUnattendOpenButton" MinWidth="80" />
                            </StackPanel>
 
                            <TextBlock x:Name="HDTBootImageAnswerFileHint" Style="{StaticResource HDTHintText}" Margin="0,5,0,0" MaxWidth="560"
 HorizontalAlignment="Left"
 />
                        </StackPanel>
 
                        <!--
                            MDT'S "custom background bitmap file". DESIGN 11.1
                            says HDT does not NEED one - the progress window
                            paints its own full-screen ground, which is what the
                            wallpaper is for in MDT - but the boot image still
                            has a desktop behind that window, and branding it
                            should not mean hand-editing YAML.
 
                            THE FILE PICKER FILTERS TO JPEG because WinPE reads
                            \Windows\System32\winpe.jpg and nothing else. A .png
                            chosen here would be copied into the image and never
                            shown; Set-HDTBootImageBackground refuses one, and
                            the dialog tries not to offer it in the first place.
                        -->
                        <!--
                            MDT'S LABEL, MINUS THE WORD THAT IS NO LONGER TRUE.
                            Deployment Workbench calls this "Custom background
                            bitmap file" and an MDT admin is looking for that
                            phrase - but WinPE 10 and 11 read
                            \Windows\System32\winpe.jpg, so "bitmap" would be
                            the one word on the row that sends somebody looking
                            for a .bmp. The rest of the phrase is MDT's, and the
                            hint says which format it has to be.
                        -->
                        <TextBlock x:Name="HDTBootImageCustomBackgroundFileLabel" Grid.Row="5" Grid.Column="0"
 TextWrapping="Wrap" VerticalAlignment="Top" Margin="0,6,8,12" />
                        <StackPanel Grid.Row="5" Grid.Column="1" Margin="0,0,0,12">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="HDTBootImageBackgroundBox" Width="470"
                                         HorizontalAlignment="Left" FontFamily="Consolas, Courier New"
                                         Margin="0,0,8,0" />
                                <Button x:Name="HDTBootImageBackgroundBrowseButton" MinWidth="80" />
                            </StackPanel>
                            <TextBlock x:Name="HDTBootImageCustomBackgroundFileHint" Style="{StaticResource HDTHintText}" Margin="0,5,0,0" MaxWidth="560"
 HorizontalAlignment="Left"
 />
                        </StackPanel>
 
                        <!--
                            THE TIME ZONE, WHICH THE ANSWER FILE ABOVE CANNOT
                            SET. WinPE's windowsPE pass carries locale and
                            nothing else - Microsoft's TimeZone belongs to
                            Shell-Setup, which only runs in the deployed OS's
                            passes - so this row is what puts tzutil into
                            startnet.cmd, and what the deployed machine's
                            unattend inherits.
 
                            A LIST, BECAUSE tzutil TAKES AN ID. Nobody knows the
                            ids; everybody recognises "(UTC+02:00) Jerusalem".
                        -->
                        <TextBlock x:Name="HDTBootImageTimeZoneLabel" Grid.Row="6" Grid.Column="0"
 TextWrapping="Wrap" VerticalAlignment="Top" Margin="0,6,8,12" />
                        <StackPanel Grid.Row="6" Grid.Column="1" Margin="0,0,0,12">
                            <ComboBox x:Name="HDTBootImageTimeZoneBox" Width="470"
                                      HorizontalAlignment="Left"
                                      DisplayMemberPath="Display" SelectedValuePath="Id" />
                            <TextBlock x:Name="HDTBootImageTimeZoneHintText"
                                       Style="{StaticResource HDTHintText}" Margin="0,5,0,0"
                                       MaxWidth="620" HorizontalAlignment="Left" Text="" />
                        </StackPanel>
 
                        <!--
                            "PRESS ANY KEY TO BOOT FROM CD OR DVD" IS A BOOT
                            SECTOR, NOT A SETTING WinPE READS. oscdimg writes
                            efisys.bin for the prompt and efisys_noprompt.bin
                            for silence, and HDT has always written the silent
                            one - a machine nobody is standing at cannot answer
                            a keypress, and an unattended deployment that waited
                            for one would sit at a black screen until somebody
                            walked past.
 
                            UNTICKED IS THEREFORE THE DEFAULT and matches every
                            image built before this box existed. Ticking it is
                            for the machine whose boot order still has the DVD
                            first: the prompt is what lets it fall through to
                            the disk instead of deploying itself again.
 
                            UEFI ONLY. The BIOS boot sector has no quiet
                            variant, so a BIOS ISO prompts either way.
                        -->
                        <TextBlock x:Name="HDTBootImageBootPromptLabel" Grid.Row="9" Grid.Column="0"
 TextWrapping="Wrap" VerticalAlignment="Top" Margin="0,6,8,12" />
                        <StackPanel Grid.Row="9" Grid.Column="1" Margin="0,0,0,12">
                            <CheckBox x:Name="HDTBootImagePromptForKeyCheck"
 
 HorizontalAlignment="Left" />
                            <TextBlock x:Name="HDTBootImageBootPromptHint" Style="{StaticResource HDTHintText}" Margin="0,5,0,0"
 MaxWidth="620" HorizontalAlignment="Left"
 />
                        </StackPanel>
 
                        <!--
                            THE CERTIFICATES, AS TWO ROWS ON THIS TAB rather
                            than a tab of their own. They are two paths and a
                            password - the same shape as the answer file and the
                            background directly above them - and a tab for two
                            rows makes an administrator hunt for a setting that
                            belongs beside the others.
 
                            THE FIRST ROW IS A LIST because a PKI is a chain: a
                            root and the subordinate that actually issued the
                            certificate, and an image trusting only the root
                            still cannot validate what the issuing CA signed.
 
                            IT WAS A DROP-DOWN AND THAT WAS WRONG. One box did
                            two jobs - the thing being typed and the things
                            already trusted - so adding one emptied the box and
                            hid the result behind a click: the only visible
                            change was a grey count line, and it read as nothing
                            having happened. A list shows what the image trusts
                            without being asked, which is what this row is for.
                            It is the shape the Customisations tab uses for extra
                            content, and it costs the vertical space a tab that
                            already scrolls can afford.
                        -->
                        <TextBlock x:Name="HDTBootImageCertificateAuthoritiesLabel" Grid.Row="7" Grid.Column="0"
 TextWrapping="Wrap" VerticalAlignment="Top" Margin="0,6,8,12" />
                        <StackPanel Grid.Row="7" Grid.Column="1" Margin="0,0,0,12">
                            <Border Background="{DynamicResource HDTPanelBrush}"
                                    BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"
                                    Width="470" HorizontalAlignment="Left" Height="86">
                                <ListBox x:Name="HDTCertificateList" BorderThickness="0"
                                         Background="Transparent" DisplayMemberPath="Path"
                                         FontFamily="Consolas, Courier New" FontSize="12" />
                            </Border>
                            <StackPanel Orientation="Horizontal" Margin="0,8,0,0">
                                <TextBox x:Name="HDTCertificateBox" Width="470"
                                         HorizontalAlignment="Left" FontFamily="Consolas, Courier New"
                                         Margin="0,0,8,0" />
                                <Button x:Name="HDTCertificateBrowseButton" MinWidth="80" />
                                <Button x:Name="HDTCertificateAddButton" MinWidth="70" />
                                <Button x:Name="HDTCertificateRemoveButton" MinWidth="80" Margin="0" />
                            </StackPanel>
                            <TextBlock x:Name="HDTCertificateSummaryText" Style="{StaticResource HDTHintText}"
                                       Margin="0,5,0,0" MaxWidth="620" HorizontalAlignment="Left" Text="" />
                            <!--
                                ONE LINE, BECAUSE THIS TAB IS ALREADY LONG. The
                                rest of the reasoning is in the schema and in
                                Add-HDTBootImageCertificate's help; what has to
                                be on the window is the store, which is what
                                makes these two rows different from each other.
                            -->
                            <TextBlock x:Name="HDTBootImageCertificateAuthoritiesHint" Style="{StaticResource HDTHintText}" Margin="0,3,0,0" MaxWidth="620"
 HorizontalAlignment="Left"
 />
                        </StackPanel>
 
                        <!--
                            THE SECOND ROW IS ONE FILE AND ONE PASSWORD, and the
                            password is the only value on this window that goes
                            to a different file: Control\certificate-password.json,
                            never workspace.yaml, which is the document an
                            administrator commits.
                        -->
                        <TextBlock x:Name="HDTBootImageMachineCertificateLabel" Grid.Row="8" Grid.Column="0"
 TextWrapping="Wrap" VerticalAlignment="Top" Margin="0,6,8,12" />
                        <StackPanel Grid.Row="8" Grid.Column="1" Margin="0,0,0,12">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="HDTClientCertificateBox" Width="470"
                                         HorizontalAlignment="Left" FontFamily="Consolas, Courier New"
                                         Margin="0,0,8,0" />
                                <Button x:Name="HDTClientCertificateBrowseButton" MinWidth="80" />
                                <Button x:Name="HDTClientCertificatePasswordButton"
 MinWidth="110" Margin="0" />
                            </StackPanel>
                            <TextBlock x:Name="HDTClientCertificateWarningText" Text=""
                                       Foreground="{DynamicResource HDTErrorBrush}" FontSize="12"
                                       TextWrapping="Wrap" Margin="0,5,0,0" MaxWidth="620"
                                       HorizontalAlignment="Left" />
                            <TextBlock x:Name="HDTBootImageMachineCertificateHint" Style="{StaticResource HDTHintText}" Margin="0,3,0,0" MaxWidth="620"
 HorizontalAlignment="Left"
 />
                        </StackPanel>
 
                        <!--
                            THERE IS NO APPLY ON THIS TAB, and that is not an
                            omission. Every tab edits the same in-memory
                            document; Save at the bottom is what writes it, and
                            it is where MDT's properties dialog puts Apply too.
                            A second Apply mid-form would have to mean something
                            different from Save to be worth pressing, and it
                            does not - it sat under the last field and read as
                            "apply the answer file".
                        -->
 
                        <!--
                            WHAT THIS TAB DOES NOT SHOW, said here rather than
                            drawn as dead controls: workspace.yaml also carries
                            bootImage.skip - the four Welcome-screen Skip*
                            properties - and no command sets them, so there is
                            nothing for a checkbox to call. They are edited in
                            the file until there is one.
                        -->
                        <TextBlock x:Name="HDTBootImageMachineCertificateHint2" Grid.Row="10" Grid.Column="1" Style="{StaticResource HDTHintText}"
 Margin="0,22,0,0" MaxWidth="560" HorizontalAlignment="Left"
 />
                    </Grid>
                </ScrollViewer>
            </TabItem>
 
            <!-- ==================== Features ==================== -->
            <TabItem x:Name="HDTBootImageFeatures" >
                <Grid Margin="18,16,18,16">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
 
                    <TextBlock x:Name="HDTBootImageMachineCertificateHint3" Grid.Row="0" Style="{StaticResource HDTHintText}" Margin="0,0,0,12"
 MaxWidth="820" HorizontalAlignment="Left"
 />
 
                    <!--
                        A TICK PER COMPONENT, AND SIX OF THEM CANNOT BE UNTICKED.
                        Get-HDTAdkComponent marks the ones HDT applies to every
                        image - WinPE-NetFx and WinPE-PowerShell among them,
                        because a boot image without them cannot run the engine
                        at all. They are shown ticked and disabled rather than
                        hidden: an administrator looking for PowerShell in this
                        list has to find it and see that it is already there.
 
                        REQUIRES IS ON THE ROW, not in a dialog after the fact.
                        WinPE-PowerShell needs WinPE-WMI beside it, and a list
                        that only says so once the build fails has spent two and
                        a half minutes teaching it.
                    -->
                    <Border Grid.Row="2" Background="{DynamicResource HDTPanelBrush}"
                            BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1">
                        <ScrollViewer VerticalScrollBarVisibility="Auto" Padding="12,10,12,10">
                            <ItemsControl x:Name="HDTComponentList">
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <Grid Margin="0,3,0,3">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="250" />
                                                <ColumnDefinition Width="80" />
                                                <ColumnDefinition Width="*" />
                                            </Grid.ColumnDefinitions>
 
                                            <CheckBox Grid.Column="0"
                                                      IsChecked="{Binding Declared, Mode=TwoWay}"
                                                      IsEnabled="{Binding CanChange}"
                                                      Content="{Binding Name}" />
 
                                            <TextBlock Grid.Column="1" Text="{Binding SizeText}"
                                                       Foreground="{DynamicResource HDTHintBrush}"
                                                       FontFamily="Consolas, Courier New" FontSize="12"
                                                       HorizontalAlignment="Right" Margin="0,0,16,0" />
 
                                            <!--
                                                WHAT IT DOES, THEN WHAT COMES
                                                WITH IT. The ADK ships no
                                                descriptions at all - the cab
                                                names are the only metadata
                                                there is - so this text is a
                                                table HDT carries, from
                                                Microsoft's OC reference, the
                                                same way MDT carries its own.
                                                Without it the row read
                                                'WinPE-Dot3Svc 1.3 MB'.
                                            -->
                                            <TextBlock Grid.Column="2" Text="{Binding DetailText}"
                                                       Foreground="{DynamicResource HDTHintBrush}"
                                                       FontSize="12" TextTrimming="CharacterEllipsis"
                                                       ToolTip="{Binding DetailText}" />
                                        </Grid>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </ScrollViewer>
                    </Border>
 
                    <!--
                        THE TOTAL, BECAUSE THE COST OF THIS TAB IS THE THING IT
                        HIDES. Every tick is megabytes in a WIM that has to be
                        transferred to every machine that PXE boots, and the
                        list gives no sense of that one row at a time.
                    -->
                    <TextBlock Grid.Row="2" x:Name="HDTComponentSizeText" Text=""
                               Style="{StaticResource HDTHintText}" Margin="0,12,0,0" />
                </Grid>
            </TabItem>
 
            <!-- ==================== Drivers ==================== -->
            <TabItem x:Name="HDTBootImageDrivers" >
                <ScrollViewer VerticalScrollBarVisibility="Auto" Padding="18,16,18,16">
                    <StackPanel>
                        <TextBlock x:Name="HDTBootImageMachineCertificateHint4" Style="{StaticResource HDTHintText}" Margin="0,0,0,14"
 MaxWidth="760" HorizontalAlignment="Left"
 />
 
                        <!--
                            A LIST, NOT A BOX YOU TYPE INTO. A group is a folder
                            under Drivers\ on the share, so the legal answers are
                            knowable - Get-HDTDriverGroup reads them - and a
                            typed one that is wrong builds an image with NO
                            drivers in it, warned about at build time and
                            discovered on a bench with a disk WinPE cannot see.
 
                            "No drivers" IS THE FIRST ROW rather than an empty
                            selection: it is a real choice, and a list you can
                            only say it in by clearing the box is a list you
                            cannot say it in.
                        -->
                        <TextBlock x:Name="HDTBootImageDriverGroupLabel" Margin="0,0,0,6" />
                        <ComboBox x:Name="HDTDriverGroupBox" Width="420" HorizontalAlignment="Left"
                                  DisplayMemberPath="Display" SelectedValuePath="Name" />
                        <!--
                            NO APPLY AND NO CLEAR HERE EITHER. Save writes what
                            is in the box, and EMPTYING IT IS CLEARING IT - a
                            Clear button beside a box you can already empty is a
                            second way to do one thing, and the two disagree the
                            first time somebody empties the box and presses
                            Save expecting Clear's behaviour. Set-HDTBootImageDriver
                            still has -Clear; it is what Save runs on an empty box.
                        -->
                        <TextBlock x:Name="HDTBootImageDriverGroupHint" Style="{StaticResource HDTHintText}" Margin="0,6,0,0" MaxWidth="620"
 HorizontalAlignment="Left"
 />
                    </StackPanel>
                </ScrollViewer>
            </TabItem>
 
            <!-- ==================== Customisations ==================== -->
            <TabItem x:Name="HDTBootImageCustomisations" >
                <Grid Margin="18,16,18,16">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
 
                    <!--
                        TWO HALVES, AND THEY ONLY WORK TOGETHER. Copying BGInfo
                        or a VNC server into the image starts nothing - the
                        entry command is the deployment, and it does not return.
                        The top half puts a file in the image; the bottom half
                        is what runs it. A window with only the first would let
                        an administrator ship a tool that never launches, which
                        is the failure this pair exists to stop.
                    -->
                    <TextBlock x:Name="HDTBootImageExtraContentLabel" Grid.Row="0" FontSize="14" Margin="0,0,0,8" />
 
                    <Border Grid.Row="1" Background="{DynamicResource HDTPanelBrush}"
                            BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"
                            MinHeight="110">
                        <ListBox x:Name="HDTContentList" BorderThickness="0"
                                 Background="Transparent" FontSize="13">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <Grid Margin="0,2,0,2">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*" />
                                            <ColumnDefinition Width="Auto" />
                                            <ColumnDefinition Width="260" />
                                        </Grid.ColumnDefinitions>
 
                                        <TextBlock Grid.Column="0" Text="{Binding Source}"
                                                   FontFamily="Consolas, Courier New" FontSize="12"
                                                   TextTrimming="CharacterEllipsis" />
                                        <TextBlock Grid.Column="1" Text=" &#x2192; "
                                                   Foreground="{DynamicResource HDTHintBrush}" FontSize="12" />
                                        <TextBlock Grid.Column="2" Text="{Binding Destination}"
                                                   FontFamily="Consolas, Courier New" FontSize="12"
                                                   TextTrimming="CharacterEllipsis" />
                                    </Grid>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </Border>
 
                    <!--
                        THE TWO BOXES ARE LABELLED, and on this row it is not
                        decoration: they hold a path on the build machine and a
                        path inside the image, they look identical, and putting
                        them the wrong way round produces an image that builds
                        and is missing the tool. A tooltip is no help - it needs
                        the pointer to already be in the right box.
                    -->
                    <Grid Grid.Row="2" Margin="0,10,0,0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="260" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
 
                        <TextBlock x:Name="HDTBootImageSourceOnThisMachine" Grid.Row="0" Grid.Column="0"
 Style="{StaticResource HDTHintText}" Margin="0,0,8,4" />
                        <TextBlock x:Name="HDTBootImageWhereItLandsInsideLabel" Grid.Row="0" Grid.Column="2"
 Style="{StaticResource HDTHintText}" Margin="0,0,8,4" />
 
                        <TextBox Grid.Row="1" Grid.Column="0" x:Name="HDTContentSourceBox"
 FontFamily="Consolas, Courier New" Margin="0,0,8,0"
 />
                        <Button Grid.Row="1" Grid.Column="1" x:Name="HDTContentBrowseButton" MinWidth="80" />
                        <TextBox Grid.Row="1" Grid.Column="2" x:Name="HDTContentDestinationBox"
 FontFamily="Consolas, Courier New" Margin="0,0,8,0"
 />
                        <StackPanel Grid.Row="1" Grid.Column="3" Orientation="Horizontal">
                            <Button x:Name="HDTContentAddButton" MinWidth="80" />
                            <Button x:Name="HDTContentRemoveButton" MinWidth="80" Margin="0" />
                        </StackPanel>
                    </Grid>
 
                    <StackPanel Grid.Row="3" Margin="0,24,0,8">
                        <TextBlock x:Name="HDTBootImageStartCommandsLabel" FontSize="14" Margin="0,0,0,4" />
                        <TextBlock x:Name="HDTBootImageStartCommandsHint" Style="{StaticResource HDTHintText}" MaxWidth="820" HorizontalAlignment="Left"
 />
                    </StackPanel>
 
                    <!--
                        THE ORDER IS THE LIST'S ORDER, and startnet.cmd runs
                        them in it - after wpeinit, so anything needing the
                        network has one, and before the entry command, because
                        that one never comes back. There are no up and down
                        buttons: Add appends or takes -First, Remove takes a
                        command, and no command moves one. Drawing arrows that
                        call nothing would be the window promising what the
                        module cannot do.
                    -->
                    <Border Grid.Row="4" Background="{DynamicResource HDTPanelBrush}"
                            BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"
                            MinHeight="90">
                        <!--
                            IT SHOWS THE DOCUMENT, WHICH IS WHAT THIS WINDOW
                            EDITS. startnet.cmd and workspace.yaml are two
                            different files: the yaml is the authored one, and
                            the .cmd is generated from it at build time, with
                            `call` in front of a batch file so cmd.exe returns.
 
                            An earlier version showed the generated line here.
                            It put a row on screen that appears in no file this
                            window can save, and made a list that is otherwise
                            a faithful view of the yaml quietly not one. The
                            `call` rule is stated in the hint above instead -
                            words about the other file, rather than the other
                            file's contents wearing this one's clothes.
                        -->
                        <ListBox x:Name="HDTStartCommandList" BorderThickness="0"
                                 Background="Transparent" DisplayMemberPath="Text"
                                 FontFamily="Consolas, Courier New" FontSize="12" />
                    </Border>
 
                    <Grid Grid.Row="5" Margin="0,10,0,0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
 
                        <TextBox Grid.Column="0" x:Name="HDTStartCommandBox"
 FontFamily="Consolas, Courier New" Margin="0,0,12,0"
 />
 
                        <CheckBox Grid.Column="1" x:Name="HDTStartCommandFirstCheck"
 VerticalAlignment="Center" Margin="0,0,12,0"
 />
 
                        <StackPanel Grid.Column="2" Orientation="Horizontal">
                            <!--
                                THE ARROWS ARE GLYPHS, AND THEY MOVE ONE PLACE.
                                Order is semantics in this list - startnet.cmd
                                runs the lines in it, synchronously - so a tool
                                that must be up before the next line runs has to
                                be above it. Move-HDTBootImageStartCommand is
                                what they call; before it existed, reordering
                                meant Remove and Add again.
 
                                Segoe UI Symbol, NOT an image: WinPE has no
                                icon pipeline and the console should not need
                                one either, and a glyph scales with the window.
                            -->
                            <Button x:Name="HDTStartCommandUpButton" Content="&#xE010;"
 FontFamily="Segoe UI Symbol" FontSize="12"
 MinWidth="36" Margin="0,0,4,0"
 />
                            <Button x:Name="HDTStartCommandDownButton" Content="&#xE011;"
 FontFamily="Segoe UI Symbol" FontSize="12"
 MinWidth="36" Margin="0,0,12,0"
 />
 
                            <Button x:Name="HDTStartCommandAddButton" MinWidth="80" />
                            <Button x:Name="HDTStartCommandRemoveButton" MinWidth="80" Margin="0" />
                        </StackPanel>
                    </Grid>
                </Grid>
            </TabItem>
            <!--
                THE RULES TAB. MDT put CustomSettings.ini on the deployment
                share's Properties, as text you edit in place; HDT's equivalent
                is rules.yaml and it goes in the same place, because that is
                where an administrator arriving from MDT will look for it.
 
                TEXT, NOT A GRID, AND THAT IS THE POINT. Add-HDTRule and
                Set-HDTRule exist and a grid could be built on them - but the
                document is walked top to bottom with first match winning per
                variable, so the ORDER of the rules, and the comments explaining
                that order, ARE its meaning. A grid would hide the one thing the
                administrator is reasoning about.
 
                SAVE IS DARK UNTIL THE DOCUMENT PARSES. Assert-HDTRuleLine is
                the same gate Add-HDTRule passes through, so a file WinPE would
                refuse at three in the morning is refused here, at the desk.
            -->
            <TabItem x:Name="HDTBootImageRules" >
                <Grid Margin="18,16,18,16">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
 
                    <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,0,0,8">
                        <TextBlock x:Name="HDTBootImageRulesLabel" FontSize="14" />
                        <TextBlock x:Name="HDTRulesSummaryText" Style="{StaticResource HDTHintText}"
                                   Margin="10,3,0,0" VerticalAlignment="Center" />
                    </StackPanel>
 
                    <Border Grid.Row="1" Background="{DynamicResource HDTPanelBrush}"
                            BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"
                            MinHeight="220">
                        <!-- Consolas, because YAML is whitespace-significant and
                             a proportional font makes a two-space indent
                             impossible to see. -->
                        <!-- WHITE, NOT THE FIELD GREY. Every other TextBox on
                             this window is a one-line field and wears
                             HDTFieldBrush; a panel-sized box in the same grey
                             reads as output rather than as something you type
                             into, and got reported as read-only when it never
                             was. -->
                        <TextBox x:Name="HDTRulesBox" BorderThickness="0"
                                 Background="{DynamicResource HDTPanelBrush}"
                                 FontFamily="Consolas" FontSize="13"
                                 AcceptsReturn="True" AcceptsTab="True" TextWrapping="NoWrap"
                                 VerticalScrollBarVisibility="Auto"
                                 HorizontalScrollBarVisibility="Auto"
                                 VerticalContentAlignment="Top" />
                    </Border>
 
                    <!-- The engine's own refusal, in the engine's own words, in
                         front of the administrator BEFORE it can reach a booted
                         machine. Empty and invisible while the document is
                         good. -->
                    <TextBlock x:Name="HDTRulesProblemText" Grid.Row="2" Margin="0,8,0,0"
                               Foreground="{DynamicResource HDTCommandTextBrush}"
                               TextWrapping="Wrap" Visibility="Collapsed" />
 
                    <StackPanel Grid.Row="3" Orientation="Horizontal"
                                HorizontalAlignment="Right" Margin="0,12,0,0">
                        <TextBlock x:Name="HDTBootImageRulesHint" Style="{StaticResource HDTHintText}"
                                   MaxWidth="520" VerticalAlignment="Center" Margin="0,0,12,0" />
                        <Button x:Name="HDTRulesReloadButton" MinWidth="90" Margin="0,0,10,0" />
                        <Button x:Name="HDTRulesSaveButton" MinWidth="90" Margin="0" />
                    </StackPanel>
                </Grid>
            </TabItem>
 
            <!--
                THE BOOTSTRAP TAB. MDT's Bootstrap.ini is what WinPE reads
                before it has a share: where the share is, who to sign in as,
                whether to ask. HDT's equivalent is bootstrap.json, written into
                the image by Update-HDTBootImage - so unlike MDT's it is
                GENERATED, and a tab that edited it as text would be editing
                something the next build overwrites.
 
                SO THIS TAB IS THE FACTS IT IS BUILT FROM. Same information,
                same place on the window, edited through the commands that own
                those keys - the only shape that survives a rebuild.
            -->
            <TabItem x:Name="HDTBootImageBootstrap" >
                <!--
                    THE BOOTSTRAP TAB IS THE RULES FILE, AND NOTHING ELSE.
 
                    It carried two blocks: five fields for what the image is
                    built with - share name, deploy root, sign-in account, log
                    level, workspace id - and, under a rule, the rules that
                    override the share for a machine that should not use it.
                    Two blocks answering the same question is what an
                    administrator reads as a window that has not decided, and it
                    was reported as exactly that.
 
                    MDT DOES NOT SPLIT THEM EITHER. Bootstrap.ini is rules all
                    the way down: [Default] is a section like any other, and
                    DeployRoot, UserID, UserDomain and UserPassword sit in it.
                    So the account moved into the rules file with the share -
                    bootstrap-rules.yaml may now set HDTUserId, HDTUserDomain
                    and HDTUserPassword - and a machine no rule matches still
                    falls back to what the image was built with.
 
                    THE PASSWORD IS CLEAR TEXT IN THAT FILE, as it was in
                    Bootstrap.ini. The file is copied INTO the boot image, so
                    anybody holding the image already holds the credential baked
                    into it.
 
                    WHAT WAS NEVER A BOOTSTRAP SETTING WENT WHERE IT BELONGS.
                    The share's name and log level are the SHARE's, not the boot
                    image's; they are on the share's own row in the console
                    tree, with the workspace id, which is fixed at creation.
                -->
                <Grid Margin="18,16,18,16">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
 
                            <TextBlock x:Name="HDTBootstrapRulesLabel" Grid.Row="0" FontSize="14"
                                       Margin="0,0,0,4" />
 
                        <TextBlock x:Name="HDTBootstrapRulesSummaryText" Grid.Row="1"
                                   Style="{StaticResource HDTHintText}" Margin="0,0,0,6" />
 
                        <Border Grid.Row="2" Background="{DynamicResource HDTPanelBrush}"
                                BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"
                                MinHeight="90">
                            <TextBox x:Name="HDTBootstrapRulesBox" BorderThickness="0"
                                     Background="{DynamicResource HDTPanelBrush}"
                                     FontFamily="Consolas" FontSize="13"
                                     AcceptsReturn="True" AcceptsTab="True" TextWrapping="NoWrap"
                                     VerticalScrollBarVisibility="Auto"
                                     HorizontalScrollBarVisibility="Auto"
                                     VerticalContentAlignment="Top" />
                        </Border>
 
                        <TextBlock x:Name="HDTBootstrapRulesProblemText" Grid.Row="3" Margin="0,8,0,0"
                                   Foreground="{DynamicResource HDTCommandTextBrush}"
                                   TextWrapping="Wrap" Visibility="Collapsed" />
 
                        <StackPanel Grid.Row="4" Orientation="Horizontal"
                                    HorizontalAlignment="Right" Margin="0,10,0,0">
                            <TextBlock x:Name="HDTBootstrapRulesHint" Style="{StaticResource HDTHintText}"
                                       MaxWidth="470" VerticalAlignment="Center" Margin="0,0,12,0" />
                            <Button x:Name="HDTBootstrapRulesReloadButton" MinWidth="90" Margin="0,0,10,0" />
                            <Button x:Name="HDTBootstrapRulesSaveButton" MinWidth="90" Margin="0" />
                        </StackPanel>
                </Grid>
            </TabItem>
        </TabControl>
 
        <!-- the cmdlet the last action ran, and the ways out -->
        <Grid Grid.Row="2" Margin="24,16,24,20">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
 
            <Border Grid.Row="0" Background="{DynamicResource HDTCommandBrush}"
                    BorderBrush="{DynamicResource HDTBorderBrush}" BorderThickness="1"
                    Padding="10,7,10,7">
                <!--
                    AcceptsReturn, ON A BOX NOBODY TYPES INTO. One press of Save
                    is four invocations - the three that decide what is written
                    and the one that writes it - and a TextBox without this
                    shows the first line of them and silently eats the rest.
                    MaxHeight keeps four lines from pushing the buttons off the
                    bottom of a short window.
                -->
                <TextBox x:Name="HDTBootImageCommandText"
                         Text=""
                         IsReadOnly="True" BorderThickness="0"
                         AcceptsReturn="True" MaxHeight="76"
                         VerticalScrollBarVisibility="Auto"
                         Background="Transparent"
                         Foreground="{DynamicResource HDTCommandTextBrush}"
                         FontFamily="Consolas, Courier New" FontSize="12"
                         TextWrapping="Wrap" />
            </Border>
 
            <Grid Grid.Row="1" Margin="0,14,0,0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
 
                <!-- The long one, on its own, away from the ones that answer
                     instantly. It mounts, injects and rebuilds - minutes, not
                     milliseconds - and a mis-click on it beside Close is a
                     coffee break nobody asked for. -->
                <Button Grid.Column="0" x:Name="HDTBootImageUpdateButton"
 MinWidth="150"
 />
 
                <StackPanel Grid.Column="2" Orientation="Horizontal">
                    <Button x:Name="HDTBootImageSaveButton" MinWidth="96" />
                    <Button x:Name="HDTBootImageCloseButton" MinWidth="96" Margin="0" />
                </StackPanel>
            </Grid>
        </Grid>
    </Grid>
</Window>