"""The Windows Registry object interfaces."""
import abc
from dfwinreg import definitions
from dfwinreg import key_paths
[docs]
class WinRegistryFile:
"""Windows Registry file interface."""
[docs]
def __init__(self, ascii_codepage="cp1252", key_path_prefix=""):
"""Initializes a Windows Registry file.
Args:
ascii_codepage (Optional[str]): ASCII string codepage.
key_path_prefix (Optional[str]): Windows Registry key path prefix.
"""
super().__init__()
self._ascii_codepage = ascii_codepage
self._key_path_prefix = key_path_prefix
self._key_path_prefix_length = len(key_path_prefix)
self._key_path_prefix_upper = key_path_prefix.upper()
[docs]
@abc.abstractmethod
def Close(self):
"""Closes the Windows Registry file."""
[docs]
@abc.abstractmethod
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.
"""
[docs]
@abc.abstractmethod
def GetRootKey(self):
"""Retrieves the root key.
Returns:
WinRegistryKey: Windows Registry root key or None if not available.
"""
[docs]
@abc.abstractmethod
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.
"""
[docs]
def RecurseKeys(self):
"""Recurses the Windows Registry keys starting with the root key.
Yields:
WinRegistryKey: Windows Registry key.
"""
root_key = self.GetRootKey()
if root_key:
yield from root_key.RecurseKeys()
[docs]
def SetKeyPathPrefix(self, key_path_prefix):
"""Sets the Window Registry key path prefix.
Args:
key_path_prefix (str): Windows Registry key path prefix.
"""
self._key_path_prefix = key_path_prefix
self._key_path_prefix_length = len(key_path_prefix)
self._key_path_prefix_upper = key_path_prefix.upper()
[docs]
class WinRegistryFileReader:
"""Windows Registry file reader interface."""
[docs]
@abc.abstractmethod
def Open(self, path, ascii_codepage="cp1252"):
"""Opens a Windows Registry file specified by the path.
Args:
path (str): path of the Windows Registry file. The path is a Windows
path relative to the root of the file system that contains the
specific Windows Registry file, for example:
C:\\Windows\\System32\\config\\SYSTEM
ascii_codepage (Optional[str]): ASCII string codepage.
Returns:
WinRegistryFile: Windows Registry file or None.
"""
[docs]
class WinRegistryKey:
"""Windows Registry key interface."""
[docs]
def __init__(self, key_helper=None, key_path_prefix="", relative_key_path=""):
"""Initializes a Windows Registry key.
Args:
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().__init__()
self._key_helper = key_helper
self._key_path_prefix = key_path_prefix
self._relative_key_path = relative_key_path
@property
@abc.abstractmethod
def class_name(self):
"""str: class name of the key or None if not available."""
@property
@abc.abstractmethod
def last_written_time(self):
"""dfdatetime.DateTimeValues: last written time or None."""
@property
@abc.abstractmethod
def name(self):
"""str: name of the key."""
@property
@abc.abstractmethod
def number_of_subkeys(self):
"""int: number of subkeys within the key."""
@property
@abc.abstractmethod
def number_of_values(self):
"""int: number of values within the key."""
@property
@abc.abstractmethod
def offset(self):
"""int: offset of the key within the Windows Registry file or None."""
@property
def path(self):
"""str: Windows Registry key path."""
return key_paths.JoinKeyPath([self._key_path_prefix, self._relative_key_path])
[docs]
@abc.abstractmethod
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.
"""
[docs]
@abc.abstractmethod
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.
"""
[docs]
@abc.abstractmethod
def GetSubkeyByPath(self, key_path):
"""Retrieves a subkey by a path.
Args:
key_path (str): relative key path of the subkey.
Returns:
WinRegistryKey: Windows Registry subkey or None if not found.
"""
[docs]
@abc.abstractmethod
def GetSubkeys(self):
"""Retrieves all subkeys within the key.
Yields:
WinRegistryKey: Windows Registry subkey.
"""
[docs]
@abc.abstractmethod
def GetValueByName(self, name):
"""Retrieves a value by name.
Args:
name (str): name of the value or an empty string for the default value.
Returns:
WinRegistryValue: Windows Registry value or None if not found.
"""
[docs]
@abc.abstractmethod
def GetValues(self):
"""Retrieves all values within the key.
Yields:
WinRegistryValue: Windows Registry value.
"""
[docs]
def RecurseKeys(self):
"""Recurses the subkeys starting with the key.
Yields:
WinRegistryKey: Windows Registry key.
"""
yield self
for subkey in self.GetSubkeys():
yield from subkey.RecurseKeys()
[docs]
class WinRegistryKeyHelper:
"""Windows Registry key helper."""
[docs]
class WinRegistryValue:
"""Windows Registry value interface."""
_DATA_TYPE_STRINGS = {
0: "REG_NONE",
1: "REG_SZ",
2: "REG_EXPAND_SZ",
3: "REG_BINARY",
4: "REG_DWORD_LE",
5: "REG_DWORD_BE",
6: "REG_LINK",
7: "REG_MULTI_SZ",
8: "REG_RESOURCE_LIST",
9: "REG_FULL_RESOURCE_DESCRIPTOR",
10: "REG_RESOURCE_REQUIREMENTS_LIST",
11: "REG_QWORD",
}
_STRING_VALUE_TYPES = frozenset(
[definitions.REG_SZ, definitions.REG_EXPAND_SZ, definitions.REG_LINK]
)
@property
@abc.abstractmethod
def data(self):
"""bytes: value data."""
@property
@abc.abstractmethod
def data_type(self):
"""int: data type."""
@property
def data_type_string(self):
"""str: string representation of the data type."""
return self._DATA_TYPE_STRINGS.get(self.data_type, "UNKNOWN")
@property
@abc.abstractmethod
def name(self):
"""str: name of the value."""
@property
@abc.abstractmethod
def offset(self):
"""int: offset of the value within the Windows Registry file."""
[docs]
def DataIsBinaryData(self):
"""Determines, based on the data type, if the data is binary data.
The data types considered binary data are: REG_BINARY.
Returns:
bool: True if the data is a binary data, False otherwise.
"""
return self.data_type == definitions.REG_BINARY
[docs]
def DataIsInteger(self):
"""Determines, based on the data type, if the data is an integer.
The data types considered strings are: REG_DWORD (REG_DWORD_LITTLE_ENDIAN),
REG_DWORD_BIG_ENDIAN and REG_QWORD.
Returns:
bool: True if the data is an integer, False otherwise.
"""
return self.data_type in (
definitions.REG_DWORD,
definitions.REG_DWORD_BIG_ENDIAN,
definitions.REG_QWORD,
)
[docs]
def DataIsMultiString(self):
"""Determines, based on the data type, if the data is a multi string.
The data types considered multi strings are: REG_MULTI_SZ.
Returns:
bool: True if the data is multi string, False otherwise.
"""
return self.data_type == definitions.REG_MULTI_SZ
[docs]
def DataIsString(self):
"""Determines, based on the data type, if the data is a string.
The data types considered strings are: REG_SZ and REG_EXPAND_SZ.
Returns:
bool: True if the data is a string, False otherwise.
"""
return self.data_type in (definitions.REG_SZ, definitions.REG_EXPAND_SZ)
[docs]
@abc.abstractmethod
def GetDataAsObject(self):
"""Retrieves the data as an object.
Returns:
object: data as a Python type.
"""