# -*- coding: utf-8 -*-
"""Windows 9x/Me Registry (CREG) objects implementation using pycreg."""
from dfdatetime import semantic_time as dfdatetime_semantic_time
import pycreg
from dfwinreg import definitions
from dfwinreg import errors
from dfwinreg import interface
from dfwinreg import key_paths
[docs]
class CREGWinRegistryFile(interface.WinRegistryFile):
"""Implementation of a Windows Registry file using pycreg."""
[docs]
def __init__(self, ascii_codepage='cp1252', key_path_prefix=''):
"""Initializes the Windows Registry file.
Args:
ascii_codepage (Optional[str]): ASCII string codepage.
key_path_prefix (Optional[str]): Windows Registry key path prefix.
"""
super(CREGWinRegistryFile, self).__init__(
ascii_codepage=ascii_codepage, key_path_prefix=key_path_prefix)
self._file_object = None
self._creg_file = pycreg.file()
self._creg_file.set_ascii_codepage(ascii_codepage)
[docs]
def Close(self):
"""Closes the Windows Registry file."""
self._creg_file.close()
self._file_object = None
[docs]
def GetKeyByPath(self, key_path):
"""Retrieves the key for a specific path.
Args:
key_path (str): Windows Registry key path.
Returns:
WinRegistryKey: Windows Registry key or None if not available.
"""
key_path_upper = key_path.upper()
if key_path_upper.startswith(self._key_path_prefix_upper):
relative_key_path = key_path[self._key_path_prefix_length:]
elif key_path.startswith(definitions.KEY_PATH_SEPARATOR):
relative_key_path = key_path
key_path = ''.join([self._key_path_prefix, key_path])
else:
return None
try:
creg_key = self._creg_file.get_key_by_path(relative_key_path)
except IOError:
creg_key = None
if not creg_key:
return None
return CREGWinRegistryKey(
creg_key, key_path_prefix=self._key_path_prefix,
relative_key_path=relative_key_path)
[docs]
def GetRootKey(self):
"""Retrieves the root key.
Returns:
WinRegistryKey: Windows Registry root key or None if not available.
"""
creg_key = self._creg_file.get_root_key()
if not creg_key:
return None
return CREGWinRegistryKey(
creg_key, key_path_prefix=self._key_path_prefix,
relative_key_path='')
[docs]
def Open(self, file_object):
"""Opens the Windows Registry file using a file-like object.
Args:
file_object (file): file-like object.
Returns:
bool: True if successful or False if not.
"""
self._file_object = file_object
self._creg_file.open_file_object(self._file_object)
return True
[docs]
class CREGWinRegistryKey(interface.WinRegistryKey):
"""Implementation of a Windows Registry key using pycreg."""
[docs]
def __init__(
self, pycreg_key, key_helper=None, key_path_prefix='',
relative_key_path=''):
"""Initializes a Windows Registry key.
Args:
pycreg_key (pycreg.key): pycreg key object.
key_helper (Optional[WinRegistryKeyHelper]): Windows Registry key helper.
key_path_prefix (Optional[str]): Windows Registry key path prefix.
relative_key_path (Optional[str]): relative Windows Registry key path.
"""
super(CREGWinRegistryKey, self).__init__(
key_helper=key_helper, key_path_prefix=key_path_prefix,
relative_key_path=relative_key_path)
self._pycreg_key = pycreg_key
@property
def class_name(self):
"""str: class name of the key or None if not available."""
return None
@property
def last_written_time(self):
"""dfdatetime.DateTimeValues: last written time."""
return dfdatetime_semantic_time.SemanticTime('Not set')
@property
def name(self):
"""str: name of the key."""
return self._pycreg_key.name
@property
def number_of_subkeys(self):
"""int: number of subkeys within the key."""
return self._pycreg_key.number_of_sub_keys
@property
def number_of_values(self):
"""int: number of values within the key."""
return self._pycreg_key.number_of_values
@property
def offset(self):
"""int: offset of the key within the Windows Registry file or None."""
return self._pycreg_key.offset
[docs]
def GetSubkeyByIndex(self, index):
"""Retrieves a subkey by index.
Args:
index (int): index of the subkey.
Returns:
WinRegistryKey: Windows Registry subkey.
Raises:
IndexError: if the index is out of bounds.
"""
if index < 0 or index >= self._pycreg_key.number_of_sub_keys:
raise IndexError('Index out of bounds.')
pycreg_key = self._pycreg_key.get_sub_key(index)
relative_key_path = key_paths.JoinKeyPath([
self._relative_key_path, pycreg_key.name])
return CREGWinRegistryKey(
pycreg_key, key_helper=self._key_helper,
key_path_prefix=self._key_path_prefix,
relative_key_path=relative_key_path)
[docs]
def GetSubkeyByName(self, name):
"""Retrieves a subkey by name.
Args:
name (str): name of the subkey.
Returns:
WinRegistryKey: Windows Registry subkey or None if not found.
"""
pycreg_key = self._pycreg_key.get_sub_key_by_name(name)
if not pycreg_key:
return None
relative_key_path = key_paths.JoinKeyPath([
self._relative_key_path, pycreg_key.name])
return CREGWinRegistryKey(
pycreg_key, key_helper=self._key_helper,
key_path_prefix=self._key_path_prefix,
relative_key_path=relative_key_path)
[docs]
def GetSubkeyByPath(self, key_path):
"""Retrieves a subkey by path.
Args:
key_path (str): path of the subkey.
Returns:
WinRegistryKey: Windows Registry subkey or None if not found.
"""
pycreg_key = self._pycreg_key.get_sub_key_by_path(key_path)
if not pycreg_key:
return None
relative_key_path = key_paths.JoinKeyPath([
self._relative_key_path, key_path])
return CREGWinRegistryKey(
pycreg_key, key_helper=self._key_helper,
key_path_prefix=self._key_path_prefix,
relative_key_path=relative_key_path)
[docs]
def GetSubkeys(self):
"""Retrieves all subkeys within the key.
Yields:
WinRegistryKey: Windows Registry subkey.
"""
for pycreg_key in self._pycreg_key.sub_keys:
relative_key_path = key_paths.JoinKeyPath([
self._relative_key_path, pycreg_key.name])
yield CREGWinRegistryKey(
pycreg_key, key_helper=self._key_helper,
key_path_prefix=self._key_path_prefix,
relative_key_path=relative_key_path)
[docs]
def GetValueByName(self, name):
"""Retrieves a value by name.
Value names are not unique and pycreg provides first match for the value.
Args:
name (str): name of the value or an empty string for the default value.
Returns:
WinRegistryValue: Windows Registry value if a corresponding value was
found or None if not.
"""
pycreg_value = self._pycreg_key.get_value_by_name(name)
if not pycreg_value:
return None
return CREGWinRegistryValue(pycreg_value)
[docs]
def GetValues(self):
"""Retrieves all values within the key.
Yields:
WinRegistryValue: Windows Registry value.
"""
for pycreg_value in self._pycreg_key.values:
yield CREGWinRegistryValue(pycreg_value)
[docs]
class CREGWinRegistryValue(interface.WinRegistryValue):
"""Implementation of a Windows Registry value using pycreg."""
# Note that missing-return-doc is broken for pylint 1.7.x
# pylint: disable=missing-return-doc
[docs]
def __init__(self, pycreg_value):
"""Initializes a Windows Registry value.
Args:
pycreg_value (pycreg.value): pycreg value object.
"""
super(CREGWinRegistryValue, self).__init__()
self._pycreg_value = pycreg_value
# Pylint 1.7.x seems to be get confused about properties.
# pylint: disable=missing-return-type-doc
@property
def data(self):
"""bytes: value data as a byte string.
Raises:
WinRegistryValueError: if the value data cannot be read.
"""
try:
return self._pycreg_value.data
except IOError as exception:
raise errors.WinRegistryValueError((
f'Unable to read data from value: {self._pycreg_value.name:s} '
f'with error: {exception!s}'))
@property
def data_type(self):
"""int: data type."""
return self._pycreg_value.type
@property
def name(self):
"""str: name of the value."""
return self._pycreg_value.name
@property
def offset(self):
"""int: offset of the value within the Windows Registry file."""
return self._pycreg_value.offset
[docs]
def GetDataAsObject(self):
"""Retrieves the data as an object.
Returns:
object: data as a Python type.
Raises:
WinRegistryValueError: if the value data cannot be read.
"""
try:
if self._pycreg_value.type in self._STRING_VALUE_TYPES:
value_data = self._pycreg_value.get_data_as_string()
elif self._pycreg_value.type in definitions.INTEGER_VALUE_TYPES:
value_data = self._pycreg_value.get_data_as_integer()
elif self._pycreg_value.type == definitions.REG_MULTI_SZ:
value_data = self._pycreg_value.get_data_as_multi_string()
else:
value_data = self._pycreg_value.data
except (IOError, OverflowError) as exception:
raise errors.WinRegistryValueError((
f'Unable to read data from value: {self._pycreg_value.name:s} '
f'with error: {exception!s}'))
return value_data