Templates/Wizard/BitLocker.xaml

<!--
    WHETHER THIS MACHINE IS ENCRYPTED, and with what, asked once rather than
    decided per task sequence. (MDT administrators know this screen as the
    BitLocker pane.)
 
    THE PAGE SETS VARIABLES; THE STEP READS THEM. The EnableBitLocker step in
    client.yaml resolves %HDTBitLockerProtector% and %HDTBitLockerEscrow% and
    runs at all only when $HDTEnableBitLocker is true - so this page is not
    wired to anything special. It answers three questions and the sequence
    decides what to do with them, which is how every other page here works.
 
    OFF IS THE DEFAULT, DELIBERATELY. An unticked box leaves
    HDTEnableBitLocker false, the step's condition is false, and the deployment
    does exactly what it did before this page existed. A wizard page that
    silently started encrypting disks would be a worse surprise than one that
    has to be ticked.
 
    SCOPE AND METHOD ARE NOT ASKED. usedSpaceOnly vs full, and which AES, are
    policy for a site rather than a decision at a bench - they stay authored in
    the task sequence where an administrator sets them once. The three asked
    here are the three that change per machine.
 
    xmlns AND xmlns:x ARE BOTH DECLARED. A page fragment is loaded standalone by
    XamlReader, so it carries no namespace by inheritance - and one using
    x:Name without xmlns:x throws "'x' is an undeclared prefix" at load, which
    on a bench looks like a wizard that failed to open.
 
    THE CONTROLS CARRY NO COLOURS. They take their brushes from HDTTheme.xaml,
    like every other control on every other page.
-->
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
 
    <CheckBox Grid.Row="0" Grid.Column="1" x:Name="HDTBitLockerEnableBox"
              Content="Encrypt this computer with BitLocker" Foreground="#FFCCCCCC"
              FontSize="14" Margin="0,0,0,16" HorizontalAlignment="Left" />
 
    <TextBlock Grid.Row="1" Grid.Column="0" Text="Unlocked by" Foreground="#FF8A8A8A"
               FontSize="13" VerticalAlignment="Center" Margin="0,0,16,10"
               ToolTip="What the machine needs at boot to unlock the drive." />
    <ComboBox Grid.Row="1" Grid.Column="1" x:Name="HDTBitLockerProtectorBox" SelectedValuePath="Tag"
              Width="380" HorizontalAlignment="Left" Margin="0,0,0,10">
        <ComboBoxItem Tag="tpm" Content="TPM only - unlocks with no typing" IsSelected="True" />
        <ComboBoxItem Tag="tpmPin" Content="TPM and a PIN" />
        <ComboBoxItem Tag="tpmStartupKey" Content="TPM and a startup key on USB" />
    </ComboBox>
 
    <!--
        THE PIN AND THE STARTUP KEY, WITHOUT WHICH TWO OF THE THREE PROTECTORS
        REFUSE. Invoke-HDTEnableBitLockerStep will not run a tpmPin without a
        pin, or a tpmStartupKey without a path:
 
            protector: tpmPin needs a pin, and this step declares none.
 
        This page shipped offering both choices and collecting neither, so
        picking either produced a deployment that failed at the last step with
        a message about a value the technician had never been asked for.
 
        BOTH ARE BLANK FOR TPM-ONLY AND THAT IS FINE. The step only demands the
        one its protector needs, so an empty box costs nothing when it is not
        the choice.
 
        THE PIN IS A PasswordBox BECAUSE IT IS TYPED AT A BENCH, not because it
        stays secret afterwards - it is authored into sequence.yaml as readable
        text exactly as HDTAdminPassword is (DESIGN 4.5.2), since a value WinPE
        must use with nobody present cannot be protected by a key that ships in
        the same boot image. Masking it stops the shoulder, not the file.
 
        AND IT HAS AN EYE, BECAUSE NOTHING ELSE HERE CATCHES A TYPO. The
        administrator password page asks twice; this asks once, and a mistyped
        PIN is not found at the bench - it is found by the person the machine
        is handed to, at a boot screen, with no way back in. The trio
        New-HDTWizardHost wires is named off the box: HDTBitLockerPinBox wants
        HDTBitLockerPinRevealBox and HDTBitLockerPinRevealToggle.
 
        OFF BY DEFAULT, like every other eye, and the value it uncovers is
        readable in sequence.yaml anyway - which is the paragraph above, and
        the reason masking this one was always about the shoulder.
    -->
    <TextBlock Grid.Row="2" Grid.Column="0" Text="Startup PIN" Foreground="#FF8A8A8A"
               FontSize="13" VerticalAlignment="Center" Margin="0,0,16,10"
               ToolTip="Only for 'TPM and a PIN'. Typed on the machine at every boot." />
    <Grid Grid.Row="2" Grid.Column="1" Margin="0,0,0,10" HorizontalAlignment="Left">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="380" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
 
        <PasswordBox Grid.Column="0" x:Name="HDTBitLockerPinBox"
                     Width="380" HorizontalAlignment="Left" />
 
        <TextBox Grid.Column="0" x:Name="HDTBitLockerPinRevealBox" Width="380"
                 HorizontalAlignment="Left" Visibility="Collapsed" />
 
        <ToggleButton Grid.Column="1" x:Name="HDTBitLockerPinRevealToggle"
                      Style="{DynamicResource HDTRevealEye}"
                      Width="36" Height="34" Margin="8,0,0,0"
                      ToolTip="Show the password" />
    </Grid>
 
    <TextBlock Grid.Row="3" Grid.Column="0" Text="Startup key" Foreground="#FF8A8A8A"
               FontSize="13" VerticalAlignment="Center" Margin="0,0,16,10"
               ToolTip="Only for 'TPM and a startup key'. Where the key is written - for example E:\ ." />
    <TextBox Grid.Row="3" Grid.Column="1" x:Name="HDTBitLockerStartupKeyBox"
             Width="380" HorizontalAlignment="Left" Margin="0,0,0,10" />
 
    <TextBlock Grid.Row="4" Grid.Column="0" Text="Recovery key" Foreground="#FF8A8A8A"
               FontSize="13" VerticalAlignment="Center" Margin="0,0,16,10"
               ToolTip="Where the recovery key is escrowed. Without one, a machine that loses its TPM is unrecoverable." />
    <!--
        ROW 4, WITH THE LABEL THAT NAMES IT. This said Grid.Row="2" - the
        Startup PIN's row - so the escrow list was drawn ON TOP OF the PIN box,
        in the same column, at the same width. WPF stacks whatever shares a
        cell and the later child wins, so the PIN box was on the page,
        collectable, tabbable and completely invisible; row 4 held its label
        and nothing else. Found by the rule that every password box has an eye,
        which is what made somebody look at this cell at all.
    -->
    <ComboBox Grid.Row="4" Grid.Column="1" x:Name="HDTBitLockerEscrowBox" SelectedValuePath="Tag"
              Width="380" HorizontalAlignment="Left" Margin="0,0,0,10">
        <ComboBoxItem Tag="ad" Content="Active Directory" IsSelected="True" />
        <ComboBoxItem Tag="entra" Content="Microsoft Entra ID" />
        <ComboBoxItem Tag="none" Content="Do not escrow it" />
    </ComboBox>
 
    <!--
        ONE LINE, AND IT IS THE ONE THAT COSTS A MACHINE. Everything else -
        which protectors exist, what escrow means, why usedSpaceOnly is faster
        - is in the comment above and in the step's own help, where the next
        person to change this reads it and a technician does not.
    -->
    <TextBlock Grid.Row="5" Grid.Column="1" Foreground="#FF8A8A8A" FontSize="12"
               TextWrapping="Wrap" MaxWidth="380" HorizontalAlignment="Left"
               Text="Without an escrowed recovery key, a machine that loses its TPM cannot be unlocked by anyone." />
</Grid>