# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Mobius Forensic Toolkit
# Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2018 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/>.
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
from pymobius.forensics.registry import *
import struct
import binascii
import mobius

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Installed program structure
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
class program (object):
  pass

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief get installed programs from uninstall key
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def get_programs_from_uninstall_key (username, uninstall_key):
  if not uninstall_key:
    return []

  programs = []

  for key in uninstall_key.subkeys:
    p = program ()
    p.username = username
    p.last_modification_time = key.last_modification_time
    p.display_name = get_data_as_string (key.get_data_by_name ('DisplayName')) or key.name
    p.install_location = get_data_as_string (key.get_data_by_name ('InstallLocation'))
    p.publisher = get_data_as_string (key.get_data_by_name ('Publisher'))
    p.comments = get_data_as_string (key.get_data_by_name ('Comments'))
    p.url_info_about = get_data_as_string (key.get_data_by_name ('URLInfoAbout'))
    p.url_update_info = get_data_as_string (key.get_data_by_name ('URLUpdateInfo'))
    p.help_link = get_data_as_string (key.get_data_by_name ('HelpLink'))

    # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    # version
    # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    p.version = get_data_as_string (key.get_data_by_name ('DisplayVersion'))

    if not p.version:
      major = get_data_as_string (key.get_data_by_name ('VersionMajor'))
      minor = get_data_as_string (key.get_data_by_name ('VersionMinor'))
          
      if major:
        p.version = '%s.%s' % (major, minor)
            
      else:
        p.version = ''

    # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    # installdate
    # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    data = key.get_data_by_name ('InstallDate')

    if not data:
      p.install_date = ''

    elif data.size == 4:
      p.install_date = get_data_as_unix_datetime (data)

    else:
      p.install_date = get_data_as_string (data)
        
      if len (p.install_date) == 8:
        p.install_date = p.install_date[:4] + '-' + p.install_date[4:6] + '-' + p.install_date[6:]

    programs.append (p)
    
  return programs

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief get installed programs
# @author Eduardo Aguiar
# @param registry registry object
# @reference Forensic Analysis of the Windows Registry, by Lih Wern Wong, p.8
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def get (registry):
  programs = []
  
  programs += get_programs_from_uninstall_key (None, registry.get_key_by_path ('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall'))
  programs += get_programs_from_uninstall_key (None, registry.get_key_by_path ('HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall'))
   
  for username, key in iter_hkey_users (registry):
    programs += get_programs_from_uninstall_key (username, key.get_key_by_path ('Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall'))
    programs += get_programs_from_uninstall_key (username, key.get_key_by_path ('Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall'))

  return programs
