Source code for winregrc.shellfolders

# -*- coding: utf-8 -*-
"""Windows Shell folder collector."""

from winregrc import interface


[docs] class WindowsShellFolder(object): """Windows Shell folder. Attributes: alternate_names (list[str]): alternate names. class_name (str): class name (CLSID). identifier (str): identifier (GUID). name (str): name. localized_string (str): localized string of the name. """
[docs] def __init__(self, identifier=None, localized_string=None): """Initializes a Windows Shell folder. Args: identifier (Optional[str]): identifier (GUID). localized_string (Optional[str]): localized string of the name. """ super(WindowsShellFolder, self).__init__() self.alternate_names = [] self.class_name = None self.identifier = identifier self.localized_string = localized_string self.name = None
[docs] class ShellFoldersCollector(interface.WindowsRegistryKeyCollector): """Windows Shell folder collector.""" _CLASS_IDENTIFIERS_KEY_PATH = 'HKEY_LOCAL_MACHINE\\Software\\Classes\\CLSID'
[docs] def __init__(self, debug=False): """Initializes a Windows Registry key and value collector. Args: debug (Optional[bool]): True if debug information should be printed. """ super(ShellFoldersCollector, self).__init__(debug=debug) self._ascii_codepage = 'cp1252'
def _CollectShellFolders(self, class_identifiers_key): """Collects Windows Shell folders. Args: class_identifiers_key (dfwinreg.WinRegistry): CLSID Windows Registry. Yields: ShellFolder: a Windows Shell folder. """ for class_identifier_key in class_identifiers_key.GetSubkeys(): shell_folder_identifier = class_identifier_key.name.lower() shell_folder_key = class_identifier_key.GetSubkeyByName('ShellFolder') if shell_folder_key: name = self._GetShellFolderName(class_identifier_key) value = class_identifier_key.GetValueByName('LocalizedString') if value: # The value data type does not have to be a string therefore try to # decode the data as an UTF-16 little-endian string and strip # the trailing end-of-string character localized_string = value.data.decode('utf-16-le').rstrip('\x00') else: localized_string = None shell_folder = WindowsShellFolder( identifier=shell_folder_identifier, localized_string=localized_string) if name and name.startswith('CLSID_'): shell_folder.class_name = name else: shell_folder.name = name yield shell_folder def _GetShellFolderName(self, class_identifier_key): """Retrieves the shell folder name. Args: class_identifier_key (dfwinreg.RegistryKey): class identifier Windows Registry key. Returns: str: shell folder name or None if not available. """ value = class_identifier_key.GetValueByName('') if not value or not value.data: return None # First try to decode the value data as an UTF-16 little-endian string with # end-of-string character try: return value.data.decode('utf-16-le').rstrip('\x00') except UnicodeDecodeError: pass # Next try to decode the value data as an ASCII string with a specific # codepage and end-of-string character. try: return value.data.decode(self._ascii_codepage).rstrip('\x00') except UnicodeDecodeError: pass return None
[docs] def Collect(self, registry): """Collects Windows Shell folders. Args: registry (dfwinreg.WinRegistry): Windows Registry. Yields: WindowsShellFolder: a Windows Shell folder. """ # TODO: Add support for per-user shell folders class_identifiers_key = registry.GetKeyByPath( self._CLASS_IDENTIFIERS_KEY_PATH) if class_identifiers_key: yield from self._CollectShellFolders(class_identifiers_key)