chromium/remoting/host/installer/win/chromoting.wxs

<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <!-- Note: Including Win64 components in a 32-bit installer usually triggers
       a consistency error. We suppress that error in our build to allow the
       installer to set 64-bit registry keys on 64-bit Windows. Care must be
       taken when adding Win64 components to ensure they are not installed on
       32-bit Windows. -->

  <?define EventSourceName = "chromoting" ?>
  <?define ServiceName = "chromoting" ?>

  <!-- TODO(alexeypa): There strings should be localized,
       see http://crbug.com/121785 -->
  <?if $(var.Branding) ~= Chrome ?>
    <?define ChromotingHost = "Chrome Remote Desktop Host" ?>
    <?define Manufacturer = "Google LLC" ?>
  <?else?>
    <?define ChromotingHost = "Chromoting Host" ?>
    <?define Manufacturer = "The Chromium Authors" ?>
  <?endif?>

  <?if $(sys.BUILDARCH) = "x64" ?>
    <?define ProgramFilesFolderForPlatform = "ProgramFiles64Folder" ?>
    <?define CAQuietExecForPlatform = "CAQuietExec64" ?>
    <?define PowershellExeRegPath = "SOFTWARE\WOW6432Node\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" ?>
  <?else?>
    <?define ProgramFilesFolderForPlatform = "ProgramFilesFolder" ?>
    <?define CAQuietExecForPlatform = "CAQuietExec" ?>
    <?define PowershellExeRegPath = "SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" ?>
  <?endif?>

  <?if $(var.OfficialBuild) != 0 ?>
    <?define ChromotingKeyPath = "Google\Chrome Remote Desktop" ?>
    <?define UrlForwarderName = "Chrome Remote Desktop URL Forwarder" ?>
    <?define UrlForwarderProgId = "ChromeRemoteDesktopUrlForwarder" ?>
  <?else?>
    <?define ChromotingKeyPath = "Chromoting" ?>
    <?define UrlForwarderName = "Chromoting URL Forwarder" ?>
    <?define UrlForwarderProgId = "ChromotingUrlForwarder" ?>
  <?endif?>

  <?define FirewallName = "$(var.ChromotingHost)" ?>

  <?define OmahaAppid = "{b210701e-ffc4-49e3-932b-370728c72662}" ?>
  <?define UpgradeCode = "2b21f767-e157-4fa6-963c-55834c1433a6" ?>

  <?define CoreBinary = "remoting_core.dll" ?>
  <?define HostBinary = "remoting_host.exe" ?>
  <?define RemoteSecurityKeyBinary = "remote_security_key.exe" ?>

  <?define ChromotingTypelib = "{b6396c45-b0cc-456b-9f49-f12964ee6df4}" ?>

  <!-- AppIDs used by the COM components. -->
  <?define RdpAppid = "{52e6fd1a-f16e-49c0-aacb-5436a915448b}" ?>

  <?define IRdpDesktopSessionId = "{6a7699f0-ee43-43e7-aa30-a6738f9bd470}" ?>
  <?define IRdpDesktopSessionEventHandlerId =
      "{b59b96da-83cb-40ee-9b91-c377400fc3e3}" ?>

  <!--
    The long hex value(s) below are security descriptors generated from SDDL
    definition using the PowerShell script below:

    $sddl = "<SDDL definition goes here>"
    $i = ([wmiclass]"Win32_SecurityDescriptorHelper").SDDLToBinarySD($sddl).BinarySD
    -join ($i | foreach {$_.ToString("X2")})
  -->

  <!--
    A security descriptor that gives SYSTEM, built-in administrators and
    LocalService accounts COM_RIGHTS_EXECUTE, COM_RIGHTS_EXECUTE_LOCAL, and
    COM_RIGHTS_ACTIVATE_LOCAL rights. It specifies a mandatory label that
    specifies "no execute up" policy for medium integrity level.

    $sddl = "O:BAG:BAD:(A;;0xb;;;SY)(A;;0xb;;;BA)(A;;0xb;;;LS)S:(ML;;NX;;;ME)"
  -->
  <?define RdpSd = "010014807800000088000000140000003000000002001C000100000011001400040000000101000000000010002000000200480003000000000014000B000000010100000000000512000000000018000B00000001020000000000052000000020020000000014000B0000000101000000000005130000000102000000000005200000002002000001020000000000052000000020020000" ?>

  <!-- Verify that all required parameters are defined. -->
  <?ifndef RdpDesktopSessionClsid ?>
    <?error RdpDesktopSessionClsid must be defined ?>
  <?endif?>

  <?ifndef Version ?>
    <?error Version must be defined ?>
  <?endif?>

  <Product Id="*"
           Language="1033"
           Manufacturer="$(var.Manufacturer)"
           Name="$(var.ChromotingHost)"
           UpgradeCode="$(var.UpgradeCode)"
           Version="$(var.Version)">

    <Package Comments="$(var.ChromotingHost) Package"
             Compressed="yes"
             Description="$(var.ChromotingHost) Package"
             InstallerVersion="200"
             Manufacturer="$(var.Manufacturer)"
             InstallScope="perMachine"/>

    <PropertyRef Id="WIX_ACCOUNT_LOCALSYSTEM" />
    <PropertyRef Id="WIX_ACCOUNT_ADMINISTRATORS" />

    <!-- Note that Windows10 reports its version as 6.3 rather than 10.0 via
        the VersionNT WXS var for back-compat reasons. -->
    <Condition
      Message="$(var.ChromotingHost) is only supported on Windows 10 and above.">
      <![CDATA[Installed OR (VersionNT >= 603)]]>
    </Condition>

    <!-- The upgrade rules below could be expressed with MajorUpgrade element.
         Unfortunately, there is a bug in WiX decompiler (Dark) corrupting
         InstallExecuteSequence table. The installation compiled from
         the disassembled .msi schedules RemoveExistingProducts after
         InstallFinalize while the original installation schedules it after
         InstallInitialize. Fortunately, the verbose version of the upgrade
         rules below decompiles correctly, so we use it instead.
         See http://crbug.com/145265 for more details.
    -->
    <Upgrade Id="$(var.UpgradeCode)">
      <UpgradeVersion IncludeMinimum="no"
                      Minimum="$(var.Version)"
                      OnlyDetect="no"
                      Property="NEWERVERSIONDETECTED" />
      <UpgradeVersion IncludeMaximum="yes"
                      IncludeMinimum="yes"
                      Maximum="$(var.Version)"
                      Minimum="0.0.0.0"
                      Property="OLDERVERSIONBEINGUPGRADED" />
    </Upgrade>

    <Media Id="1" Cabinet="chromoting.cab" EmbedCab="yes"/>

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="$(var.ProgramFilesFolderForPlatform)">
        <?if $(var.OfficialBuild) != 0 ?>
          <Directory Id="program_files_google" Name="Google">
            <Directory Id="chromoting" Name="Chrome Remote Desktop">
              <Directory Id="binaries" Name="$(var.Version)"/>
            </Directory>
          </Directory>
        <?else?>
          <Directory Id="chromoting" Name="Chromoting">
            <Directory Id="binaries" Name="$(var.Version)"/>
          </Directory>
        <?endif?>
      </Directory>
      <Directory Id="CommonAppDataFolder">
        <?if $(var.OfficialBuild) != 0 ?>
          <Directory Id="common_app_data_google" Name="Google">
            <Directory Id="config_files" Name="Chrome Remote Desktop"/>
          </Directory>
        <?else?>
          <Directory Id="config_files" Name="Chromoting"/>
        <?endif?>
      </Directory>
    </Directory>

    <DirectoryRef Id="binaries">
      <Component Id="credits" Guid="*">
        <File Id="CREDITS.txt"
              DiskId="1"
              Name="CREDITS.txt"
              Vital="yes"/>
      </Component>

      <Component Id="remoting_core" Guid="*">
        <File Id="$(var.CoreBinary)"
              DiskId="1"
              KeyPath="yes"
              Name="$(var.CoreBinary)"
              Vital="yes"/>

        <util:EventSource xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
                          Name="$(var.EventSourceName)"
                          Log="Application"
                          CategoryCount="1"
                          CategoryMessageFile="[#$(var.CoreBinary)]"
                          EventMessageFile="[#$(var.CoreBinary)]"
                          SupportsErrors="yes"
                          SupportsInformationals="yes"
                          SupportsWarnings="yes"/>
      </Component>

      <Component Id="remoting_desktop" Guid="*">
        <File Id="remoting_desktop.exe"
              DiskId="1"
              KeyPath="yes"
              Name="remoting_desktop.exe"
              Vital="yes"/>
      </Component>

      <Component Id="remoting_native_messaging_host" Guid="*">
        <File Id="remoting_native_messaging_host.exe"
              DiskId="1"
              KeyPath="yes"
              Name="remoting_native_messaging_host.exe"
              Vital="yes"/>
      </Component>

      <Component Id="remoting_start_host" Guid="*">
        <File Id="remoting_start_host.exe"
              DiskId="1"
              KeyPath="yes"
              Name="remoting_start_host.exe"
              Vital="yes"/>
      </Component>

      <Component Id="remote_assistance_host" Guid="*">
        <File Id="remote_assistance_host.exe"
              DiskId="1"
              KeyPath="yes"
              Name="remote_assistance_host.exe"
              Vital="yes"/>
      </Component>

      <Component Id="remote_assistance_host_uiaccess" Guid="*">
          <File Id="remote_assistance_host_uiaccess.exe"
              DiskId="1"
              KeyPath="yes"
              Name="remote_assistance_host_uiaccess.exe"
              Vital="yes"/>
      </Component>

      <Component Id="remote_open_url" Guid="*">
        <File Id="remote_open_url.exe"
              DiskId="1"
              KeyPath="yes"
              Name="remote_open_url.exe"
              Vital="yes"/>
      </Component>

      <Component Id="remote_webauthn" Guid="*">
        <File Id="remote_webauthn.exe"
              DiskId="1"
              KeyPath="yes"
              Name="remote_webauthn.exe"
              Vital="yes"/>
      </Component>

      <Component Id="remote_open_url_registration" Guid="*">
        <!-- ProgID -->
        <RegistryKey Id="remote_open_url_prog_id_reg_key"
                    Root="HKLM"
                    Key="SOFTWARE\Classes\$(var.UrlForwarderProgId)"
                    Action="create">
          <RegistryKey Key="Application">
            <RegistryValue Type="string"
                          Name="ApplicationCompany"
                          Value="$(var.Manufacturer)"/>
            <RegistryValue Type="string"
                          Name="ApplicationName"
                          Value="@[binaries]$(var.CoreBinary),-119"/>
            <RegistryValue Type="string"
                          Name="ApplicationDescription"
                          Value="@[binaries]$(var.CoreBinary),-120"/>
            <RegistryValue Type="string"
                          Name="ApplicationIcon"
                          Value="[binaries]$(var.CoreBinary),-112"/>
          </RegistryKey>
          <RegistryKey Key="DefaultIcon">
            <RegistryValue Type="string"
                          Value="[binaries]$(var.CoreBinary),-112"/>
          </RegistryKey>

          <RegistryKey Key="shell\open\command">
            <RegistryValue Type="string"
                          Value='"[binaries]remote_open_url.exe" %1'/>
          </RegistryKey>
        </RegistryKey>

        <!-- Capabilities -->
        <RegistryKey Id="remote_open_url_capabilities_reg_key"
                    Root="HKLM"
                    Key="SOFTWARE\$(var.ChromotingKeyPath)\UrlForwarder\Capabilities"
                    Action="create">
          <RegistryValue Type="string"
                        Name="ApplicationDescription"
                        Value="@[binaries]$(var.CoreBinary),-120"/>

          <RegistryKey Key="URLAssociations">
            <RegistryValue Type="string"
                          Name="http"
                          Value="$(var.UrlForwarderProgId)"/>
            <RegistryValue Type="string"
                          Name="https"
                          Value="$(var.UrlForwarderProgId)"/>
            <RegistryValue Type="string"
                          Name="mailto"
                          Value="$(var.UrlForwarderProgId)"/>
          </RegistryKey>
        </RegistryKey>
      </Component>

      <Component Id="native_messaging_host_manifest" Guid="*">
        <File Id="com.google.chrome.remote_desktop.json"
              DiskId="1"
              KeyPath="yes"
              Name="com.google.chrome.remote_desktop.json"
              Vital="yes"/>
      </Component>

      <Component Id="native_messaging_host_firefox_manifest" Guid="*">
        <File Id="com.google.chrome.remote_desktop_firefox.json"
              DiskId="1"
              KeyPath="yes"
              Name="com.google.chrome.remote_desktop-firefox.json"
              Vital="yes"/>
      </Component>

      <Component Id="remote_assistance_host_manifest" Guid="*">
        <File Id="com.google.chrome.remote_assistance.json"
              DiskId="1"
              KeyPath="yes"
              Name="com.google.chrome.remote_assistance.json"
              Vital="yes"/>
      </Component>


      <Component Id="remote_assistance_host_firefox_manifest" Guid="*">
        <File Id="com.google.chrome.remote_assistance_firefox.json"
              DiskId="1"
              KeyPath="yes"
              Name="com.google.chrome.remote_assistance-firefox.json"
              Vital="yes"/>
      </Component>

      <Component Id="remote_webauthn_manifest" Guid="*">
        <File Id="com.google.chrome.remote_webauthn.json"
              DiskId="1"
              KeyPath="yes"
              Name="com.google.chrome.remote_webauthn.json"
              Vital="yes"/>
      </Component>

      <Component Id="icudtl" Guid="*">
        <File Id="icudtl.dat"
              DiskId="1"
              KeyPath="yes"
              Name="icudtl.dat"
              Vital="yes"/>
      </Component>

      <Component Id="remoting_host" Guid="*">
        <File Id="remoting_host.exe"
              DiskId="1"
              Name="remoting_host.exe"
              Vital="yes"/>

        <ServiceInstall Id="install_service"
                        Type="ownProcess"
                        Vital="yes"
                        Name="$(var.ServiceName)"
                        DisplayName="[chromoting_service_display_name]"
                        Description="[chromoting_service_description]"
                        Arguments="--type=daemon --host-config=&quot;[config_files]host.json&quot;"
                        Start="demand"
                        Account="LocalSystem"
                        ErrorControl="ignore"
                        Interactive="no">
          <!-- Configure the service to restart after 1 minute if it crashes -->
          <util:ServiceConfig
              xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
              FirstFailureActionType="restart"
              ResetPeriodInDays="1"
              RestartServiceDelayInSeconds="60"
              SecondFailureActionType="restart"
              ThirdFailureActionType="restart"/>
        </ServiceInstall>

        <ServiceControl Id="start_service"
                        Stop="both"
                        Remove="uninstall"
                        Name="$(var.ServiceName)"
                        Wait="yes" />

        <fire:FirewallException xmlns:fire="http://schemas.microsoft.com/wix/FirewallExtension"
                                Id="me2me_firewall_exception"
                                IgnoreFailure="yes"
                                Name="$(var.FirewallName)"
                                Profile="all"
                                Program="[#remoting_host.exe]"
                                Scope="any" />
      </Component>

      <Component Id="remote_security_key" Guid="*">
        <File Id="$(var.RemoteSecurityKeyBinary)"
              DiskId="1"
              KeyPath="yes"
              Name="$(var.RemoteSecurityKeyBinary)"
              Vital="yes"/>
      </Component>

      <Component Id="remote_security_key_registration" Guid="*">
        <RegistryKey Id="remote_security_key_reg_key"
                     Root="HKLM"
                     Key="SOFTWARE\Google\SecurityKey"
                     Action="create">
          <RegistryValue Type="string"
                         Name="RemoteSecurityKeyPath"
                         Value="[binaries]$(var.RemoteSecurityKeyBinary)"/>
        </RegistryKey>
      </Component>

      <?if $(var.OfficialBuild) != 0 ?>
        <Component Id="omaha_registration" Guid="*">
          <RegistryKey Id="omaha_client_key"
                       Root="HKLM"
                       Key="SOFTWARE\Google\Update\Clients\$(var.OmahaAppid)"
                       Action="create">
            <RegistryValue Type="string"
                           Name="pv"
                           Value="$(var.Version)"/>

            <RegistryValue Type="string"
                           Name="name"
                           Value="$(var.ChromotingHost)"/>
          </RegistryKey>
        </Component>
      <?endif?>

      <Component Id="remoting_lib" Guid="*">
        <RegistryKey Root="HKLM"
                     Key="SOFTWARE\Classes">
          <RegistryKey Key="AppId">
            <RegistryKey Key="$(var.RdpAppid)" Action="create">
              <RegistryValue Type="string"
                             Value="ChromotingRdpDesktopSession"/>
              <RegistryValue Name="AccessPermission"
                             Type="binary"
                             Value="$(var.RdpSd)"/>
              <RegistryValue Name="LaunchPermission"
                             Type="binary"
                             Value="$(var.RdpSd)"/>
              <RegistryValue Name="RunAs"
                             Type="string"
                             Value="NT AUTHORITY\LocalService"/>
            </RegistryKey>

          </RegistryKey>

          <RegistryKey Key="CLSID">
            <RegistryKey Key="$(var.RdpDesktopSessionClsid)" Action="create">
              <RegistryValue Type="string"
                             Value="RdpDesktopSession Class"/>

              <RegistryValue Type="string"
                             Name="AppID"
                             Value="$(var.RdpAppid)"/>

              <RegistryKey Key="LocalServer32" Action="create">
                <RegistryValue Type="string"
                               Value="[binaries]$(var.HostBinary) --type=rdp_desktop_session"/>
              </RegistryKey>

              <RegistryKey Key="TypeLib" Action="create">
                <RegistryValue Type="string"
                               Value="$(var.ChromotingTypelib)"/>
              </RegistryKey>
            </RegistryKey>

            <!-- IRdpDesktopSession PSFactory -->
            <RegistryKey Key="$(var.IRdpDesktopSessionId)"
                         Action="create">
              <RegistryValue Type="string"
                             Value="IRdpDesktopSession PSFactory"/>

              <RegistryKey Key="InprocServer32" Action="create">
                <RegistryValue Type="string"
                               Value="[binaries]$(var.CoreBinary)"/>
              </RegistryKey>
            </RegistryKey>

            <!-- IRdpDesktopSessionEventHandler PSFactory -->
            <RegistryKey Key="$(var.IRdpDesktopSessionEventHandlerId)"
                         Action="create">
              <RegistryValue Type="string"
                             Value="IRdpDesktopSessionEventHandler PSFactory"/>

              <RegistryKey Key="InprocServer32" Action="create">
                <RegistryValue Type="string"
                               Value="[binaries]$(var.CoreBinary)"/>
              </RegistryKey>
            </RegistryKey>
          </RegistryKey>

          <RegistryKey Key="Interface">
            <!-- IDaemonControl2 interface -->
            <RegistryKey Key="{655bd819-c08c-4b04-80c2-f160739ff6ef}"
                         Action="create">
              <RegistryKey Key="ProxyStubClsid32" Action="create">
                <RegistryValue Type="string"
                               Value="{00020424-0000-0000-C000-000000000046}"/>
              </RegistryKey>

              <RegistryKey Key="TypeLib" Action="create">
                <RegistryValue Type="string"
                               Value="$(var.ChromotingTypelib)"/>
              </RegistryKey>
            </RegistryKey>

            <!-- IDaemonControl interface -->
            <RegistryKey Key="{e051a481-6345-4ba1-bdb1-cf7929955268}"
                         Action="create">
              <RegistryKey Key="ProxyStubClsid32" Action="create">
                <RegistryValue Type="string"
                               Value="{00020424-0000-0000-C000-000000000046}"/>
              </RegistryKey>

              <RegistryKey Key="TypeLib" Action="create">
                <RegistryValue Type="string"
                               Value="$(var.ChromotingTypelib)"/>
              </RegistryKey>
            </RegistryKey>

            <!-- IRdpDesktopSession interface -->
            <RegistryKey Key="$(var.IRdpDesktopSessionId)"
                         Action="create">
              <RegistryValue Type="string"
                             Value="IRdpDesktopSession"/>
              <RegistryKey Key="ProxyStubClsid32" Action="create">
                <RegistryValue Type="string"
                               Value="$(var.IRdpDesktopSessionId)"/>
              </RegistryKey>
            </RegistryKey>

            <!-- IRdpDesktopSessionEventHandler interface -->
            <RegistryKey Key="$(var.IRdpDesktopSessionEventHandlerId)"
                         Action="create">
              <RegistryValue Type="string"
                             Value="IRdpDesktopSessionEventHandler"/>
              <RegistryKey Key="ProxyStubClsid32" Action="create">
                <RegistryValue Type="string"
                               Value="$(var.IRdpDesktopSessionEventHandlerId)"/>
              </RegistryKey>

              <RegistryKey Key="TypeLib" Action="create">
                <RegistryValue Type="string"
                               Value="$(var.ChromotingTypelib)"/>
              </RegistryKey>
            </RegistryKey>
          </RegistryKey>

          <RegistryKey Key="Typelib">
            <RegistryKey Key="$(var.ChromotingTypelib)" Action="create">
              <RegistryKey Key="1.0" Action="create">
                <RegistryValue Type="string"
                               Value="Chromoting 1.0 Type Library"/>
                <RegistryKey Key="0" Action="create">
                  <RegistryKey Key="win32" Action="create">
                    <RegistryValue Type="string"
                                   Value="[binaries]$(var.CoreBinary)"/>
                  </RegistryKey>
                </RegistryKey>

                <RegistryKey Key="FLAGS" Action="create">
                  <RegistryValue Type="string"
                                 Value="0"/>
                </RegistryKey>

                <RegistryKey Key="HELPDIR" Action="create">
                  <RegistryValue Type="string"
                                 Value="[binaries]"/>
                </RegistryKey>
              </RegistryKey>
            </RegistryKey>
          </RegistryKey>
        </RegistryKey>

      </Component>

      <!-- Creates the pairing registry store and protect it with an ACL. -->
      <Component Id="remoting_pairing_registry" Guid="960bc7eb-a816-428b-90e8-ad13336955d5">
        <RegistryKey Root="HKLM"
                     Key="SOFTWARE\$(var.ChromotingKeyPath)\paired-clients"
                     Action="create">
          <RegistryKey Key="clients" Action="create"/>
          <RegistryKey Key="secrets" Action="create">
            <!-- Gives full access to SYSTEM only. -->
            <!-- Cannot use the builtin PermissionEx element because it maps
                 to the MsiLockPermissionsEx table which is not supported on
                 Windows Installer version 4.5 or lower. Also cannot use
                 PermissionEx in WixUtilExtension because it automatically
                 inherits all the ACLs from the parent. -->
            <Permission User="[WIX_ACCOUNT_LOCALSYSTEM]"
                        GenericAll="yes"
                        ChangePermission="yes"
                        TakeOwnership="yes"/>
            <Permission User="[WIX_ACCOUNT_ADMINISTRATORS]"
                        GenericAll="yes"
                        ChangePermission="yes"
                        TakeOwnership="yes"/>
          </RegistryKey>
        </RegistryKey>
        <CreateFolder/>
      </Component>

      <Component Id="native_messaging_host_registry" Guid="*">
        <RegistryKey Root="HKLM"
                     Key="SOFTWARE\Google\chrome\NativeMessagingHosts"
                     Action="create">
          <RegistryKey Key="com.google.chrome.remote_desktop" Action="create">
            <RegistryValue
                Type="string"
                Value="[binaries]com.google.chrome.remote_desktop.json"/>
          </RegistryKey>
        </RegistryKey>
        <CreateFolder/>
      </Component>

      <!-- Firefox requires the key to be installed in the native registry -->
      <Component Id="native_messaging_host_firefox_registry_win32"
                 Guid="*"
                 Win64="no">
        <Condition>NOT Msix64</Condition>
        <RegistryKey Root="HKLM"
                     Key="SOFTWARE\Mozilla\NativeMessagingHosts"
                     Action="create">
          <RegistryKey Key="com.google.chrome.remote_desktop" Action="create">
            <RegistryValue
                Type="string"
                Value="[binaries]com.google.chrome.remote_desktop-firefox.json"/>
          </RegistryKey>
        </RegistryKey>
        <CreateFolder/>
      </Component>

      <Component Id="native_messaging_host_firefox_registry_win64"
                 Guid="*"
                 Win64="yes">
        <Condition>Msix64</Condition>
        <RegistryKey Root="HKLM"
                     Key="SOFTWARE\Mozilla\NativeMessagingHosts"
                     Action="create">
          <RegistryKey Key="com.google.chrome.remote_desktop" Action="create">
            <RegistryValue
                Type="string"
                Value="[binaries]com.google.chrome.remote_desktop-firefox.json"/>
          </RegistryKey>
        </RegistryKey>
        <CreateFolder/>
      </Component>

      <Component Id="remote_assistance_host_registry" Guid="*">
        <RegistryKey Root="HKLM"
                     Key="SOFTWARE\Google\chrome\NativeMessagingHosts"
                     Action="create">
          <RegistryKey Key="com.google.chrome.remote_assistance"
                       Action="create">
            <RegistryValue
                Type="string"
                Value="[binaries]com.google.chrome.remote_assistance.json"/>
          </RegistryKey>
        </RegistryKey>
        <CreateFolder/>
      </Component>

      <Component Id="remote_assistance_host_firefox_registry_win32"
                 Guid="*"
                 Win64="no">
        <Condition>NOT Msix64</Condition>
        <RegistryKey Root="HKLM"
                     Key="SOFTWARE\Mozilla\NativeMessagingHosts"
                     Action="create">
          <RegistryKey Key="com.google.chrome.remote_assistance"
                       Action="create">
            <RegistryValue
                Type="string"
                Value="[binaries]com.google.chrome.remote_assistance-firefox.json"/>
          </RegistryKey>
        </RegistryKey>
        <CreateFolder/>
      </Component>

      <Component Id="remote_assistance_host_firefox_registry_win64"
                 Guid="*"
                 Win64="yes">
        <Condition>Msix64</Condition>
        <RegistryKey Root="HKLM"
                     Key="SOFTWARE\Mozilla\NativeMessagingHosts"
                     Action="create">
          <RegistryKey Key="com.google.chrome.remote_assistance"
                       Action="create">
            <RegistryValue
                Type="string"
                Value="[binaries]com.google.chrome.remote_assistance-firefox.json"/>
          </RegistryKey>
        </RegistryKey>
        <CreateFolder/>
      </Component>

      <Component Id="remote_webauthn_registry" Guid="*">
        <RegistryKey Root="HKLM"
                     Key="SOFTWARE\Google\chrome\NativeMessagingHosts"
                     Action="create">
          <RegistryKey Key="com.google.chrome.remote_webauthn"
                       Action="create">
            <RegistryValue
                Type="string"
                Value="[binaries]com.google.chrome.remote_webauthn.json"/>
          </RegistryKey>
        </RegistryKey>
        <CreateFolder/>
      </Component>

      <Component Id="remoting_logging_registry"
                 Guid="b640a025-18dd-49b9-b26d-b31252a12f8a">
        <RegistryKey Root="HKLM"
                     Key="SOFTWARE\$(var.ChromotingKeyPath)\logging"
                     Action="create">
        </RegistryKey>
        <CreateFolder/>
      </Component>

    </DirectoryRef>

    <!-- Register with Sawbuck. See http://code.google.com/p/sawbuck/. -->
    <DirectoryRef Id="TARGETDIR">
      <Component Id="sawbuck_provider" Guid="*" Win64="no">
        <RegistryKey Root="HKLM"
                     Key="SOFTWARE\Google\Sawbuck\Providers">
          <RegistryKey Key="{2db51ca1-4fd8-4b88-b5a2-fb8606b66b02}"
                       Action="create">
            <RegistryValue Type="string" Value="Chromoting"/>
            <RegistryValue Name="default_flags" Type="integer" Value="1"/>
            <RegistryValue Name="default_level" Type="integer" Value="4"/>
            <RegistryKey Key="Flags" Action="create">
              <RegistryKey Key="Stack Trace" Action="create">
                <RegistryValue Type="integer" Value="1"/>
              </RegistryKey>
              <RegistryKey Key="Text Only" Action="create">
                <RegistryValue Type="integer" Value="2"/>
              </RegistryKey>
            </RegistryKey>
          </RegistryKey>
        </RegistryKey>
      </Component>
    </DirectoryRef>

    <!-- The service is always installed in the stopped state with start type
         set to 'manual'. This becomes a problem when upgrading an existing
         installation that is configured to start the service automatically.

         Here we check the startup type before making any changes, then restart
         the service as needed once the installation is finished. -->
    <Property Id="CHROMOTING_SERVICE_START_TYPE">
      <RegistrySearch Id="chromoting_service_start_type"
                      Root="HKLM"
                      Key="SYSTEM\CurrentControlSet\services\$(var.ServiceName)"
                      Name="Start"
                      Type="raw" />
    </Property>

    <CustomAction Id="query_auto_start_service"
                  Property="auto_start_service"
                  Value="[CHROMOTING_SERVICE_START_TYPE]" />

    <CustomAction Id="start_chromoting_service"
                  Impersonate="no"
                  Execute="deferred"
                  Script="jscript">
      <![CDATA[
        var ADS_SERVICE_STOPPED = 0x00000001;
        var ADS_SERVICE_AUTO_START = 2;
        var service = GetObject("WinNT://./$(var.ServiceName),Service");
        service.StartType = ADS_SERVICE_AUTO_START;
        service.SetInfo();
        if (service.Status == ADS_SERVICE_STOPPED) {
          service.Start();
        }
      ]]>
    </CustomAction>

    <CustomAction Id="set_service_display_name"
                  Property="chromoting_service_display_name"
                  Value="@[binaries]$(var.CoreBinary),-101" />
    <CustomAction Id="set_service_description"
                  Property="chromoting_service_description"
                  Value="@[binaries]$(var.CoreBinary),-102" />

    <UIRef Id="WixUI_ErrorProgressText" />

    <Feature Id="chromoting_host" Level="1" Title="$(var.ChromotingHost)">
      <ComponentRef Id="credits"/>
      <?if $(var.OfficialBuild) != 0 ?>
        <ComponentRef Id="omaha_registration"/>
      <?endif?>
      <ComponentRef Id="icudtl"/>
      <ComponentRef Id="native_messaging_host_firefox_manifest"/>
      <ComponentRef Id="native_messaging_host_firefox_registry_win32"/>
      <ComponentRef Id="native_messaging_host_firefox_registry_win64"/>
      <ComponentRef Id="native_messaging_host_manifest"/>
      <ComponentRef Id="native_messaging_host_registry"/>
      <ComponentRef Id="remote_assistance_host"/>
      <ComponentRef Id="remote_assistance_host_firefox_manifest"/>
      <ComponentRef Id="remote_assistance_host_firefox_registry_win32"/>
      <ComponentRef Id="remote_assistance_host_firefox_registry_win64"/>
      <ComponentRef Id="remote_assistance_host_manifest"/>
      <ComponentRef Id="remote_assistance_host_registry"/>
      <ComponentRef Id="remote_assistance_host_uiaccess"/>
      <ComponentRef Id="remote_webauthn"/>
      <ComponentRef Id="remote_webauthn_manifest"/>
      <ComponentRef Id="remote_webauthn_registry"/>

      <ComponentRef Id="remote_open_url"/>
      <ComponentRef Id="remote_open_url_registration"/>

      <ComponentRef Id="remote_security_key"/>
      <ComponentRef Id="remote_security_key_registration"/>
      <ComponentRef Id="remoting_native_messaging_host"/>
      <ComponentRef Id="remoting_core"/>
      <ComponentRef Id="remoting_desktop"/>
      <ComponentRef Id="remoting_host"/>
      <ComponentRef Id="remoting_lib"/>
      <ComponentRef Id="remoting_logging_registry"/>
      <ComponentRef Id="remoting_pairing_registry"/>
      <ComponentRef Id="remoting_start_host"/>
      <ComponentRef Id="sawbuck_provider"/>
    </Feature>

    <!-- Set the icon shown in Add/Remove Programs. -->
    <Icon Id="chromoting.ico" SourceFile="chromoting.ico"/>
    <Property Id="ARPPRODUCTICON" Value="chromoting.ico" />

    <CustomAction Id="set_maintenance" Property="MAINTENANCE" Value="true" />

    <!-- Set to reinstall all features. -->
    <CustomAction Id="set_reinstall_all_property"
                  Property="REINSTALL"
                  Value="ALL" />
    <!-- "amus" will force reinstall all files.
         See https://docs.microsoft.com/en-us/windows/desktop/Msi/reinstallmode -->
    <CustomAction Id="set_reinstallmode_property"
                  Property="REINSTALLMODE"
                  Value="amus" />

    <Property Id="POWERSHELLEXE">
      <RegistrySearch Id="POWERSHELLEXE"
        Type="raw"
        Root="HKLM"
        Key="$(var.PowershellExeRegPath)"
        Name="Path" />
    </Property>

    <!-- Actions are run in quiet mode (no interactive windows are shown). This is done
         using a custom action that uses CAQuietExec to execute a command line which is
         stored in a property with the same name as the action. -->
    <SetProperty Id="make_symbolic_link"
      Value="&quot;[POWERSHELLEXE]&quot; -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass New-Item -ItemType SymbolicLink -Path '[chromoting]CurrentVersion' -Target '[binaries]' -Force"
      Before="make_symbolic_link"
      Sequence="execute" />
    <CustomAction Id="make_symbolic_link"
      BinaryKey="WixCA"
      DllEntry="$(var.CAQuietExecForPlatform)"
      Execute="deferred"
      Impersonate="no"
      Return="ignore"/>

    <!-- We're using (Get-Item "symlink").Delete() because using Remove-Item for a
         symlink will recursively delete the folder being pointed to which we may not
         want, for instance if we are re-creating the link in maintenance mode. -->
    <SetProperty Id="remove_symbolic_link"
      Value="&quot;[POWERSHELLEXE]&quot; -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass (Get-Item '[chromoting]CurrentVersion').Delete()"
      Before="remove_symbolic_link"
      Sequence="execute" />
    <CustomAction Id="remove_symbolic_link"
      BinaryKey="WixCA"
      DllEntry="$(var.CAQuietExecForPlatform)"
      Execute="deferred"
      Impersonate="no"
      Return="ignore"/>

    <SetProperty Id="remove_logs"
      Value="&quot;[POWERSHELLEXE]&quot; -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass Remove-Item -Force '[binaries]*.log'"
      Before="remove_logs"
      Sequence="execute" />
    <CustomAction Id="remove_logs"
      BinaryKey="WixCA"
      DllEntry="$(var.CAQuietExecForPlatform)"
      Execute="deferred"
      Impersonate="no"
      Return="ignore"/>

    <SetProperty Id="remove_minidumps"
      Value="&quot;[POWERSHELLEXE]&quot; -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass Remove-Item -Force -Recurse '[binaries]minidumps'"
      Before="remove_minidumps"
      Sequence="execute" />
    <CustomAction Id="remove_minidumps"
      BinaryKey="WixCA"
      DllEntry="$(var.CAQuietExecForPlatform)"
      Execute="deferred"
      Impersonate="no"
      Return="ignore"/>

    <!-- Prevents errors during installation time when the website client has an
         active native messaging host instance running. Actions are run in quiet
         mode (no interactive windows are shown). This is done using a custom
         action that uses CAQuietExec to execute a command line which is stored
         in a property with the same name as the action. -->
    <SetProperty Id="kill_remoting_native_messaging_host"
      Value="&quot;[POWERSHELLEXE]&quot; -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass Stop-Process -Force -Name remoting_native_messaging_host"
      Before="kill_remoting_native_messaging_host"
      Sequence="execute" />
    <CustomAction Id="kill_remoting_native_messaging_host"
      BinaryKey="WixCA"
      DllEntry="$(var.CAQuietExecForPlatform)"
      Execute="deferred"
      Impersonate="no"
      Return="ignore"/>

    <SetProperty Id="kill_remote_assistance_host_uiaccess"
      Value="&quot;[POWERSHELLEXE]&quot; -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass Stop-Process -Force -Name remote_assistance_host_uiaccess"
      Before="kill_remote_assistance_host_uiaccess"
      Sequence="execute" />
    <CustomAction Id="kill_remote_assistance_host_uiaccess"
      BinaryKey="WixCA"
      DllEntry="$(var.CAQuietExecForPlatform)"
      Execute="deferred"
      Impersonate="no"
      Return="ignore"/>

    <SetProperty Id="kill_remote_assistance_host"
      Value="&quot;[POWERSHELLEXE]&quot; -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass Stop-Process -Force -Name remote_assistance_host"
      Before="kill_remote_assistance_host"
      Sequence="execute" />
    <CustomAction Id="kill_remote_assistance_host"
      BinaryKey="WixCA"
      DllEntry="$(var.CAQuietExecForPlatform)"
      Execute="deferred"
      Impersonate="no"
      Return="ignore"/>

    <SetProperty Id="kill_remote_webauthn"
      Value="&quot;[POWERSHELLEXE]&quot; -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass -Force Stop-Process -Name remote_webauthn"
      Before="kill_remote_webauthn"
      Sequence="execute" />
    <CustomAction Id="kill_remote_webauthn"
      BinaryKey="WixCA"
      DllEntry="$(var.CAQuietExecForPlatform)"
      Execute="deferred"
      Impersonate="no"
      Return="ignore"/>

    <InstallExecuteSequence>
      <!-- Set REINSTALL=all and REINSTALLMODE=amus if the user reruns the
           MSI, which will force reinstalling all files and services.  -->
      <Custom Action="set_maintenance" Before="set_reinstall_all_property">
        Installed AND (NOT REMOVE) AND (NOT UPGRADINGPRODUCTCODE)
      </Custom>
      <Custom Action="set_reinstall_all_property"
              Before="set_reinstallmode_property">
        MAINTENANCE
      </Custom>
      <Custom Action="set_reinstallmode_property" Before="LaunchConditions">
        MAINTENANCE
      </Custom>

      <Custom Action="query_auto_start_service" Before="InstallInitialize"/>
      <Custom Action="start_chromoting_service" After="StartServices">
        <![CDATA[NOT REMOVE AND (auto_start_service = "#2")]]>
      </Custom>

      <!-- Set the service name and description -->
      <Custom Action="set_service_display_name" Before="InstallInitialize"/>
      <Custom Action="set_service_description" Before="InstallInitialize"/>

      <!-- Schedule RemoveExistingProducts before installing any files.
           See http://msdn.microsoft.com/en-us/library/aa371197.aspx. -->
      <RemoveExistingProducts After="InstallInitialize" />

      <Custom Action="remove_logs" Before="RemoveFiles">
        Installed AND (NOT MAINTENANCE)
      </Custom>
      <Custom Action="remove_minidumps" Before="RemoveFiles">
        Installed AND (NOT MAINTENANCE)
      </Custom>
      <Custom Action="remove_symbolic_link" Before="RemoveFiles">
        Installed AND (NOT MAINTENANCE)
      </Custom>
      <Custom Action="kill_remote_assistance_host_uiaccess" After="InstallInitialize">
        Installed
      </Custom>
      <!-- Kill the 'uiaccess' child process before killing the parent process. -->
      <Custom Action="kill_remote_assistance_host" After="kill_remote_assistance_host_uiaccess">
        Installed
      </Custom>
      <Custom Action="kill_remoting_native_messaging_host" After="InstallInitialize">
        Installed
      </Custom>
      <Custom Action="kill_remote_webauthn" After="InstallInitialize">
        Installed
      </Custom>
      <Custom Action="make_symbolic_link" After="InstallFiles">
        NOT Installed
      </Custom>
    </InstallExecuteSequence>
  </Product>
</Wix>