diff --git a/src/common/include/displaydevice/settingsmanagerinterface.h b/src/common/include/displaydevice/settingsmanagerinterface.h
index 7f225d7..e49c615 100644
--- a/src/common/include/displaydevice/settingsmanagerinterface.h
+++ b/src/common/include/displaydevice/settingsmanagerinterface.h
@@ -18,6 +18,7 @@ namespace display_device {
       DevicePrepFailed,
       PrimaryDevicePrepFailed,
       DisplayModePrepFailed,
+      HdrStatePrepFailed,
       PersistenceSaveFailed,
     };
 
diff --git a/src/windows/include/displaydevice/windows/settingsmanager.h b/src/windows/include/displaydevice/windows/settingsmanager.h
index 01c4338..4ed05c5 100644
--- a/src/windows/include/displaydevice/windows/settingsmanager.h
+++ b/src/windows/include/displaydevice/windows/settingsmanager.h
@@ -76,6 +76,18 @@ namespace display_device {
     [[nodiscard]] bool
     prepareDisplayModes(const SingleDisplayConfiguration &config, const std::string &device_to_configure, const std::set<std::string> &additional_devices_to_configure, DdGuardFn &guard_fn, SingleDisplayConfigState &new_state);
 
+    /**
+     * @brief Changes or restores the HDR states based on the cached state, new state and configuration.
+     * @param config Configuration to be used for preparing HDR states.
+     * @param device_to_configure The main device to be used for preparation.
+     * @param additional_devices_to_configure Additional devices that should be configured.
+     * @param guard_fn Reference to the guard function which will be set to restore original state (if needed) in case something else fails down the line.
+     * @param new_state Reference to the new state which is to be updated accordingly.
+     * @return True if no errors have occured, false otherwise.
+     */
+    [[nodiscard]] bool
+    prepareHdrStates(const SingleDisplayConfiguration &config, const std::string &device_to_configure, const std::set<std::string> &additional_devices_to_configure, DdGuardFn &guard_fn, SingleDisplayConfigState &new_state);
+
     /**
      * @brief Try to revert the modified settings.
      * @returns True on success, false otherwise.
diff --git a/src/windows/include/displaydevice/windows/settingsutils.h b/src/windows/include/displaydevice/windows/settingsutils.h
index 24f5fc7..b88a610 100644
--- a/src/windows/include/displaydevice/windows/settingsutils.h
+++ b/src/windows/include/displaydevice/windows/settingsutils.h
@@ -117,6 +117,22 @@ namespace display_device::win_utils {
     const std::set<std::string> &additional_devices_to_configure,
     const DeviceDisplayModeMap &original_modes);
 
+  /**
+   * @brief Compute new HDR states from arbitrary data.
+   * @param hdr_state Specify state that should be used to override the original states.
+   * @param configuring_primary_devices Specify whether the `device_to_configure` was unspecified (primary device was selected).
+   * @param device_to_configure Main device to be configured.
+   * @param additional_devices_to_configure Additional devices that belong to the same group as `device_to_configure`.
+   * @param original_states HDR states to be used as a base onto which changes are made.
+   * @return New HDR states that should be set.
+   */
+  HdrStateMap
+  computeNewHdrStates(const std::optional<HdrState> &hdr_state,
+    bool configuring_primary_devices,
+    const std::string &device_to_configure,
+    const std::set<std::string> &additional_devices_to_configure,
+    const HdrStateMap &original_states);
+
   /**
    * @brief Make guard function for the topology.
    * @param win_dd Interface for interacting with the OS.
@@ -210,4 +226,21 @@ namespace display_device::win_utils {
    */
   DdGuardFn
   hdrStateGuardFn(WinDisplayDeviceInterface &win_dd, const ActiveTopology &topology);
+
+  /**
+   * @brief Make guard function for the HDR states.
+   * @param win_dd Interface for interacting with the OS.
+   * @param states HDR states to restore when the guard is executed.
+   * @return Function that once called will try to revert HDR states to the ones that were provided.
+   *
+   * EXAMPLES:
+   * ```cpp
+   * WinDisplayDeviceInterface* iface = getIface(...);
+   * const HdrStateMap states { };
+   *
+   * boost::scope::scope_exit guard { hdrStateGuardFn(*iface, states) };
+   * ```
+   */
+  DdGuardFn
+  hdrStateGuardFn(WinDisplayDeviceInterface &win_dd, const HdrStateMap &states);
 }  // namespace display_device::win_utils
diff --git a/src/windows/settingsmanagerapply.cpp b/src/windows/settingsmanagerapply.cpp
index 94ef909..024c9b1 100644
--- a/src/windows/settingsmanagerapply.cpp
+++ b/src/windows/settingsmanagerapply.cpp
@@ -82,12 +82,12 @@ namespace display_device {
       return ApplyResult::DisplayModePrepFailed;
     }
 
-    // TODO:
-    //
-    //    Other device handling goes here that will use device_to_configure and additional_devices_to_configure:
-    //
-    //      - handle HDR (need to replicate the HDR bug and find the best place for workaround)
-    //
+    DdGuardFn hdr_state_guard_fn { noopFn };
+    boost::scope::scope_exit<DdGuardFn &> hdr_state_guard { hdr_state_guard_fn };
+    if (!prepareHdrStates(config, device_to_configure, additional_devices_to_configure, hdr_state_guard_fn, new_state)) {
+      // Error already logged
+      return ApplyResult::HdrStatePrepFailed;
+    }
 
     // We will always keep the new state persistently, even if there are no new meaningful changes, because
     // we want to preserve the initial state for consistency.
@@ -105,6 +105,7 @@ namespace display_device {
     topology_prep_guard.set_active(false);
     primary_guard.set_active(false);
     mode_guard.set_active(false);
+    hdr_state_guard.set_active(false);
     return ApplyResult::Ok;
   }
 
@@ -304,4 +305,59 @@ namespace display_device {
 
     return true;
   }
+
+  [[nodiscard]] bool
+  SettingsManager::prepareHdrStates(const SingleDisplayConfiguration &config, const std::string &device_to_configure, const std::set<std::string> &additional_devices_to_configure, DdGuardFn &guard_fn, SingleDisplayConfigState &new_state) {
+    const auto &cached_state { m_persistence_state->getState() };
+    const auto cached_hdr_states { cached_state ? cached_state->m_modified.m_original_hdr_states : HdrStateMap {} };
+    const bool change_required { config.m_hdr_state };
+    const bool might_need_to_restore { !cached_hdr_states.empty() };
+
+    HdrStateMap current_hdr_states;
+    if (change_required || might_need_to_restore) {
+      current_hdr_states = m_dd_api->getCurrentHdrStates(win_utils::flattenTopology(new_state.m_modified.m_topology));
+      if (current_hdr_states.empty()) {
+        DD_LOG(error) << "Failed to get current HDR states!";
+        return false;
+      }
+    }
+
+    const auto try_change { [&](const HdrStateMap &new_states, const auto info_preamble, const auto error_log) {
+      if (current_hdr_states != new_states) {
+        DD_LOG(info) << info_preamble << toJson(new_states);
+        if (!m_dd_api->setHdrStates(new_states)) {
+          DD_LOG(error) << error_log;
+          return false;
+        }
+
+        guard_fn = win_utils::hdrStateGuardFn(*m_dd_api, current_hdr_states);
+      }
+
+      return true;
+    } };
+
+    if (change_required) {
+      const bool configuring_primary_devices { config.m_device_id.empty() };
+      const auto original_hdr_states { cached_hdr_states.empty() ? current_hdr_states : cached_hdr_states };
+      const auto new_hdr_states { win_utils::computeNewHdrStates(config.m_hdr_state, configuring_primary_devices, device_to_configure, additional_devices_to_configure, original_hdr_states) };
+
+      if (!try_change(new_hdr_states, "Changing HDR states to: ", "Failed to apply new configuration, because new HDR states could not be set!")) {
+        // Error already logged
+        return false;
+      }
+
+      // Here we preserve the data from persistence (unless there's none) as in the end that is what we want to go back to.
+      new_state.m_modified.m_original_hdr_states = original_hdr_states;
+      return true;
+    }
+
+    if (might_need_to_restore) {
+      if (!try_change(cached_hdr_states, "Changing HDR states back to: ", "Failed to restore original HDR states!")) {
+        // Error already logged
+        return false;
+      }
+    }
+
+    return true;
+  }
 }  // namespace display_device
diff --git a/src/windows/settingsutils.cpp b/src/windows/settingsutils.cpp
index f881ac2..71a9720 100644
--- a/src/windows/settingsutils.cpp
+++ b/src/windows/settingsutils.cpp
@@ -296,6 +296,39 @@ namespace display_device::win_utils {
     return new_modes;
   }
 
+  HdrStateMap
+  computeNewHdrStates(const std::optional<HdrState> &hdr_state, bool configuring_primary_devices, const std::string &device_to_configure, const std::set<std::string> &additional_devices_to_configure, const HdrStateMap &original_states) {
+    HdrStateMap new_states { original_states };
+
+    if (hdr_state) {
+      const auto try_update_new_state = [&new_states, &hdr_state](const std::string &device_id) {
+        const auto current_state { new_states[device_id] };
+        if (!current_state) {
+          return;
+        }
+
+        new_states[device_id] = *hdr_state;
+      };
+
+      if (configuring_primary_devices) {
+        // No device has been specified, so if they're all are primary devices
+        // we need to update state for all duplicates.
+        const auto devices { joinConfigurableDevices(device_to_configure, additional_devices_to_configure) };
+        for (const auto &device_id : devices) {
+          try_update_new_state(device_id);
+        }
+      }
+      else {
+        // Even if we have duplicate devices, their HDR states may differ
+        // and since the device was specified, let's apply the HDR state
+        // only to the specified device.
+        try_update_new_state(device_to_configure);
+      }
+    }
+
+    return new_states;
+  }
+
   DdGuardFn
   topologyGuardFn(WinDisplayDeviceInterface &win_dd, const ActiveTopology &topology) {
     DD_LOG(debug) << "Got topology in topologyGuardFn:\n"
@@ -344,7 +377,11 @@ namespace display_device::win_utils {
 
   DdGuardFn
   hdrStateGuardFn(WinDisplayDeviceInterface &win_dd, const ActiveTopology &topology) {
-    const auto states = win_dd.getCurrentHdrStates(flattenTopology(topology));
+    return hdrStateGuardFn(win_dd, win_dd.getCurrentHdrStates(flattenTopology(topology)));
+  }
+
+  DdGuardFn
+  hdrStateGuardFn(WinDisplayDeviceInterface &win_dd, const HdrStateMap &states) {
     DD_LOG(debug) << "Got states in hdrStateGuardFn:\n"
                   << toJson(states);
     return [&win_dd, states]() {
diff --git a/tests/unit/windows/test_settingsmanagerapply.cpp b/tests/unit/windows/test_settingsmanagerapply.cpp
index 8123c41..4447053 100644
--- a/tests/unit/windows/test_settingsmanagerapply.cpp
+++ b/tests/unit/windows/test_settingsmanagerapply.cpp
@@ -34,6 +34,11 @@ namespace {
     { "DeviceId2", { { 1920, 1080 }, { 60, 1 } } },
     { "DeviceId3", { { 2560, 1440 }, { 30, 1 } } }
   };
+  const display_device::HdrStateMap DEFAULT_CURRENT_HDR_STATES {
+    { "DeviceId1", display_device::HdrState::Disabled },
+    { "DeviceId2", display_device::HdrState::Disabled },
+    { "DeviceId3", std::nullopt }
+  };
   const display_device::SingleDisplayConfigState DEFAULT_PERSISTENCE_INPUT_BASE { { DEFAULT_CURRENT_TOPOLOGY, { "DeviceId1", "DeviceId2" } } };
 
   // Test fixture(s) for this file
@@ -193,6 +198,30 @@ namespace {
         .RetiresOnSaturation();
     }
 
+    void
+    expectedSetHdrStatesCall(InSequence &sequence /* To ensure that sequence is created outside this scope */, const display_device::HdrStateMap &states, const bool success = true) {
+      EXPECT_CALL(*m_dd_api, setHdrStates(states))
+        .Times(1)
+        .WillOnce(Return(success))
+        .RetiresOnSaturation();
+    }
+
+    void
+    expectedGetCurrentHdrStatesCall(InSequence &sequence /* To ensure that sequence is created outside this scope */, const std::set<std::string> &devices, const display_device::HdrStateMap &states) {
+      EXPECT_CALL(*m_dd_api, getCurrentHdrStates(devices))
+        .Times(1)
+        .WillOnce(Return(states))
+        .RetiresOnSaturation();
+    }
+
+    void
+    expectedSetHdrStatesGuardCall(InSequence &sequence /* To ensure that sequence is created outside this scope */, const display_device::HdrStateMap &states) {
+      EXPECT_CALL(*m_dd_api, setHdrStates(states))
+        .Times(1)
+        .WillOnce(Return(true))
+        .RetiresOnSaturation();
+    }
+
     std::shared_ptr<StrictMock<display_device::MockWinDisplayDevice>> m_dd_api { std::make_shared<StrictMock<display_device::MockWinDisplayDevice>>() };
     std::shared_ptr<StrictMock<display_device::MockSettingsPersistence>> m_settings_persistence_api { std::make_shared<StrictMock<display_device::MockSettingsPersistence>>() };
     std::shared_ptr<StrictMock<display_device::MockAudioContext>> m_audio_context_api { std::make_shared<StrictMock<display_device::MockAudioContext>>() };
@@ -947,6 +976,237 @@ TEST_F_S_MOCKED(PrepareDisplayModes, DisplayModesRestoreSkipped, PersistenceFail
   EXPECT_EQ(getImpl().applySettings({ .m_device_id = "DeviceId1" }), display_device::SettingsManager::ApplyResult::PersistenceSaveFailed);
 }
 
+TEST_F_S_MOCKED(PrepareHdrStates, FailedToGetHdrStates) {
+  InSequence sequence;
+  expectedDefaultCallsUntilTopologyPrep(sequence);
+  expectedIsCapturedCall(sequence, false);
+  expectedDeviceEnumCall(sequence);
+  expectedIsTopologyTheSameCall(sequence, DEFAULT_CURRENT_TOPOLOGY, DEFAULT_CURRENT_TOPOLOGY);
+
+  expectedGetCurrentHdrStatesCall(sequence, display_device::win_utils::flattenTopology(DEFAULT_CURRENT_TOPOLOGY), {});
+
+  expectedTopologyGuardTopologyCall(sequence);
+  expectedTopologyGuardNewlyCapturedContextCall(sequence, false);
+
+  EXPECT_EQ(getImpl().applySettings({ .m_device_id = "DeviceId1", .m_hdr_state = display_device::HdrState::Enabled }), display_device::SettingsManager::ApplyResult::HdrStatePrepFailed);
+}
+
+TEST_F_S_MOCKED(PrepareHdrStates, FailedToSetHdrStates) {
+  auto new_states { DEFAULT_CURRENT_HDR_STATES };
+  new_states["DeviceId1"] = display_device::HdrState::Enabled;
+
+  InSequence sequence;
+  expectedDefaultCallsUntilTopologyPrep(sequence);
+  expectedIsCapturedCall(sequence, false);
+  expectedDeviceEnumCall(sequence);
+  expectedIsTopologyTheSameCall(sequence, DEFAULT_CURRENT_TOPOLOGY, DEFAULT_CURRENT_TOPOLOGY);
+
+  expectedGetCurrentHdrStatesCall(sequence, display_device::win_utils::flattenTopology(DEFAULT_CURRENT_TOPOLOGY), DEFAULT_CURRENT_HDR_STATES);
+  expectedSetHdrStatesCall(sequence, new_states, false);
+
+  expectedTopologyGuardTopologyCall(sequence);
+  expectedTopologyGuardNewlyCapturedContextCall(sequence, false);
+
+  EXPECT_EQ(getImpl().applySettings({ .m_device_id = "DeviceId1", .m_hdr_state = display_device::HdrState::Enabled }), display_device::SettingsManager::ApplyResult::HdrStatePrepFailed);
+}
+
+TEST_F_S_MOCKED(PrepareHdrStates, HdrStatesSet) {
+  auto new_states { DEFAULT_CURRENT_HDR_STATES };
+  new_states["DeviceId1"] = display_device::HdrState::Enabled;
+
+  auto persistence_input { DEFAULT_PERSISTENCE_INPUT_BASE };
+  persistence_input.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+  persistence_input.m_modified.m_original_hdr_states = DEFAULT_CURRENT_HDR_STATES;
+
+  InSequence sequence;
+  expectedDefaultCallsUntilTopologyPrep(sequence);
+  expectedIsCapturedCall(sequence, false);
+  expectedDeviceEnumCall(sequence);
+  expectedIsTopologyTheSameCall(sequence, DEFAULT_CURRENT_TOPOLOGY, DEFAULT_CURRENT_TOPOLOGY);
+
+  expectedGetCurrentHdrStatesCall(sequence, display_device::win_utils::flattenTopology(DEFAULT_CURRENT_TOPOLOGY), DEFAULT_CURRENT_HDR_STATES);
+  expectedSetHdrStatesCall(sequence, new_states);
+  expectedPersistenceCall(sequence, persistence_input);
+
+  EXPECT_EQ(getImpl().applySettings({ .m_device_id = "DeviceId1", .m_hdr_state = display_device::HdrState::Enabled }), display_device::SettingsManager::ApplyResult::Ok);
+}
+
+TEST_F_S_MOCKED(PrepareHdrStates, HdrStatesSet, PrimaryDeviceSpecified) {
+  auto new_states { DEFAULT_CURRENT_HDR_STATES };
+  new_states["DeviceId1"] = display_device::HdrState::Enabled;
+  new_states["DeviceId2"] = display_device::HdrState::Enabled;
+
+  auto persistence_input { DEFAULT_PERSISTENCE_INPUT_BASE };
+  persistence_input.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+  persistence_input.m_modified.m_original_hdr_states = DEFAULT_CURRENT_HDR_STATES;
+
+  InSequence sequence;
+  expectedDefaultCallsUntilTopologyPrep(sequence);
+  expectedIsCapturedCall(sequence, false);
+  expectedDeviceEnumCall(sequence);
+  expectedIsTopologyTheSameCall(sequence, DEFAULT_CURRENT_TOPOLOGY, DEFAULT_CURRENT_TOPOLOGY);
+
+  expectedGetCurrentHdrStatesCall(sequence, display_device::win_utils::flattenTopology(DEFAULT_CURRENT_TOPOLOGY), DEFAULT_CURRENT_HDR_STATES);
+  expectedSetHdrStatesCall(sequence, new_states);
+  expectedPersistenceCall(sequence, persistence_input);
+
+  EXPECT_EQ(getImpl().applySettings({ .m_hdr_state = display_device::HdrState::Enabled }), display_device::SettingsManager::ApplyResult::Ok);
+}
+
+TEST_F_S_MOCKED(PrepareHdrStates, HdrStatesSet, CachedModesReused) {
+  auto new_states { DEFAULT_CURRENT_HDR_STATES };
+  new_states["DeviceId1"] = display_device::HdrState::Enabled;
+
+  auto initial_state { DEFAULT_PERSISTENCE_INPUT_BASE };
+  initial_state.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+  initial_state.m_modified.m_original_hdr_states = DEFAULT_CURRENT_HDR_STATES;
+
+  InSequence sequence;
+  expectedDefaultCallsUntilTopologyPrep(sequence, DEFAULT_CURRENT_TOPOLOGY, initial_state);
+  expectedIsCapturedCall(sequence, false);
+  expectedDeviceEnumCall(sequence);
+  expectedIsTopologyTheSameCall(sequence, DEFAULT_CURRENT_TOPOLOGY, DEFAULT_CURRENT_TOPOLOGY);
+
+  expectedGetCurrentHdrStatesCall(sequence, display_device::win_utils::flattenTopology(DEFAULT_CURRENT_TOPOLOGY), DEFAULT_CURRENT_HDR_STATES);
+  expectedSetHdrStatesCall(sequence, new_states);
+
+  EXPECT_EQ(getImpl().applySettings({ .m_device_id = "DeviceId1", .m_hdr_state = display_device::HdrState::Enabled }), display_device::SettingsManager::ApplyResult::Ok);
+}
+
+TEST_F_S_MOCKED(PrepareHdrStates, HdrStatesSet, GuardInvoked) {
+  auto new_states { DEFAULT_CURRENT_HDR_STATES };
+  new_states["DeviceId1"] = display_device::HdrState::Enabled;
+
+  auto persistence_input { DEFAULT_PERSISTENCE_INPUT_BASE };
+  persistence_input.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+  persistence_input.m_modified.m_original_hdr_states = DEFAULT_CURRENT_HDR_STATES;
+
+  InSequence sequence;
+  expectedDefaultCallsUntilTopologyPrep(sequence);
+  expectedIsCapturedCall(sequence, false);
+  expectedDeviceEnumCall(sequence);
+  expectedIsTopologyTheSameCall(sequence, DEFAULT_CURRENT_TOPOLOGY, DEFAULT_CURRENT_TOPOLOGY);
+
+  expectedGetCurrentHdrStatesCall(sequence, display_device::win_utils::flattenTopology(DEFAULT_CURRENT_TOPOLOGY), DEFAULT_CURRENT_HDR_STATES);
+  expectedSetHdrStatesCall(sequence, new_states);
+  expectedPersistenceCall(sequence, persistence_input, false);
+
+  expectedSetHdrStatesGuardCall(sequence, DEFAULT_CURRENT_HDR_STATES);
+  expectedTopologyGuardTopologyCall(sequence);
+  expectedTopologyGuardNewlyCapturedContextCall(sequence, false);
+
+  EXPECT_EQ(getImpl().applySettings({ .m_device_id = "DeviceId1", .m_hdr_state = display_device::HdrState::Enabled }), display_device::SettingsManager::ApplyResult::PersistenceSaveFailed);
+}
+
+TEST_F_S_MOCKED(PrepareHdrStates, HdrStatesSetSkipped) {
+  auto persistence_input { DEFAULT_PERSISTENCE_INPUT_BASE };
+  persistence_input.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+  persistence_input.m_modified.m_original_hdr_states = DEFAULT_CURRENT_HDR_STATES;
+
+  InSequence sequence;
+  expectedDefaultCallsUntilTopologyPrep(sequence);
+  expectedIsCapturedCall(sequence, false);
+  expectedDeviceEnumCall(sequence);
+  expectedIsTopologyTheSameCall(sequence, DEFAULT_CURRENT_TOPOLOGY, DEFAULT_CURRENT_TOPOLOGY);
+
+  expectedGetCurrentHdrStatesCall(sequence, display_device::win_utils::flattenTopology(DEFAULT_CURRENT_TOPOLOGY), DEFAULT_CURRENT_HDR_STATES);
+  expectedPersistenceCall(sequence, persistence_input);
+
+  EXPECT_EQ(getImpl().applySettings({ .m_device_id = "DeviceId3", .m_hdr_state = display_device::HdrState::Enabled }), display_device::SettingsManager::ApplyResult::Ok);
+}
+
+TEST_F_S_MOCKED(PrepareHdrStates, FailedToRestoreHdrStates) {
+  auto initial_state { DEFAULT_PERSISTENCE_INPUT_BASE };
+  initial_state.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+  initial_state.m_modified.m_original_hdr_states = DEFAULT_CURRENT_HDR_STATES;
+  initial_state.m_modified.m_original_hdr_states["DeviceId1"] = display_device::HdrState::Enabled;
+
+  InSequence sequence;
+  expectedDefaultCallsUntilTopologyPrep(sequence, DEFAULT_CURRENT_TOPOLOGY, initial_state);
+  expectedIsCapturedCall(sequence, false);
+  expectedDeviceEnumCall(sequence);
+  expectedIsTopologyTheSameCall(sequence, DEFAULT_CURRENT_TOPOLOGY, DEFAULT_CURRENT_TOPOLOGY);
+
+  expectedGetCurrentHdrStatesCall(sequence, display_device::win_utils::flattenTopology(DEFAULT_CURRENT_TOPOLOGY), DEFAULT_CURRENT_HDR_STATES);
+  expectedSetHdrStatesCall(sequence, initial_state.m_modified.m_original_hdr_states, false);
+
+  expectedTopologyGuardTopologyCall(sequence);
+  expectedTopologyGuardNewlyCapturedContextCall(sequence, false);
+
+  EXPECT_EQ(getImpl().applySettings({ .m_device_id = "DeviceId1" }), display_device::SettingsManager::ApplyResult::HdrStatePrepFailed);
+}
+
+TEST_F_S_MOCKED(PrepareHdrStates, HdrStatesRestored) {
+  auto initial_state { DEFAULT_PERSISTENCE_INPUT_BASE };
+  initial_state.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+  initial_state.m_modified.m_original_hdr_states = DEFAULT_CURRENT_HDR_STATES;
+  initial_state.m_modified.m_original_hdr_states["DeviceId1"] = display_device::HdrState::Enabled;
+
+  auto persistence_input { DEFAULT_PERSISTENCE_INPUT_BASE };
+  persistence_input.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+
+  InSequence sequence;
+  expectedDefaultCallsUntilTopologyPrep(sequence, DEFAULT_CURRENT_TOPOLOGY, initial_state);
+  expectedIsCapturedCall(sequence, false);
+  expectedDeviceEnumCall(sequence);
+  expectedIsTopologyTheSameCall(sequence, DEFAULT_CURRENT_TOPOLOGY, DEFAULT_CURRENT_TOPOLOGY);
+
+  expectedGetCurrentHdrStatesCall(sequence, display_device::win_utils::flattenTopology(DEFAULT_CURRENT_TOPOLOGY), DEFAULT_CURRENT_HDR_STATES);
+  expectedSetHdrStatesCall(sequence, initial_state.m_modified.m_original_hdr_states);
+  expectedPersistenceCall(sequence, persistence_input);
+
+  EXPECT_EQ(getImpl().applySettings({ .m_device_id = "DeviceId1" }), display_device::SettingsManager::ApplyResult::Ok);
+}
+
+TEST_F_S_MOCKED(PrepareHdrStates, HdrStatesRestored, PersistenceFailed) {
+  auto initial_state { DEFAULT_PERSISTENCE_INPUT_BASE };
+  initial_state.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+  initial_state.m_modified.m_original_hdr_states = DEFAULT_CURRENT_HDR_STATES;
+  initial_state.m_modified.m_original_hdr_states["DeviceId1"] = display_device::HdrState::Enabled;
+
+  auto persistence_input { DEFAULT_PERSISTENCE_INPUT_BASE };
+  persistence_input.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+
+  InSequence sequence;
+  expectedDefaultCallsUntilTopologyPrep(sequence, DEFAULT_CURRENT_TOPOLOGY, initial_state);
+  expectedIsCapturedCall(sequence, false);
+  expectedDeviceEnumCall(sequence);
+  expectedIsTopologyTheSameCall(sequence, DEFAULT_CURRENT_TOPOLOGY, DEFAULT_CURRENT_TOPOLOGY);
+
+  expectedGetCurrentHdrStatesCall(sequence, display_device::win_utils::flattenTopology(DEFAULT_CURRENT_TOPOLOGY), DEFAULT_CURRENT_HDR_STATES);
+  expectedSetHdrStatesCall(sequence, initial_state.m_modified.m_original_hdr_states);
+  expectedPersistenceCall(sequence, persistence_input, false);
+
+  expectedSetHdrStatesGuardCall(sequence, DEFAULT_CURRENT_HDR_STATES);
+  expectedTopologyGuardTopologyCall(sequence);
+  expectedTopologyGuardNewlyCapturedContextCall(sequence, false);
+
+  EXPECT_EQ(getImpl().applySettings({ .m_device_id = "DeviceId1" }), display_device::SettingsManager::ApplyResult::PersistenceSaveFailed);
+}
+
+TEST_F_S_MOCKED(PrepareHdrStates, HdrStatesRestoreSkipped, PersistenceFailed) {
+  auto initial_state { DEFAULT_PERSISTENCE_INPUT_BASE };
+  initial_state.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+  initial_state.m_modified.m_original_hdr_states = DEFAULT_CURRENT_HDR_STATES;
+
+  auto persistence_input { DEFAULT_PERSISTENCE_INPUT_BASE };
+  persistence_input.m_modified.m_topology = DEFAULT_CURRENT_TOPOLOGY;
+
+  InSequence sequence;
+  expectedDefaultCallsUntilTopologyPrep(sequence, DEFAULT_CURRENT_TOPOLOGY, initial_state);
+  expectedIsCapturedCall(sequence, false);
+  expectedDeviceEnumCall(sequence);
+  expectedIsTopologyTheSameCall(sequence, DEFAULT_CURRENT_TOPOLOGY, DEFAULT_CURRENT_TOPOLOGY);
+
+  expectedGetCurrentHdrStatesCall(sequence, display_device::win_utils::flattenTopology(DEFAULT_CURRENT_TOPOLOGY), DEFAULT_CURRENT_HDR_STATES);
+  expectedPersistenceCall(sequence, persistence_input, false);
+
+  expectedTopologyGuardTopologyCall(sequence);
+  expectedTopologyGuardNewlyCapturedContextCall(sequence, false);
+
+  EXPECT_EQ(getImpl().applySettings({ .m_device_id = "DeviceId1" }), display_device::SettingsManager::ApplyResult::PersistenceSaveFailed);
+}
+
 TEST_F_S_MOCKED(AudioContextDelayedRelease) {
   using DevicePrep = display_device::SingleDisplayConfiguration::DevicePreparation;
   auto persistence_input { *ut_consts::SDCS_NO_MODIFICATIONS };
diff --git a/tests/unit/windows/test_settingsutils.cpp b/tests/unit/windows/test_settingsutils.cpp
index dd868d0..fa19705 100644
--- a/tests/unit/windows/test_settingsutils.cpp
+++ b/tests/unit/windows/test_settingsutils.cpp
@@ -26,6 +26,11 @@ namespace {
     { "DeviceId2", { { 1920, 1080 }, { 60, 1 } } },
     { "DeviceId3", { { 2560, 1440 }, { 30, 1 } } }
   };
+  const display_device::HdrStateMap DEFAULT_CURRENT_HDR_STATES {
+    { "DeviceId1", { display_device::HdrState::Disabled } },
+    { "DeviceId2", { display_device::HdrState::Disabled } },
+    { "DeviceId3", std::nullopt }
+  };
 }  // namespace
 
 TEST_F_S_MOCKED(FlattenTopology) {
@@ -101,6 +106,27 @@ TEST_F_S_MOCKED(ComputeNewDisplayModes, NonPrimaryDevices) {
   EXPECT_EQ(display_device::win_utils::computeNewDisplayModes({ { 1920, 1080 } }, { 120. }, false, "DeviceId1", { "DeviceId2" }, DEFAULT_CURRENT_MODES), expected_modes);
 }
 
+TEST_F_S_MOCKED(ComputeNewHdrStates, PrimaryDevices) {
+  auto expected_states { DEFAULT_CURRENT_HDR_STATES };
+  expected_states["DeviceId1"] = display_device::HdrState::Enabled;
+  expected_states["DeviceId2"] = display_device::HdrState::Enabled;
+
+  EXPECT_EQ(display_device::win_utils::computeNewHdrStates(display_device::HdrState::Enabled, true, "DeviceId1", { "DeviceId2", "DeviceId3" }, DEFAULT_CURRENT_HDR_STATES), expected_states);
+}
+
+TEST_F_S_MOCKED(ComputeNewHdrStates, NonPrimaryDevices) {
+  auto expected_states { DEFAULT_CURRENT_HDR_STATES };
+  expected_states["DeviceId1"] = display_device::HdrState::Enabled;
+
+  EXPECT_EQ(display_device::win_utils::computeNewHdrStates(display_device::HdrState::Enabled, false, "DeviceId1", { "DeviceId2", "DeviceId3" }, DEFAULT_CURRENT_HDR_STATES), expected_states);
+  EXPECT_EQ(display_device::win_utils::computeNewHdrStates(std::nullopt, false, "DeviceId1", { "DeviceId2", "DeviceId3" }, DEFAULT_CURRENT_HDR_STATES), DEFAULT_CURRENT_HDR_STATES);
+}
+
+TEST_F_S_MOCKED(ComputeNewHdrStates, NoStateProvided) {
+  EXPECT_EQ(display_device::win_utils::computeNewHdrStates(std::nullopt, true, "DeviceId1", { "DeviceId2", "DeviceId3" }, DEFAULT_CURRENT_HDR_STATES), DEFAULT_CURRENT_HDR_STATES);
+  EXPECT_EQ(display_device::win_utils::computeNewHdrStates(std::nullopt, false, "DeviceId1", { "DeviceId2", "DeviceId3" }, DEFAULT_CURRENT_HDR_STATES), DEFAULT_CURRENT_HDR_STATES);
+}
+
 TEST_F_S_MOCKED(StripInitialState, NoStripIsPerformed) {
   const display_device::SingleDisplayConfigState::Initial initial_state { DEFAULT_INITIAL_TOPOLOGY, { "DeviceId1", "DeviceId2" } };
   const display_device::EnumeratedDeviceList devices {