// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Mobius Forensic Toolkit
// Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024 Eduardo Aguiar
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include "registry_key_impl_pssp.h"
#include "registry_value_impl_container.h"
#include "registry_data_impl_pssp.h"
#include "registry_value.h"
#include <mobius/io/bytearray_io.h>
#include <mobius/decoder/data_decoder.h>

namespace mobius::os::win::registry
{
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief constructor
//! \param key delegated key
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
registry_key_impl_pssp::registry_key_impl_pssp (registry_key key, pssp_data2 data2)
  : key_ (key),
    name_ (key.get_name ()),
    data2_ (data2)
{
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief load subkeys on demand
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
registry_key_impl_pssp::_load_subkeys () const
{
  // return if subkeys are loaded
  if (subkeys_loaded_)
    return;

  // load subkeys
  for (auto subkey : key_)
    {
      auto value = subkey.get_value_by_name ("Display String");

      if (value)
        {
          auto key = registry_key (std::make_shared <registry_key_impl_pssp> (subkey, data2_));
          subkeys_.append (key);
        }
    }

  // set subkeys loaded
  subkeys_loaded_ = true;
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief load values on demand
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
registry_key_impl_pssp::_load_values () const
{
  // return if values are loaded
  if (values_loaded_)
    return;

  // load values from original key
  values_ = key_.get_values ();

  // load values from PSSP keys that have both "Behavior" and "Item Data" values
  for (auto subkey : key_)
    {
      auto v_behavior = subkey.get_value_by_name ("Behavior");
      auto v_itemdata = subkey.get_value_by_name ("Item Data");

      if (v_behavior && v_itemdata)
        {
          // decode "behavior" value
          auto behavior_data = v_behavior.get_data ().get_data ();
          auto reader = mobius::io::new_bytearray_reader (behavior_data);
          auto decoder = mobius::decoder::data_decoder (reader);

          decoder.skip (8);
          auto size = decoder.get_uint32_le ();
          auto key_name = decoder.get_string_by_size (size, "UTF-16LE");
          auto des_key = data2_.get_key (key_name);

          // if cryptographic key has been found, create new value
          if (!des_key.empty ())
            {
              auto itemdata = v_itemdata.get_data ().get_data ();
              registry_data data (std::make_shared <registry_data_impl_pssp> (des_key, itemdata));
              registry_value value (subkey.get_name (), data);
              values_.push_back (value);
            }
        }
    }

  // set values loaded
  values_loaded_ = true;
}

} // namespace mobius::os::win::registry
