[
  {
    "path": ".github/workflows/test_docker.yml",
    "content": "# Run tests on Fedora and Ubuntu Docker images using GIFT COPR and GIFT PPA on commit\nname: test_docker\non: [push]\npermissions: read-all\njobs:\n  test_fedora:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        version: ['43']\n    container:\n      image: registry.fedoraproject.org/fedora:${{ matrix.version }}\n    steps:\n    - uses: actions/checkout@v6\n    - name: Set up container\n      run: |\n        dnf install -y dnf-plugins-core langpacks-en\n    - name: Install dependencies\n      run: |\n        dnf copr -y enable @gift/dev\n        dnf install -y @development-tools libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3 python3-acstore python3-artifacts python3-build python3-devel python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pytsk3 python3-pyyaml python3-setuptools python3-wheel python3-xattr\n    - name: Run tests\n      env:\n        LANG: C.utf8\n      run: |\n        python3 ./run_tests.py\n    - name: Run end-to-end tests\n      run: |\n        if test -f tests/end-to-end.py; then PYTHONPATH=. python3 ./tests/end-to-end.py --debug -c config/end-to-end.ini; fi\n    - name: Build source distribution (sdist)\n      run: |\n        python3 -m build --no-isolation --sdist\n    - name: Build binary distribution (wheel)\n      run: |\n        python3 -m build --no-isolation --wheel\n  test_ubuntu:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        version: ['26.04']\n    container:\n      image: ubuntu:${{ matrix.version }}\n    steps:\n    - uses: actions/checkout@v6\n    - name: Set up container\n      env:\n        DEBIAN_FRONTEND: noninteractive\n      run: |\n        apt-get update -q\n        apt-get install -y libterm-readline-gnu-perl locales software-properties-common\n        locale-gen en_US.UTF-8\n        ln -f -s /usr/share/zoneinfo/UTC /etc/localtime\n    - name: Install dependencies\n      run: |\n        add-apt-repository -y ppa:gift/dev\n        apt-get update -q\n        apt-get install -y build-essential libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3 python3-acstore python3-artifacts python3-build python3-dev python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pip python3-pytsk3 python3-setuptools python3-venv python3-wheel python3-xattr python3-yaml\n    - name: Run tests\n      env:\n        LANG: en_US.UTF-8\n      run: |\n        python3 ./run_tests.py\n    - name: Run end-to-end tests\n      env:\n        LANG: en_US.UTF-8\n      run: |\n        if test -f tests/end-to-end.py; then PYTHONPATH=. python3 ./tests/end-to-end.py --debug -c config/end-to-end.ini; fi\n    - name: Build source distribution (sdist)\n      run: |\n        python3 -m build --no-isolation --sdist\n    - name: Build binary distribution (wheel)\n      run: |\n        python3 -m build --no-isolation --wheel\n"
  },
  {
    "path": ".github/workflows/test_docs.yml",
    "content": "# Run docs tox tests on Ubuntu Docker images using the deadsnakes and GIFT PPAs\nname: test_docs\non:\n  pull_request:\n    branches:\n    - main\n  push:\n    branches:\n    - main\npermissions: read-all\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        python-version: ['3.12']\n    container:\n      image: ubuntu:24.04\n    steps:\n    - uses: actions/checkout@v6\n    - name: Set up container\n      env:\n        DEBIAN_FRONTEND: noninteractive\n      run: |\n        apt-get update -q\n        apt-get install -y libterm-readline-gnu-perl locales software-properties-common\n        locale-gen en_US.UTF-8\n        ln -f -s /usr/share/zoneinfo/UTC /etc/localtime\n    - name: Install dependencies\n      env:\n        DEBIAN_FRONTEND: noninteractive\n      run: |\n        add-apt-repository -y universe\n        add-apt-repository -y ppa:deadsnakes/ppa\n        add-apt-repository -y ppa:gift/dev\n        apt-get update -q\n        apt-get install -y build-essential git libffi-dev pkg-config python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-acstore python3-artifacts python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml tox\n    - name: Run tests\n      env:\n        LANG: en_US.UTF-8\n      run: |\n        tox -e docs\n"
  },
  {
    "path": ".github/workflows/test_macos.yml",
    "content": "# Run tests on Mac OS.\nname: test_macos\non: [push, pull_request]\npermissions: read-all\njobs:\n  test_macos:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        include:\n        - os: macos-26\n          python-version: '3.14'\n          toxenv: 'py314'\n    steps:\n    - uses: actions/checkout@v6\n    - name: Install dependencies\n      run: |\n        brew update -q\n        brew install -q gettext gnu-sed python@${{ matrix.python-version }} tox || true\n        brew link --force gettext\n    - name: Run tests\n      run: |\n        tox -e ${{ matrix.toxenv }}\n"
  },
  {
    "path": ".github/workflows/test_tox.yml",
    "content": "# Run tox tests on Ubuntu Docker images using the deadsnakes and GIFT PPAs\nname: test_tox\non:\n  pull_request:\n    branches:\n    - main\n  push:\n    branches:\n    - main\npermissions: read-all\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        include:\n        - python-version: '3.10'\n          toxenv: 'py310'\n        - python-version: '3.11'\n          toxenv: 'py311'\n        - python-version: '3.12'\n          toxenv: 'py312'\n        - python-version: '3.13'\n          toxenv: 'py313'\n        - python-version: '3.14'\n          toxenv: 'py314'\n    container:\n      image: ubuntu:24.04\n    steps:\n    - uses: actions/checkout@v6\n    - name: Set up container\n      env:\n        DEBIAN_FRONTEND: noninteractive\n      run: |\n        apt-get update -q\n        apt-get install -y libterm-readline-gnu-perl locales software-properties-common\n        locale-gen en_US.UTF-8\n        ln -f -s /usr/share/zoneinfo/UTC /etc/localtime\n    - name: Install dependencies\n      env:\n        DEBIAN_FRONTEND: noninteractive\n      run: |\n        add-apt-repository -y universe\n        add-apt-repository -y ppa:deadsnakes/ppa\n        add-apt-repository -y ppa:gift/dev\n        apt-get update -q\n        apt-get install -y build-essential git libffi-dev pkg-config python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-acstore python3-artifacts python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml tox\n    - name: Run tests\n      env:\n        LANG: en_US.UTF-8\n      run: |\n        tox -e ${{ matrix.toxenv }},wheel\n  coverage:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        python-version: ['3.12']\n    container:\n      image: ubuntu:24.04\n    steps:\n    - uses: actions/checkout@v6\n    - name: Set up container\n      env:\n        DEBIAN_FRONTEND: noninteractive\n      run: |\n        apt-get update -q\n        apt-get install -y libterm-readline-gnu-perl locales software-properties-common\n        locale-gen en_US.UTF-8\n        ln -f -s /usr/share/zoneinfo/UTC /etc/localtime\n    - name: Install dependencies\n      env:\n        DEBIAN_FRONTEND: noninteractive\n      run: |\n        add-apt-repository -y universe\n        add-apt-repository -y ppa:deadsnakes/ppa\n        add-apt-repository -y ppa:gift/dev\n        apt-get update -q\n        apt-get install -y build-essential curl git libffi-dev pkg-config python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-acstore python3-artifacts python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml tox\n    - name: Run tests with coverage\n      env:\n        LANG: en_US.UTF-8\n      run: |\n        tox -e coverage\n    - name: Upload coverage report to Codecov\n      uses: codecov/codecov-action@v6\n      with:\n        token: ${{ secrets.CODECOV_TOKEN }}\n  lint:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        python-version: ['3.12']\n    container:\n      image: ubuntu:24.04\n    steps:\n    - uses: actions/checkout@v6\n    - name: Set up container\n      env:\n        DEBIAN_FRONTEND: noninteractive\n      run: |\n        apt-get update -q\n        apt-get install -y libterm-readline-gnu-perl locales software-properties-common\n        locale-gen en_US.UTF-8\n        ln -f -s /usr/share/zoneinfo/UTC /etc/localtime\n    - name: Install dependencies\n      env:\n        DEBIAN_FRONTEND: noninteractive\n      run: |\n        add-apt-repository -y universe\n        add-apt-repository -y ppa:deadsnakes/ppa\n        add-apt-repository -y ppa:gift/dev\n        apt-get update -q\n        apt-get install -y build-essential git libffi-dev pkg-config python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-acstore python3-artifacts python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml tox\n    - name: Run linter\n      env:\n        LANG: en_US.UTF-8\n      run: |\n        tox -e lint\n"
  },
  {
    "path": ".gitignore",
    "content": "# Files to ignore by git\n\n# Back-up files\n*~\n*.swp\n\n# Generic auto-generated build files\n*.pyc\n*.pyo\n\n# Specific auto-generated build files\n/.tox\n/__pycache__\n/build\n/dist\n/MANIFEST.test_data\n/winregrc.egg-info\n\n"
  },
  {
    "path": ".pylintrc",
    "content": "# Pylint 3.2.x configuration file\n#\n# This file is generated by l2tdevtools update-dependencies.py, any dependency\n# related changes should be made in dependencies.ini.\n[MAIN]\n\n# Analyse import fallback blocks. This can be used to support both Python 2 and\n# 3 compatible code, which means that the block might have code that exists\n# only in one or another interpreter, leading to false positives when analysed.\nanalyse-fallback-blocks=no\n\n# Clear in-memory caches upon conclusion of linting. Useful if running pylint\n# in a server-like mode.\nclear-cache-post-run=no\n\n# Load and enable all available extensions. Use --list-extensions to see a list\n# all available extensions.\n#enable-all-extensions=\n\n# In error mode, messages with a category besides ERROR or FATAL are\n# suppressed, and no reports are done by default. Error mode is compatible with\n# disabling specific errors.\n#errors-only=\n\n# Always return a 0 (non-error) status code, even if lint errors are found.\n# This is primarily useful in continuous integration scripts.\n#exit-zero=\n\n# A comma-separated list of package or module names from where C extensions may\n# be loaded. Extensions are loading into the active Python interpreter and may\n# run arbitrary code.\n# extension-pkg-allow-list=\nextension-pkg-allow-list=pybde,pycaes,pycreg,pyewf,pyfcrypto,pyfsapfs,pyfsext,pyfsfat,pyfshfs,pyfsntfs,pyfsxfs,pyfvde,pyfwnt,pyfwps,pyfwsi,pyhmac,pyluksde,pymodi,pyphdi,pyqcow,pyregf,pysigscan,pysmdev,pysmraw,pytsk3,pyvhdi,pyvmdk,pyvsapm,pyvsgpt,pyvshadow,pyvslvm,xattr\n\n# A comma-separated list of package or module names from where C extensions may\n# be loaded. Extensions are loading into the active Python interpreter and may\n# run arbitrary code. (This is an alternative name to extension-pkg-allow-list\n# for backward compatibility.)\nextension-pkg-whitelist=\n\n# Return non-zero exit code if any of these messages/categories are detected,\n# even if score is above --fail-under value. Syntax same as enable. Messages\n# specified are enabled, while categories only check already-enabled messages.\nfail-on=\n\n# Specify a score threshold under which the program will exit with error.\nfail-under=10\n\n# Interpret the stdin as a python script, whose filename needs to be passed as\n# the module_or_package argument.\n#from-stdin=\n\n# Files or directories to be skipped. They should be base names, not paths.\nignore=CVS\n\n# Add files or directories matching the regular expressions patterns to the\n# ignore-list. The regex matches against paths and can be in Posix or Windows\n# format. Because '\\\\' represents the directory delimiter on Windows systems,\n# it can't be used as an escape character.\nignore-paths=\n\n# Files or directories matching the regular expression patterns are skipped.\n# The regex matches against base names, not paths. The default value ignores\n# Emacs file locks\nignore-patterns=^\\.#\n\n# List of module names for which member attributes should not be checked and\n# will not be imported (useful for modules/projects where namespaces are\n# manipulated during runtime and thus existing member attributes cannot be\n# deduced by static analysis). It supports qualified module names, as well as\n# Unix pattern matching.\nignored-modules=\n\n# Python code to execute, usually for sys.path manipulation such as\n# pygtk.require().\n#init-hook=\n\n# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the\n# number of processors available to use, and will cap the count on Windows to\n# avoid hangs.\njobs=1\n\n# Control the amount of potential inferred values when inferring a single\n# object. This can help the performance when dealing with large functions or\n# complex, nested conditions.\nlimit-inference-results=100\n\n# List of plugins (as comma separated values of python module names) to load,\n# usually to register additional checkers.\n# load-plugins=\nload-plugins=pylint.extensions.docparams\n\n# Pickle collected data for later comparisons.\npersistent=yes\n\n# Resolve imports to .pyi stubs if available. May reduce no-member messages and\n# increase not-an-iterable messages.\nprefer-stubs=no\n\n# Minimum Python version to use for version dependent checks. Will default to\n# the version used to run pylint.\npy-version=3.12\n\n# Discover python modules and packages in the file system subtree.\n# recursive=no\nrecursive=yes\n\n# Add paths to the list of the source roots. Supports globbing patterns. The\n# source root is an absolute path or a path relative to the current working\n# directory used to determine a package namespace for modules located under the\n# source root.\nsource-roots=\n\n# When enabled, pylint would attempt to guess common misconfiguration and emit\n# user-friendly hints instead of false-positive error messages.\nsuggestion-mode=yes\n\n# Allow loading of arbitrary C extensions. Extensions are imported into the\n# active Python interpreter and may run arbitrary code.\nunsafe-load-any-extension=no\n\n# In verbose mode, extra non-checker-related info will be displayed.\n#verbose=\n\n\n[BASIC]\n\n# Naming style matching correct argument names.\nargument-naming-style=snake_case\n\n# Regular expression matching correct argument names. Overrides argument-\n# naming-style. If left empty, argument names will be checked with the set\n# naming style.\n#argument-rgx=\nargument-rgx=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$\n\n# Naming style matching correct attribute names.\nattr-naming-style=snake_case\n\n# Regular expression matching correct attribute names. Overrides attr-naming-\n# style. If left empty, attribute names will be checked with the set naming\n# style.\n#attr-rgx=\nattr-rgx=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$\n\n# Bad variable names which should always be refused, separated by a comma.\nbad-names=foo,\n          bar,\n          baz,\n          toto,\n          tutu,\n          tata\n\n# Bad variable names regexes, separated by a comma. If names match any regex,\n# they will always be refused\nbad-names-rgxs=\n\n# Naming style matching correct class attribute names.\nclass-attribute-naming-style=any\n\n# Regular expression matching correct class attribute names. Overrides class-\n# attribute-naming-style. If left empty, class attribute names will be checked\n# with the set naming style.\n#class-attribute-rgx=\nclass-attribute-rgx=([A-Za-z_][A-Za-z0-9_]*|(__.*__))$\n\n# Naming style matching correct class constant names.\nclass-const-naming-style=UPPER_CASE\n\n# Regular expression matching correct class constant names. Overrides class-\n# const-naming-style. If left empty, class constant names will be checked with\n# the set naming style.\n#class-const-rgx=\n\n# Naming style matching correct class names.\nclass-naming-style=PascalCase\n\n# Regular expression matching correct class names. Overrides class-naming-\n# style. If left empty, class names will be checked with the set naming style.\n#class-rgx=\nclass-rgx=[A-Z_][a-zA-Z0-9]+$\n\n# Naming style matching correct constant names.\nconst-naming-style=UPPER_CASE\n\n# Regular expression matching correct constant names. Overrides const-naming-\n# style. If left empty, constant names will be checked with the set naming\n# style.\n#const-rgx=\nconst-rgx=(([a-zA-Z_][a-zA-Z0-9_]*)|(__.*__))$\n\n# Minimum line length for functions/classes that require docstrings, shorter\n# ones are exempt.\ndocstring-min-length=-1\n\n# Naming style matching correct function names.\nfunction-naming-style=snake_case\n\n# Regular expression matching correct function names. Overrides function-\n# naming-style. If left empty, function names will be checked with the set\n# naming style.\n#function-rgx=\nfunction-rgx=[A-Z_][a-zA-Z0-9_]*$\n\n# Good variable names which should always be accepted, separated by a comma.\ngood-names=i,\n           j,\n           k,\n           ex,\n           Run,\n           _\n\n# Good variable names regexes, separated by a comma. If names match any regex,\n# they will always be accepted\ngood-names-rgxs=\n\n# Include a hint for the correct naming format with invalid-name.\ninclude-naming-hint=no\n\n# Naming style matching correct inline iteration names.\ninlinevar-naming-style=any\n\n# Regular expression matching correct inline iteration names. Overrides\n# inlinevar-naming-style. If left empty, inline iteration names will be checked\n# with the set naming style.\n#inlinevar-rgx=\ninlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$\n\n# Naming style matching correct method names.\nmethod-naming-style=snake_case\n\n# Regular expression matching correct method names. Overrides method-naming-\n# style. If left empty, method names will be checked with the set naming style.\n#method-rgx=\nmethod-rgx=(test|[A-Z_])[a-zA-Z0-9_]*$\n\n# Naming style matching correct module names.\nmodule-naming-style=snake_case\n\n# Regular expression matching correct module names. Overrides module-naming-\n# style. If left empty, module names will be checked with the set naming style.\n#module-rgx=\nmodule-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$\n\n# Colon-delimited sets of names that determine each other's naming style when\n# the name regexes allow several styles.\nname-group=\n\n# Regular expression which should only match function or class names that do\n# not require a docstring.\nno-docstring-rgx=^_\n\n# List of decorators that produce properties, such as abc.abstractproperty. Add\n# to this list to register other decorators that produce valid properties.\n# These decorators are taken in consideration only for invalid-name.\nproperty-classes=abc.abstractproperty\n\n# Regular expression matching correct type alias names. If left empty, type\n# alias names will be checked with the set naming style.\n#typealias-rgx=\n\n# Regular expression matching correct type variable names. If left empty, type\n# variable names will be checked with the set naming style.\n#typevar-rgx=\n\n# Naming style matching correct variable names.\nvariable-naming-style=snake_case\n\n# Regular expression matching correct variable names. Overrides variable-\n# naming-style. If left empty, variable names will be checked with the set\n# naming style.\n#variable-rgx=\nvariable-rgx=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$\n\n\n[CLASSES]\n\n# Warn about protected attribute access inside special methods\ncheck-protected-access-in-special-methods=no\n\n# List of method names used to declare (i.e. assign) instance attributes.\ndefining-attr-methods=__init__,\n                      __new__,\n                      setUp,\n                      asyncSetUp,\n                      __post_init__\n\n# List of member names, which should be excluded from the protected access\n# warning.\nexclude-protected=_asdict,_fields,_replace,_source,_make,os._exit\n\n# List of valid names for the first argument in a class method.\nvalid-classmethod-first-arg=cls\n\n# List of valid names for the first argument in a metaclass class method.\n# valid-metaclass-classmethod-first-arg=mcs\nvalid-metaclass-classmethod-first-arg=cls\n\n\n[DESIGN]\n\n# List of regular expressions of class ancestor names to ignore when counting\n# public methods (see R0903)\nexclude-too-few-public-methods=\n\n# List of qualified class names to ignore when counting class parents (see\n# R0901)\nignored-parents=\n\n# Maximum number of arguments for function / method.\n# max-args=5\nmax-args=10\n\n# Maximum number of attributes for a class (see R0902).\nmax-attributes=7\n\n# Maximum number of boolean expressions in an if statement (see R0916).\nmax-bool-expr=5\n\n# Maximum number of branch for function / method body.\nmax-branches=12\n\n# Maximum number of locals for function / method body.\nmax-locals=15\n\n# Maximum number of parents for a class (see R0901).\nmax-parents=7\n\n# Maximum number of public methods for a class (see R0904).\nmax-public-methods=20\n\n# Maximum number of return / yield for function / method body.\nmax-returns=6\n\n# Maximum number of statements in function / method body.\nmax-statements=50\n\n# Minimum number of public methods for a class (see R0903).\nmin-public-methods=2\n\n\n[EXCEPTIONS]\n\n# Exceptions that will emit a warning when caught.\novergeneral-exceptions=builtins.BaseException,builtins.Exception\n\n\n[FORMAT]\n\n# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.\nexpected-line-ending-format=\n\n# Regexp for a line that is allowed to be longer than the limit.\nignore-long-lines=^\\s*(# )?<?https?://\\S+>?$\n\n# Number of spaces of indent required inside a hanging or continued line.\nindent-after-paren=4\n\n# String used as indentation unit. This is usually \"    \" (4 spaces) or \"\\t\" (1\n# tab).\n# indent-string='    '\nindent-string='  '\n\n# Maximum number of characters on a single line.\n# max-line-length=100\nmax-line-length=80\n\n# Maximum number of lines in a module.\nmax-module-lines=1000\n\n# Allow the body of a class to be on the same line as the declaration if body\n# contains single statement.\nsingle-line-class-stmt=no\n\n# Allow the body of an if to be on the same line as the test if there is no\n# else.\nsingle-line-if-stmt=no\n\n\n[IMPORTS]\n\n# List of modules that can be imported at any level, not just the top level\n# one.\nallow-any-import-level=\n\n# Allow explicit reexports by alias from a package __init__.\nallow-reexport-from-package=no\n\n# Allow wildcard imports from modules that define __all__.\nallow-wildcard-with-all=no\n\n# Deprecated modules which should not be used, separated by a comma.\ndeprecated-modules=\n\n# Output a graph (.gv or any supported image format) of external dependencies\n# to the given file (report RP0402 must not be disabled).\next-import-graph=\n\n# Output a graph (.gv or any supported image format) of all (i.e. internal and\n# external) dependencies to the given file (report RP0402 must not be\n# disabled).\nimport-graph=\n\n# Output a graph (.gv or any supported image format) of internal dependencies\n# to the given file (report RP0402 must not be disabled).\nint-import-graph=\n\n# Force import order to recognize a module as part of the standard\n# compatibility libraries.\nknown-standard-library=\n\n# Force import order to recognize a module as part of a third party library.\nknown-third-party=enchant\n\n# Couples of modules and preferred modules, separated by a comma.\npreferred-modules=\n\n\n[LOGGING]\n\n# The type of string formatting that logging methods do. `old` means using %\n# formatting, `new` is for `{}` formatting.\nlogging-format-style=old\n\n# Logging modules to check that the string format arguments are in logging\n# function parameter format.\nlogging-modules=logging\n\n\n[MESSAGES CONTROL]\n\n# Only show warnings with the listed confidence levels. Leave empty to show\n# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,\n# UNDEFINED.\nconfidence=HIGH,\n           CONTROL_FLOW,\n           INFERENCE,\n           INFERENCE_FAILURE,\n           UNDEFINED\n\n# Disable the message, report, category or checker with the given id(s). You\n# can either give multiple identifiers separated by comma (,) or put this\n# option multiple times (only on the command line, not in the configuration\n# file where it should appear only once). You can also use \"--disable=all\" to\n# disable everything first and then re-enable specific checks. For example, if\n# you want to run only the similarities checker, you can use \"--disable=all\n# --enable=similarities\". If you want to run only the classes checker, but have\n# no Warning level messages displayed, use \"--disable=all --enable=classes\n# --disable=W\".\ndisable=assignment-from-none,\n        bad-inline-option,\n        deprecated-pragma,\n        duplicate-code,\n        file-ignored,\n        fixme,\n        locally-disabled,\n        logging-format-interpolation,\n        logging-fstring-interpolation,\n        missing-param-doc,\n        raise-missing-from,\n        raw-checker-failed,\n        suppressed-message,\n        too-few-public-methods,\n        too-many-ancestors,\n        too-many-boolean-expressions,\n        too-many-branches,\n        too-many-instance-attributes,\n        too-many-lines,\n        too-many-locals,\n        too-many-nested-blocks,\n        too-many-positional-arguments,\n        too-many-public-methods,\n        too-many-return-statements,\n        too-many-statements,\n        unsubscriptable-object,\n        use-implicit-booleaness-not-comparison-to-string,\n        use-implicit-booleaness-not-comparison-to-zero,\n        useless-suppression,\n        use-symbolic-message-instead\n\n# Enable the message, report, category or checker with the given id(s). You can\n# either give multiple identifier separated by comma (,) or put this option\n# multiple time (only on the command line, not in the configuration file where\n# it should appear only once). See also the \"--disable\" option for examples.\n# enable=\nenable=c-extension-no-member\n\n\n[METHOD_ARGS]\n\n# List of qualified names (i.e., library.method) which require a timeout\n# parameter e.g. 'requests.api.get,requests.api.post'\ntimeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request\n\n\n[MISCELLANEOUS]\n\n# List of note tags to take in consideration, separated by a comma.\nnotes=FIXME,\n      XXX,\n      TODO\n\n# Regular expression of note tags to take in consideration.\nnotes-rgx=\n\n\n[REFACTORING]\n\n# Maximum number of nested blocks for function / method body\nmax-nested-blocks=5\n\n# Complete name of functions that never returns. When checking for\n# inconsistent-return-statements if a never returning function is called then\n# it will be considered as an explicit return statement and no message will be\n# printed.\nnever-returning-functions=sys.exit,argparse.parse_error\n\n# Let 'consider-using-join' be raised when the separator to join on would be\n# non-empty (resulting in expected fixes of the type: ``\"- \" + \" -\n# \".join(items)``)\nsuggest-join-with-non-empty-separator=yes\n\n\n[REPORTS]\n\n# Python expression which should return a score less than or equal to 10. You\n# have access to the variables 'fatal', 'error', 'warning', 'refactor',\n# 'convention', and 'info' which contain the number of messages in each\n# category, as well as 'statement' which is the total number of statements\n# analyzed. This score is used by the global evaluation report (RP0004).\nevaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))\n\n# Template used to display messages. This is a python new-style format string\n# used to format the message information. See doc for all details.\nmsg-template=\n\n# Set the output format. Available formats are: text, parseable, colorized,\n# json2 (improved json format), json (old json format) and msvs (visual\n# studio). You can also give a reporter class, e.g.\n# mypackage.mymodule.MyReporterClass.\n#output-format=\n\n# Tells whether to display a full report or only the messages.\nreports=no\n\n# Activate the evaluation score.\n# score=yes\nscore=no\n\n\n[SIMILARITIES]\n\n# Comments are removed from the similarity computation\nignore-comments=yes\n\n# Docstrings are removed from the similarity computation\nignore-docstrings=yes\n\n# Imports are removed from the similarity computation\nignore-imports=yes\n\n# Signatures are removed from the similarity computation\nignore-signatures=yes\n\n# Minimum lines number of a similarity.\nmin-similarity-lines=4\n\n\n[SPELLING]\n\n# Limits count of emitted suggestions for spelling mistakes.\nmax-spelling-suggestions=4\n\n# Spelling dictionary name. Available dictionaries: en_AG (hunspell), en_AU\n# (hunspell), en_BS (hunspell), en_BW (hunspell), en_BZ (hunspell), en_CA\n# (hunspell), en_DK (hunspell), en_GB (hunspell), en_GH (hunspell), en_HK\n# (hunspell), en_IE (hunspell), en_IN (hunspell), en_JM (hunspell), en_MW\n# (hunspell), en_NA (hunspell), en_NG (hunspell), en_NZ (hunspell), en_PH\n# (hunspell), en_SG (hunspell), en_TT (hunspell), en_US (hunspell), en_ZA\n# (hunspell), en_ZM (hunspell), en_ZW (hunspell).\nspelling-dict=\n\n# List of comma separated words that should be considered directives if they\n# appear at the beginning of a comment and should not be checked.\nspelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:\n\n# List of comma separated words that should not be checked.\nspelling-ignore-words=\n\n# A path to a file that contains the private dictionary; one word per line.\nspelling-private-dict-file=\n\n# Tells whether to store unknown words to the private dictionary (see the\n# --spelling-private-dict-file option) instead of raising a message.\nspelling-store-unknown-words=no\n\n\n[STRING]\n\n# This flag controls whether inconsistent-quotes generates a warning when the\n# character used as a quote delimiter is used inconsistently within a module.\ncheck-quote-consistency=no\n\n# This flag controls whether the implicit-str-concat should generate a warning\n# on implicit string concatenation in sequences defined over several lines.\ncheck-str-concat-over-line-jumps=no\n\n\n[TYPECHECK]\n\n# List of decorators that produce context managers, such as\n# contextlib.contextmanager. Add to this list to register other decorators that\n# produce valid context managers.\ncontextmanager-decorators=contextlib.contextmanager\n\n# List of members which are set dynamically and missed by pylint inference\n# system, and so shouldn't trigger E1101 when accessed. Python regular\n# expressions are accepted.\ngenerated-members=\n\n# Tells whether to warn about missing members when the owner of the attribute\n# is inferred to be None.\nignore-none=yes\n\n# This flag controls whether pylint should warn about no-member and similar\n# checks whenever an opaque object is returned when inferring. The inference\n# can return multiple potential results while evaluating a Python object, but\n# some branches might not be evaluated, which results in partial inference. In\n# that case, it might be useful to still emit no-member and other checks for\n# the rest of the inferred objects.\nignore-on-opaque-inference=yes\n\n# List of symbolic message names to ignore for Mixin members.\nignored-checks-for-mixins=no-member,\n                          not-async-context-manager,\n                          not-context-manager,\n                          attribute-defined-outside-init\n\n# List of class names for which member attributes should not be checked (useful\n# for classes with dynamically set attributes). This supports the use of\n# qualified names.\nignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace\n\n# Show a hint with possible names when a member name was not found. The aspect\n# of finding the hint is based on edit distance.\nmissing-member-hint=yes\n\n# The minimum edit distance a name should have in order to be considered a\n# similar match for a missing member name.\nmissing-member-hint-distance=1\n\n# The total number of similar names that should be taken in consideration when\n# showing a hint for a missing member.\nmissing-member-max-choices=1\n\n# Regex pattern to define which classes are considered mixins.\nmixin-class-rgx=.*[Mm]ixin\n\n# List of decorators that change the signature of a decorated function.\nsignature-mutators=\n\n\n[VARIABLES]\n\n# List of additional names supposed to be defined in builtins. Remember that\n# you should avoid defining new builtins when possible.\nadditional-builtins=\n\n# Tells whether unused global variables should be treated as a violation.\nallow-global-unused-variables=yes\n\n# List of names allowed to shadow builtins\nallowed-redefined-builtins=\n\n# List of strings which can identify a callback function by name. A callback\n# name must start or end with one of those strings.\ncallbacks=cb_,\n          _cb\n\n# A regular expression matching the name of dummy variables (i.e. expected to\n# not be used).\ndummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_\n\n# Argument names that match this expression will be ignored.\nignored-argument-names=_.*|^ignored_|^unused_\n\n# Tells whether we should check for unused import in __init__ files.\ninit-import=no\n\n# List of qualified module names which can have objects that can redefine\n# builtins.\nredefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io\n"
  },
  {
    "path": ".readthedocs.yaml",
    "content": "# Read the Docs configuration file for Sphinx projects\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details\n\nversion: 2\n\nbuild:\n  os: ubuntu-24.04\n  tools:\n    python: \"3.12\"\n\nsphinx:\n  configuration: docs/conf.py\n  fail_on_warning: false\n\npython:\n  install:\n  - requirements: docs/requirements.txt\n"
  },
  {
    "path": ".yamllint.yaml",
    "content": "extends: default\n\nrules:\n  line-length: disable\n  indentation:\n    spaces: consistent\n    indent-sequences: false\n    check-multi-line-strings: true\n"
  },
  {
    "path": "ACKNOWLEDGEMENTS",
    "content": "Acknowledgements: winreg-kb\n\nCopyright (c) 2013-2022, Joachim Metz <joachim.metz@gmail.com>\n\nCopied with permission from [the Greendale data set](https://github.com/dfirlabs/greendale-specimens).\n* regf/studentpc8/NTUSER.DAT\n* regf/studentpc8/NTUSER.DAT.LOG\n* regf/studentpc8/SAM\n* regf/studentpc8/SECURITY\n* regf/studentpc8/SOFTWARE\n* regf/studentpc8/SYSTEM\n* regf/studentpc8/UsrClass.dat\n"
  },
  {
    "path": "AUTHORS",
    "content": "# Names should be added to this file with this pattern:\n#\n# For individuals:\n#   Name (email address)\n#\n# For organizations:\n#   Organization (fnmatch pattern)\n#\n# See python fnmatch module documentation for more information.\n\nJoachim Metz (joachim.metz@gmail.com)\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include ACKNOWLEDGEMENTS AUTHORS LICENSE README.md\ninclude dependencies.ini run_tests.py utils/dependencies.py\ninclude utils/check_dependencies.py\nexclude .gitignore\nexclude *.pyc\nrecursive-exclude winregrc *.pyc\n# Do not include the test data otherwise the sdist will be too large for PyPI.\nrecursive-exclude test_data *\n# The test scripts are not required in a binary distribution package they \n# are considered source distribution files and excluded by find_package().\nrecursive-include tests *.py\n"
  },
  {
    "path": "MANIFEST.test_data.in",
    "content": "include ACKNOWLEDGEMENTS AUTHORS LICENSE README.md\ninclude dependencies.ini run_tests.py utils/dependencies.py\ninclude utils/check_dependencies.py\nexclude .gitignore\nexclude *.pyc\nrecursive-exclude winregrc *.pyc\nrecursive-include test_data *\n# The test scripts are not required in a binary distribution package they \n# are considered source distribution files and excluded by find_package().\nrecursive-include tests *.py\n"
  },
  {
    "path": "README.md",
    "content": "winreg-kb is a project to build a Windows Registry Knowledge Base.\n\nwinregrc is a Python module part of winreg-kb to allow reuse of Windows\nRegistry Resources.\n\nFor more information see:\n* Project documentation: https://winreg-kb.readthedocs.io/en/latest\n\n"
  },
  {
    "path": "appveyor.yml",
    "content": "environment:\n  matrix:\n  - DESCRIPTION: \"Run tests on Windows with 32-bit Python 3.14\"\n    MACHINE_TYPE: \"x86\"\n    APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022\n    PYTHON: \"C:\\\\Python314\"\n    PYTHON_VERSION: \"3.14\"\n    L2TBINARIES_TRACK: \"dev\"\n    TARGET: tests\n  - DESCRIPTION: \"Run tests on Windows with 64-bit Python 3.14\"\n    MACHINE_TYPE: \"amd64\"\n    APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022\n    PYTHON: \"C:\\\\Python314-x64\"\n    PYTHON_VERSION: \"3.14\"\n    L2TBINARIES_TRACK: \"dev\"\n    TARGET: tests\n  - DESCRIPTION: \"Build wheel on Windows with 32-bit Python 3.14\"\n    MACHINE_TYPE: \"amd64\"\n    APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022\n    PYTHON: \"C:\\\\Python314-x64\"\n    PYTHON_VERSION: \"3.14\"\n    L2TBINARIES_TRACK: \"dev\"\n    TARGET: wheel\n  - DESCRIPTION: \"Build wheel on Windows with 64-bit Python 3.14\"\n    MACHINE_TYPE: \"amd64\"\n    APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022\n    PYTHON: \"C:\\\\Python314-x64\"\n    PYTHON_VERSION: \"3.14\"\n    L2TBINARIES_TRACK: \"dev\"\n    TARGET: wheel\n\ninstall:\n- cmd: \"%PYTHON%\\\\python.exe -m pip install -U build pip setuptools twine wheel\"\n- ps: .\\config\\appveyor\\install.ps1\n\nbuild_script:\n- cmd: IF [%TARGET%]==[wheel] (\n    \"%PYTHON%\\\\python.exe\" -m build --wheel )\n\ntest_script:\n- cmd: IF [%TARGET%]==[tests] (\n    \"%PYTHON%\\\\python.exe\" run_tests.py &&\n    IF EXIST \"tests\\\\end-to-end.py\" (\n        set PYTHONPATH=. &&\n        \"%PYTHON%\\\\python.exe\" \"tests\\\\end-to-end.py\" --debug -c \"config\\\\end-to-end.ini\" ) )\n\nartifacts:\n- path: dist\\*.whl\n"
  },
  {
    "path": "config/appveyor/install.ps1",
    "content": "# Script to set up tests on AppVeyor Windows.\n\n$Dependencies = \"PyYAML acstore artifacts dfdatetime dfimagetools dfvfs dfwinreg dtfabric libbde libcaes libcreg libewf libfcrypto libfsapfs libfsext libfsfat libfshfs libfsntfs libfsxfs libfvde libfwnt libfwps libfwsi libhmac libluksde libmodi libphdi libqcow libregf libsigscan libsmdev libsmraw libvhdi libvmdk libvsapm libvsgpt libvshadow libvslvm pytsk3 xattr\"\n\nIf ($Dependencies.Length -gt 0)\n{\n\t$Dependencies = ${Dependencies} -split \" \"\n\n\t$Output = Invoke-Expression -Command \"git clone https://github.com/log2timeline/l2tdevtools.git ..\\l2tdevtools 2>&1\" | %{ \"$_\" }\n\tWrite-Host (${Output} | Out-String)\n\n\tIf ($env:APPVEYOR_REPO_BRANCH -eq \"main\")\n\t{\n\t\t$Track = \"stable\"\n\t}\n\tElse\n\t{\n\t\t$Track = $env:APPVEYOR_REPO_BRANCH\n\t}\n\tNew-Item -ItemType \"directory\" -Name \"dependencies\"\n\n\t$env:PYTHONPATH = \"..\\l2tdevtools\"\n\n\t$Output = Invoke-Expression -Command \"& '${env:PYTHON}\\python.exe' ..\\l2tdevtools\\tools\\update.py --download-directory dependencies --machine-type ${env:MACHINE_TYPE} --track ${env:L2TBINARIES_TRACK} ${Dependencies} 2>&1\" | %{ \"$_\" }\n\tWrite-Host (${Output} | Out-String)\n}\n\n"
  },
  {
    "path": "config/dpkg/changelog",
    "content": "winreg-kb (20260413-1) unstable; urgency=low\n\n  * Auto-generated\n\n -- Joachim Metz <joachim.metz@gmail.com>  Mon, 13 Apr 2026 06:58:45 +0200\n"
  },
  {
    "path": "config/dpkg/clean",
    "content": "winregrc/*.pyc\n*.pyc\n"
  },
  {
    "path": "config/dpkg/compat",
    "content": "9\n"
  },
  {
    "path": "config/dpkg/control",
    "content": "Source: winreg-kb\nSection: python\nPriority: extra\nMaintainer: Joachim Metz <joachim.metz@gmail.com>\nBuild-Depends: debhelper (>= 9), dh-python, python3-all (>= 3.10~), python3-setuptools, pybuild-plugin-pyproject\nStandards-Version: 4.1.4\nX-Python3-Version: >= 3.10\nHomepage: https://github.com/libyal/winreg-kb\n\nPackage: python3-winregrc\nArchitecture: all\nDepends: libbde-python3 (>= 20220121), libcaes-python3 (>= 20240114), libcreg-python3 (>= 20200725), libewf-python3 (>= 20131210), libfcrypto-python3 (>= 20240114), libfsapfs-python3 (>= 20220709), libfsext-python3 (>= 20220829), libfsfat-python3 (>= 20220925), libfshfs-python3 (>= 20220831), libfsntfs-python3 (>= 20211229), libfsxfs-python3 (>= 20220829), libfvde-python3 (>= 20220121), libfwnt-python3 (>= 20210717), libfwps-python3 (>= 20240225), libfwsi-python3 (>= 20240315), libhmac-python3 (>= 20230205), libluksde-python3 (>= 20220121), libmodi-python3 (>= 20210405), libphdi-python3 (>= 20220228), libqcow-python3 (>= 20201213), libregf-python3 (>= 20201002), libsigscan-python3 (>= 20230109), libsmdev-python3 (>= 20140529), libsmraw-python3 (>= 20140612), libvhdi-python3 (>= 20201014), libvmdk-python3 (>= 20140421), libvsapm-python3 (>= 20230506), libvsgpt-python3 (>= 20211115), libvshadow-python3 (>= 20160109), libvslvm-python3 (>= 20160109), python3-acstore (>= 20230101), python3-artifacts (>= 20220219), python3-dfdatetime (>= 20221112), python3-dfimagetools (>= 20240301), python3-dfvfs (>= 20240115), python3-dfwinreg (>= 20240229), python3-dtfabric (>= 20230518), python3-pytsk3 (>= 20210419), python3-xattr (>= 0.7.2), python3-yaml (>= 3.10), ${misc:Depends}\nDescription: Python 3 module of Windows Registry resources (winregrc)\n winregrc is a Python module part of winreg-kb to allow reuse of\n Windows Registry resources.\n\nPackage: winreg-kb-tools\nArchitecture: all\nDepends: python3-winregrc (>= ${binary:Version}), ${misc:Depends}\nDescription: Tools for Windows Registry knowledge base (winreg-kb)\n Winreg-kb is a project to build a Windows Registry knowledge base.\n"
  },
  {
    "path": "config/dpkg/copyright",
    "content": "Format: http://dep.debian.net/deps/dep5\nUpstream-Name: dtfabric\nSource: https://github.com/libyal/dtfabric\n\nFiles: *\nCopyright: 2016-2017, Joachim Metz <joachim.metz@gmail.com>\nLicense: Apache-2.0\n\nLicense: Apache-2.0\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n .\n http://www.apache.org/licenses/LICENSE-2.0\n .\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n .\n On Debian systems, the complete text of the Apache version 2.0 license\n can be found in \"/usr/share/common-licenses/Apache-2.0\".\n"
  },
  {
    "path": "config/dpkg/python3-winregrc.install",
    "content": "usr/lib/python3*/dist-packages/winregrc/*.py\nusr/lib/python3*/dist-packages/winregrc/*.yaml\nusr/lib/python3*/dist-packages/winregrc*.dist-info/*\n"
  },
  {
    "path": "config/dpkg/rules",
    "content": "#!/usr/bin/make -f\n\n%:\n\tdh $@ --buildsystem=pybuild --with=python3\n\n.PHONY: override_dh_auto_test\noverride_dh_auto_test:\n\n"
  },
  {
    "path": "config/dpkg/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "config/pylint/spelling-private-dict",
    "content": "appcompatcachecachedentry\nargparse\nargs\nbackports\nbool\ncachedtask\ncodecs\ncodepage\nconfig\ncsd\ncurrentversion\ndatatypefabric\ndatatypemap\ndatatypemapcontext\ndatetimevalues\ndes\ndev\ndfdatetime\ndfvfs\ndfwinreg\ndll\ndpkg\ndtfabric\nendian\nfileio\nfilename\nfilenames\nfilesystem\nfiletime\ngid\nguid\nknownfolder\nkwargs\nlockdown\nlsa\nlzma\nmacos\nmappingerror\nmostrecentlyusedentry\nmru\nmsi\nnl\nons\nos\noutputwriter\nparseheader\npathspec\nposixtime\npre\npy\npyfwsi\npyregf\nrb\nrc\nreadfp\nregf\nsdist\nshellfolder\nstdin\nstdout\nstr\nsubkeys\nsys\nsyskey\ntimestamp\ntimestamps\ntuple\ntypelibrary\nuseraccount\nuserassistentry\nusername\nvfsstat\nvolumescannermediator\nwindowsservice\nwindowsvolumescanner\nwinregistry\nwinregistrykey\nwinregistryvalue\nwinregrc\nxp\n"
  },
  {
    "path": "dependencies.ini",
    "content": "[acstore]\ndpkg_name: python3-acstore\nminimum_version: 20230101\nrpm_name: python3-acstore\nversion_property: __version__\n\n[artifacts]\ndpkg_name: python3-artifacts\nminimum_version: 20220219\nrpm_name: python3-artifacts\nversion_property: __version__\n\n[dfdatetime]\ndpkg_name: python3-dfdatetime\nminimum_version: 20221112\nrpm_name: python3-dfdatetime\nversion_property: __version__\n\n[dfimagetools]\ndpkg_name: python3-dfimagetools\nminimum_version: 20240301\nrpm_name: python3-dfimagetools\nversion_property: __version__\n\n[dfvfs]\ndpkg_name: python3-dfvfs\nminimum_version: 20240115\nrpm_name: python3-dfvfs\nversion_property: __version__\n\n[dfwinreg]\ndpkg_name: python3-dfwinreg\nminimum_version: 20240229\nrpm_name: python3-dfwinreg\nversion_property: __version__\n\n[dtfabric]\ndpkg_name: python3-dtfabric\nminimum_version: 20230518\nrpm_name: python3-dtfabric\nversion_property: __version__\n\n[pybde]\ndpkg_name: libbde-python3\nl2tbinaries_name: libbde\nminimum_version: 20220121\npypi_name: libbde-python\nrpm_name: libbde-python3\nversion_property: get_version()\n\n[pycaes]\ndpkg_name: libcaes-python3\nl2tbinaries_name: libcaes\nminimum_version: 20240114\npypi_name: libcaes-python\nrpm_name: libcaes-python3\nversion_property: get_version()\n\n[pycreg]\ndpkg_name: libcreg-python3\nl2tbinaries_name: libcreg\nminimum_version: 20200725\npypi_name: libcreg-python\nrpm_name: libcreg-python3\nversion_property: get_version()\n\n[pyewf]\ndpkg_name: libewf-python3\nl2tbinaries_name: libewf\nminimum_version: 20131210\npypi_name: libewf-python\nrpm_name: libewf-python3\nversion_property: get_version()\n\n[pyfcrypto]\ndpkg_name: libfcrypto-python3\nl2tbinaries_name: libfcrypto\nminimum_version: 20240114\npypi_name: libfcrypto-python\nrpm_name: libfcrypto-python3\nversion_property: get_version()\n\n[pyfsapfs]\ndpkg_name: libfsapfs-python3\nl2tbinaries_name: libfsapfs\nminimum_version: 20220709\npypi_name: libfsapfs-python\nrpm_name: libfsapfs-python3\nversion_property: get_version()\n\n[pyfsext]\ndpkg_name: libfsext-python3\nl2tbinaries_name: libfsext\nminimum_version: 20220829\npypi_name: libfsext-python\nrpm_name: libfsext-python3\nversion_property: get_version()\n\n[pyfsfat]\ndpkg_name: libfsfat-python3\nl2tbinaries_name: libfsfat\nminimum_version: 20220925\npypi_name: libfsfat-python\nrpm_name: libfsfat-python3\nversion_property: get_version()\n\n[pyfshfs]\ndpkg_name: libfshfs-python3\nl2tbinaries_name: libfshfs\nminimum_version: 20220831\npypi_name: libfshfs-python\nrpm_name: libfshfs-python3\nversion_property: get_version()\n\n[pyfsntfs]\ndpkg_name: libfsntfs-python3\nl2tbinaries_name: libfsntfs\nminimum_version: 20211229\npypi_name: libfsntfs-python\nrpm_name: libfsntfs-python3\nversion_property: get_version()\n\n[pyfsxfs]\ndpkg_name: libfsxfs-python3\nl2tbinaries_name: libfsxfs\nminimum_version: 20220829\npypi_name: libfsxfs-python\nrpm_name: libfsxfs-python3\nversion_property: get_version()\n\n[pyfvde]\ndpkg_name: libfvde-python3\nl2tbinaries_name: libfvde\nminimum_version: 20220121\npypi_name: libfvde-python\nrpm_name: libfvde-python3\nversion_property: get_version()\n\n[pyfwnt]\ndpkg_name: libfwnt-python3\nl2tbinaries_name: libfwnt\nminimum_version: 20210717\npypi_name: libfwnt-python\nrpm_name: libfwnt-python3\nversion_property: get_version()\n\n[pyfwps]\ndpkg_name: libfwps-python3\nl2tbinaries_name: libfwps\nminimum_version: 20240225\npypi_name: libfwps-python\nrpm_name: libfwps-python3\nversion_property: get_version()\n\n[pyfwsi]\ndpkg_name: libfwsi-python3\nl2tbinaries_name: libfwsi\nminimum_version: 20240315\npypi_name: libfwsi-python\nrpm_name: libfwsi-python3\nversion_property: get_version()\n\n[pyhmac]\ndpkg_name: libhmac-python3\nl2tbinaries_name: libhmac\nminimum_version: 20230205\npypi_name: libhmac-python\nrpm_name: libhmac-python3\nversion_property: get_version()\n\n[pyluksde]\ndpkg_name: libluksde-python3\nl2tbinaries_name: libluksde\nminimum_version: 20220121\npypi_name: libluksde-python\nrpm_name: libluksde-python3\nversion_property: get_version()\n\n[pymodi]\ndpkg_name: libmodi-python3\nl2tbinaries_name: libmodi\nminimum_version: 20210405\npypi_name: libmodi-python\nrpm_name: libmodi-python3\nversion_property: get_version()\n\n[pyphdi]\ndpkg_name: libphdi-python3\nl2tbinaries_name: libphdi\nminimum_version: 20220228\npypi_name: libphdi-python\nrpm_name: libphdi-python3\nversion_property: get_version()\n\n[pyqcow]\ndpkg_name: libqcow-python3\nl2tbinaries_name: libqcow\nminimum_version: 20201213\npypi_name: libqcow-python\nrpm_name: libqcow-python3\nversion_property: get_version()\n\n[pyregf]\ndpkg_name: libregf-python3\nl2tbinaries_name: libregf\nminimum_version: 20201002\npypi_name: libregf-python\nrpm_name: libregf-python3\nversion_property: get_version()\n\n[pysigscan]\ndpkg_name: libsigscan-python3\nl2tbinaries_name: libsigscan\nminimum_version: 20230109\npypi_name: libsigscan-python\nrpm_name: libsigscan-python3\nversion_property: get_version()\n\n[pysmdev]\ndpkg_name: libsmdev-python3\nl2tbinaries_name: libsmdev\nminimum_version: 20140529\npypi_name: libsmdev-python\nrpm_name: libsmdev-python3\nversion_property: get_version()\n\n[pysmraw]\ndpkg_name: libsmraw-python3\nl2tbinaries_name: libsmraw\nminimum_version: 20140612\npypi_name: libsmraw-python\nrpm_name: libsmraw-python3\nversion_property: get_version()\n\n[pytsk3]\ndpkg_name: python3-pytsk3\nminimum_version: 20210419\nrpm_name: python3-pytsk3\nversion_property: get_version()\n\n[pyvhdi]\ndpkg_name: libvhdi-python3\nl2tbinaries_name: libvhdi\nminimum_version: 20201014\npypi_name: libvhdi-python\nrpm_name: libvhdi-python3\nversion_property: get_version()\n\n[pyvmdk]\ndpkg_name: libvmdk-python3\nl2tbinaries_name: libvmdk\nminimum_version: 20140421\npypi_name: libvmdk-python\nrpm_name: libvmdk-python3\nversion_property: get_version()\n\n[pyvsapm]\ndpkg_name: libvsapm-python3\nl2tbinaries_name: libvsapm\nminimum_version: 20230506\npypi_name: libvsapm-python\nrpm_name: libvsapm-python3\nversion_property: get_version()\n\n[pyvsgpt]\ndpkg_name: libvsgpt-python3\nl2tbinaries_name: libvsgpt\nminimum_version: 20211115\npypi_name: libvsgpt-python\nrpm_name: libvsgpt-python3\nversion_property: get_version()\n\n[pyvshadow]\ndpkg_name: libvshadow-python3\nl2tbinaries_name: libvshadow\nminimum_version: 20160109\npypi_name: libvshadow-python\nrpm_name: libvshadow-python3\nversion_property: get_version()\n\n[pyvslvm]\ndpkg_name: libvslvm-python3\nl2tbinaries_name: libvslvm\nminimum_version: 20160109\npypi_name: libvslvm-python\nrpm_name: libvslvm-python3\nversion_property: get_version()\n\n[xattr]\ndpkg_name: python3-xattr\nis_optional: true\nminimum_version: 0.7.2\npypi_name: xattr\nrpm_name: python3-xattr\nversion_property: __version__\n\n[yaml]\ndpkg_name: python3-yaml\nl2tbinaries_name: PyYAML\nminimum_version: 3.10\npypi_name: PyYAML\nrpm_name: python3-pyyaml\nversion_property: __version__\n"
  },
  {
    "path": "docs/conf.py",
    "content": "\"\"\"Sphinx build configuration file.\"\"\"\n\nimport os\nimport sys\n\nfrom sphinx.ext import apidoc\n\nfrom docutils import nodes\nfrom docutils import transforms\n\n# Change PYTHONPATH to include winregrc module and dependencies.\nsys.path.insert(0, os.path.abspath('..'))\n\nimport winregrc  # pylint: disable=wrong-import-position\n\nimport utils.dependencies  # pylint: disable=wrong-import-position\n\n\n# -- General configuration ------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\nneeds_sphinx = '2.0.1'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'recommonmark',\n    'sphinx.ext.autodoc',\n    'sphinx.ext.coverage',\n    'sphinx.ext.doctest',\n    'sphinx.ext.napoleon',\n    'sphinx.ext.viewcode',\n    'sphinx_markdown_tables',\n    'sphinx_rtd_theme',\n]\n\n# We cannot install architecture dependent Python modules on readthedocs,\n# therefore we mock most imports.\npip_installed_modules = set()\n\ndependency_helper = utils.dependencies.DependencyHelper(\n    dependencies_file=os.path.join('..', 'dependencies.ini'),\n    test_dependencies_file=os.path.join('..', 'test_dependencies.ini'))\nmodules_to_mock = set(dependency_helper.dependencies.keys())\nmodules_to_mock = modules_to_mock.difference(pip_installed_modules)\n\nautodoc_mock_imports = sorted(modules_to_mock)\n\n# Options for the Sphinx Napoleon extension, which reads Google-style\n# docstrings.\nnapoleon_google_docstring = True\nnapoleon_numpy_docstring = False\nnapoleon_include_init_with_doc = True\nnapoleon_include_private_with_doc = False\nnapoleon_include_special_with_doc = True\n\n# General information about the project.\n# pylint: disable=redefined-builtin\nproject = 'Windows Registry knowledge base (winreg-kb)'\ncopyright = 'The Windows Registry knowledge base (winreg-kb) authors'\nversion = winregrc.__version__\nrelease = winregrc.__version__\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\nexclude_patterns = ['_build']\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = 'sphinx'\n\n\n# -- Options for HTML output ----------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\nhtml_theme = 'sphinx_rtd_theme'\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'winregkbdoc'\n\n\n# -- Options linkcheck ----------------------------------------------------\n\nlinkcheck_ignore = [\n]\n\n\n# -- Code to rewrite links for readthedocs --------------------------------\n\n# This function is a Sphinx core event callback, the format of which is detailed\n# here: https://www.sphinx-doc.org/en/master/extdev/appapi.html#events\n\n# pylint: disable=unused-argument\ndef RunSphinxAPIDoc(app):\n  \"\"\"Runs sphinx-apidoc to auto-generate documentation.\n\n  Args:\n    app (sphinx.application.Sphinx): Sphinx application. Required by the\n        the Sphinx event callback API.\n  \"\"\"\n  current_directory = os.path.abspath(os.path.dirname(__file__))\n  module_path = os.path.join(current_directory, '..', 'winregrc')\n  api_directory = os.path.join(current_directory, 'sources', 'api')\n  apidoc.main(['-o', api_directory, module_path, '--force'])\n\n\nclass MarkdownLinkFixer(transforms.Transform):\n  \"\"\"Transform definition to parse .md references to internal pages.\"\"\"\n\n  default_priority = 1000\n\n  _URI_PREFIXES = []\n\n  def _FixLinks(self, node):\n    \"\"\"Corrects links to .md files not part of the documentation.\n\n    Args:\n      node (docutils.nodes.Node): docutils node.\n\n    Returns:\n      docutils.nodes.Node: docutils node, with correct URIs outside\n          of Markdown pages outside the documentation.\n    \"\"\"\n    if isinstance(node, nodes.reference) and 'refuri' in node:\n      reference_uri = node['refuri']\n      for uri_prefix in self._URI_PREFIXES:\n        if (reference_uri.startswith(uri_prefix) and not (\n            reference_uri.endswith('.asciidoc') or\n            reference_uri.endswith('.md'))):\n          node['refuri'] = reference_uri + '.md'\n          break\n\n    return node\n\n  def _Traverse(self, node):\n    \"\"\"Traverses the document tree rooted at node.\n\n    Args:\n      node (docutils.nodes.Node): docutils node.\n    \"\"\"\n    self._FixLinks(node)\n\n    for child_node in node.children:\n      self._Traverse(child_node)\n\n  # pylint: disable=arguments-differ\n  def apply(self):\n    \"\"\"Applies this transform on document tree.\"\"\"\n    self._Traverse(self.document)\n\n\n# pylint: invalid-name\ndef setup(app):\n  \"\"\"Called at Sphinx initialization.\n\n  Args:\n    app (sphinx.application.Sphinx): Sphinx application.\n  \"\"\"\n  # Triggers sphinx-apidoc to generate API documentation.\n  app.connect('builder-inited', RunSphinxAPIDoc)\n  app.add_config_value(\n      'recommonmark_config', {'enable_auto_toc_tree': True}, True)\n  app.add_transform(MarkdownLinkFixer)\n"
  },
  {
    "path": "docs/index.rst",
    "content": "Welcome to the winreg-kb documentation\n========================================\n\nwinreg-kb is a project to build a Windows Registry Knowledge Base.\n\nwinregrc is a Python module part of winreg-kb to allow reuse of Windows\nRegistry Resources.\n\nThe source code is available from the `project page <https://github.com/libyal/winreg-kb>`__.\n\n.. toctree::\n   :maxdepth: 2\n\n   sources/windows-registry/index\n\n.. toctree::\n   :maxdepth: 2\n\n   sources/system-keys/index\n\n.. toctree::\n   :maxdepth: 2\n\n   sources/security-accounts-manager-keys/index\n\n.. toctree::\n   :maxdepth: 2\n\n   sources/explorer-keys/index\n\n.. toctree::\n   :maxdepth: 2\n\n   Windows EventLog keys <sources/EventLog-keys>\n\n.. toctree::\n   :maxdepth: 2\n\n   sources/internet-explorer-keys/index\n\n.. toctree::\n   :maxdepth: 2\n\n   sources/application-keys/index\n\n.. toctree::\n   :maxdepth: 2\n\n   API documentation <sources/api/winregrc>\n\n\nIndices and tables\n==================\n\n* :ref:`genindex`\n* :ref:`modindex`\n\n"
  },
  {
    "path": "docs/requirements.txt",
    "content": "certifi >= 2023.11.17\ndocutils\nMarkdown\nrecommonmark\nsphinx >= 4.1.0\nsphinx-markdown-tables\nsphinx-rtd-theme >= 0.5.1\n"
  },
  {
    "path": "docs/sources/EventLog-keys.md",
    "content": "# EventLog keys\n\n## EventLog providers\n\nInformation about EventLog providers is stored across multiple keys:\n\n* the Services\\EventLog key, which has been around since at least Windows NT 3.5\n* the WINEVT\\Publishers key, which was introduced in Windows Vista\n\nNote that the combined information of both keys can be needed, for example\nthe Services\\EventLog key:\n\n```\nLog type                : System\nLog source              : Microsoft-Windows-Time-Service\nIdentifier              : {06edcfeb-0fd0-4e53-acca-a6f8bbf81bcb}\nEvent message files     : %SystemRoot%\\system32\\w32time.dll\n```\n\n```\nLog type                : System\nLog source              : W32Time\nIdentifier              : {06edcfeb-0fd0-4e53-acca-a6f8bbf81bcb}\nEvent message files     : %SystemRoot%\\system32\\w32time.dll\n```\n\nIn combination with the corresponding WINEVT\\Publishers key:\n\n```\nName\t\t\t: Microsoft-Windows-Time-Service\nIdentifier              : {06edcfeb-0fd0-4e53-acca-a6f8bbf81bcb}\nEvent message files     : %SystemRoot%\\system32\\w32time.dll\n```\n\nIs the following EvenLog provider:\n\n```\nName\t\t\t: Microsoft-Windows-Time-Service\nIdentifier              : {06edcfeb-0fd0-4e53-acca-a6f8bbf81bcb}\nLog type                : System\nLog source(s)           : Microsoft-Windows-Time-Service\n                        : W32Time\nEvent message files     : %SystemRoot%\\system32\\w32time.dll\n```\n\nNote that an EventLog provider can have multiple log types and log sources.\nIt is not known if a log source that matches the EventLog provider name can be\ndeduplicated.\n\nOr as specified as Event XML:\n\n```\n<Provider Name='Microsoft-Windows-Time-Service'\n          Guid='{06edcfeb-0fd0-4e53-acca-a6f8bbf81bcb}'\n          EventSourceName='W32Time'/>\n```\n\n## Services\\EventLog key\n\nThe event sources are stored in the Services\\EventLog key:\n\n```\nHKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\EventLog\\\n```\n\nOn Windows NT it can be found in the SYSTEM Registry file.\n\nThe Services\\EventLog key contains a per EventLog type sub key, for example\nfor the \"System\" EventLog type:\n\n```\nHKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\EventLog\\System\\\n```\n\nCommon EventLog types are:\n\n* Application\n* Security\n* System\n\nThe EventLog type sub key contains a per EventLog source-per-type sub key,\nfor example for the \"Workstation\" EventLog source:\n\n```\nHKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\EventLog\\System\\Workstation\\\n```\n\nNote that the log source is case insensitive; so \"Workstation\" and \"workstation\"\nare considered equivalent.\n\n### Services\\EventLog type sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nSources | | Array of strings with end-of-string character containing the names of the event sources\n\n#### Services\\EventLog source-per-type sub key\n\nThe Services\\EventLog source-per-type sub key contains information about\na single event source.\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nCategoryCount | REG_DWORD | Number of event categories supported\nCategoryMessageFile | REG_EXPAND_SZ | Path to the category message file. A category message file contains language-dependent strings that describe the categories.\nEventMessageFile | REG_EXPAND_SZ | Path to event message files. An event message file contains language-dependent strings that describe the events. Note that this value can contain multiple filenames, for example \"C:\\WINDOWS\\system32\\COMRES.DLL;C:\\WINDOWS\\system32\\xpsp2res.dll\". Multiple files are delimited using a semicolon.\nParameterMessageFile | REG_EXPAND_SZ | Path to the parameter message file. A parameter message file contains language-independent strings that are to be inserted into the event description strings.\nProviderGuid | REG_SZ | Identifier, in the form \"{%GUID%}\", of the event provider.\nTypesSupported | REG_DWORD | Bitmask of supported types\n\n##### TypesSupported value data\n\nValue | Identifier | Description\n--- | --- | ---\n0x0001 | EVENTLOG_ERROR_TYPE |\n0x0002 | EVENTLOG_WARNING_TYPE |\n0x0004 | EVENTLOG_INFORMATION_TYPE |\n0x0008 | EVENTLOG_AUDIT_SUCCESS |\n0x0010 | EVENTLOG_AUDIT_FAILURE |\n\n## WINEVT\\Publishers key\n\nThe event publishers (or providers) are stored in the WINEVT\\Publishers key:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\n```\n\nOn Windows Vista or later it can be found in the SOFTWARE Registry file.\n\nThe WINEVT\\Publishers key contains a GUID type sub key, for example\n\"{de513a55-c345-438b-9a74-e18cac5c5cc5}\":\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\%GUID%\n```\n\n### WINEVT\\Publishers GUID sub key\n\nA WINEVT\\Publishers GUID sub key contains information about a single event\npublisher.\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n(default) | REG_SZ | Case insensitive log source.\nMessageFileName | REG_EXPAND_SZ | Path to an event message file. An event message file contains language-dependent strings that describe the events.\nResourceFileName | REG_EXPAND_SZ | Path to an event resource file.\nParameterFileName | REG_EXPAND_SZ | Path to an event parameter file.\n\n## Message file paths\n\nA message file path can be defined in numerous different ways for example:\n\nAs an absolute path\n\n```\nC:\\Windows\\System32\\mscoree.dll\n```\n\nAs a relative path:\n\n```\nmscoree.dll\n```\n\nAs a path using environment variables:\n\n```\n%SystemDrive%\\Windows\\System32\\mscoree.dll\n%SystemRoot%\\System32\\mscoree.dll\n%WinDir%\\System32\\mscoree.dll\n```\n\nAs a path using universal OEM runtime macros:\n\n```\n$(runtime.system32)\\mscoree.dll\n```\n\n```\n\\SystemRoot\\system32\\mscoree.dll\n```\n\n## EventLog provider with multiple provider GUIDs\n\nSeen on Windows 8.0, 8.1, 10, 11 and 2012:\n\n```\nKey path: HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\EventLog\\Application\\Microsoft-Windows-KdsSvc\nName: Microsoft-Windows-KdsSvc\nLast written time: Oct 30, 2015 07:25:12.126588100 UTC\n\nValue: 0 providerGuid\nType: string (REG_SZ)\nData size: 78\nData: {d4be7726-dc7a-11df-a6e6-0902dfd72085}\n```\n\n```\nKey path: HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\{89203471-d554-47d4-bde4-7552ec219999}\nName: {89203471-d554-47d4-bde4-7552ec219999}\nLast written time: Oct 30, 2015 07:25:53.860831900 UTC\n\nValue: 0 (default)\nType: string (REG_SZ)\nData size: 50\nData: Microsoft-Windows-KdsSvc\n\nValue: 1 ResourceFileName\nType: expandable string (REG_EXPAND_SZ)\nData size: 66\nData: %SystemRoot%\\system32\\KdsCli.dll\n\nValue: 2 MessageFileName\nType: expandable string (REG_EXPAND_SZ)\nData size: 66\nData: %SystemRoot%\\system32\\KdsCli.dll\n```\n\n## EventLog provider with multiple log types\n\nSeen on Windows 10:\n\n```\nKey path: HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\EventLog\\Application\\Microsoft-Windows-EventCollector\nName: Microsoft-Windows-EventCollector\nLast written time: Sep 13, 2014 07:27:56.080450600 UTC\n\nValue: 0 ProviderGuid\nType: string (REG_SZ)\nData size: 78\nData: {b977cf02-76f6-df84-cc1a-6a4b232322b6}\n\nValue: 1 EventMessageFile\nType: expandable string (REG_EXPAND_SZ)\nData size: 66\nData: %SystemRoot%\\system32\\wecsvc.dll\n```\n\n```\nKey path: HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\EventLog\\System\\Microsoft-Windows-EventCollector\nName: Microsoft-Windows-EventCollector\nLast written time: Sep 13, 2014 07:27:56.080450600 UTC\n\nValue: 0 ProviderGuid\nType: string (REG_SZ)\nData size: 78\nData: {b977cf02-76f6-df84-cc1a-6a4b232322b6}\n\nValue: 1 EventMessageFile\nType: expandable string (REG_EXPAND_SZ)\nData size: 66\nData: %SystemRoot%\\system32\\wecsvc.dll\n```\n\n```\nKey path:  HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\{b977cf02-76f6-df84-cc1a-6a4b232322b6}\nName: {b977cf02-76f6-df84-cc1a-6a4b232322b6}\nLast written time: Sep 13, 2014 07:27:56.080450600 UTC\n\nValue: 0 (default)\nType: string (REG_SZ)\nData size: 66\nData: Microsoft-Windows-EventCollector\n\nValue: 1 ResourceFileName\nType: expandable string (REG_EXPAND_SZ)\nData size: 66\nData: %SystemRoot%\\system32\\wecsvc.dll\n\nValue: 2 MessageFileName\nType: expandable string (REG_EXPAND_SZ)\nData size: 66\nData: %SystemRoot%\\system32\\wecsvc.dll\n```\n\n## External Links\n\n* [Eventlog Key](https://learn.microsoft.com/en-us/windows/win32/eventlog/eventlog-key)\n* [Event Sources](https://learn.microsoft.com/en-us/windows/win32/eventlog/event-sources)\n* [winevt.h header](https://learn.microsoft.com/en-us/windows/win32/api/winevt/)\n* [Windows Event Log](https://learn.microsoft.com/en-us/windows/win32/api/_wes/)\n\n"
  },
  {
    "path": "docs/sources/api/modules.rst",
    "content": "winregrc\n========\n\n.. toctree::\n   :maxdepth: 4\n\n   winregrc\n"
  },
  {
    "path": "docs/sources/api/winregrc.rst",
    "content": "winregrc package\n================\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   winregrc.scripts\n\nSubmodules\n----------\n\nwinregrc.appcompatcache module\n------------------------------\n\n.. automodule:: winregrc.appcompatcache\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.application\\_identifiers module\n----------------------------------------\n\n.. automodule:: winregrc.application_identifiers\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.cached\\_credentials module\n-----------------------------------\n\n.. automodule:: winregrc.cached_credentials\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.catalog module\n-----------------------\n\n.. automodule:: winregrc.catalog\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.controlpanel\\_items module\n-----------------------------------\n\n.. automodule:: winregrc.controlpanel_items\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.data\\_format module\n----------------------------\n\n.. automodule:: winregrc.data_format\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.delegatefolders module\n-------------------------------\n\n.. automodule:: winregrc.delegatefolders\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.environment\\_variables module\n--------------------------------------\n\n.. automodule:: winregrc.environment_variables\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.errors module\n----------------------\n\n.. automodule:: winregrc.errors\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.eventlog\\_providers module\n-----------------------------------\n\n.. automodule:: winregrc.eventlog_providers\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.filters module\n-----------------------\n\n.. automodule:: winregrc.filters\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.hexdump module\n-----------------------\n\n.. automodule:: winregrc.hexdump\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.interface module\n-------------------------\n\n.. automodule:: winregrc.interface\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.knownfolders module\n----------------------------\n\n.. automodule:: winregrc.knownfolders\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.mounted\\_devices module\n--------------------------------\n\n.. automodule:: winregrc.mounted_devices\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.mru module\n-------------------\n\n.. automodule:: winregrc.mru\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.msie\\_zone\\_info module\n--------------------------------\n\n.. automodule:: winregrc.msie_zone_info\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.output\\_writers module\n-------------------------------\n\n.. automodule:: winregrc.output_writers\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.profiles module\n------------------------\n\n.. automodule:: winregrc.profiles\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.programscache module\n-----------------------------\n\n.. automodule:: winregrc.programscache\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.sam module\n-------------------\n\n.. automodule:: winregrc.sam\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.services module\n------------------------\n\n.. automodule:: winregrc.services\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.shell\\_property\\_keys module\n-------------------------------------\n\n.. automodule:: winregrc.shell_property_keys\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.shellfolders module\n----------------------------\n\n.. automodule:: winregrc.shellfolders\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.srum\\_extensions module\n--------------------------------\n\n.. automodule:: winregrc.srum_extensions\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.sysinfo module\n-----------------------\n\n.. automodule:: winregrc.sysinfo\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.syskey module\n----------------------\n\n.. automodule:: winregrc.syskey\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.task\\_cache module\n---------------------------\n\n.. automodule:: winregrc.task_cache\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.time\\_zones module\n---------------------------\n\n.. automodule:: winregrc.time_zones\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.type\\_libraries module\n-------------------------------\n\n.. automodule:: winregrc.type_libraries\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.usbstor module\n-----------------------\n\n.. automodule:: winregrc.usbstor\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.userassist module\n--------------------------\n\n.. automodule:: winregrc.userassist\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.versions module\n------------------------\n\n.. automodule:: winregrc.versions\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.volume\\_scanner module\n-------------------------------\n\n.. automodule:: winregrc.volume_scanner\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nModule contents\n---------------\n\n.. automodule:: winregrc\n   :members:\n   :show-inheritance:\n   :undoc-members:\n"
  },
  {
    "path": "docs/sources/api/winregrc.scripts.rst",
    "content": "winregrc.scripts package\n========================\n\nSubmodules\n----------\n\nwinregrc.scripts.appcompatcache module\n--------------------------------------\n\n.. automodule:: winregrc.scripts.appcompatcache\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.application\\_identifiers module\n------------------------------------------------\n\n.. automodule:: winregrc.scripts.application_identifiers\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.cached\\_credentials module\n-------------------------------------------\n\n.. automodule:: winregrc.scripts.cached_credentials\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.catalog module\n-------------------------------\n\n.. automodule:: winregrc.scripts.catalog\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.controlpanel\\_items module\n-------------------------------------------\n\n.. automodule:: winregrc.scripts.controlpanel_items\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.delegatefolders module\n---------------------------------------\n\n.. automodule:: winregrc.scripts.delegatefolders\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.environment\\_variables module\n----------------------------------------------\n\n.. automodule:: winregrc.scripts.environment_variables\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.eventlog\\_providers module\n-------------------------------------------\n\n.. automodule:: winregrc.scripts.eventlog_providers\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.knownfolders module\n------------------------------------\n\n.. automodule:: winregrc.scripts.knownfolders\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.mounted\\_devices module\n----------------------------------------\n\n.. automodule:: winregrc.scripts.mounted_devices\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.mru module\n---------------------------\n\n.. automodule:: winregrc.scripts.mru\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.msie\\_zone\\_info module\n----------------------------------------\n\n.. automodule:: winregrc.scripts.msie_zone_info\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.profiles module\n--------------------------------\n\n.. automodule:: winregrc.scripts.profiles\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.programscache module\n-------------------------------------\n\n.. automodule:: winregrc.scripts.programscache\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.sam module\n---------------------------\n\n.. automodule:: winregrc.scripts.sam\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.services module\n--------------------------------\n\n.. automodule:: winregrc.scripts.services\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.shellfolders module\n------------------------------------\n\n.. automodule:: winregrc.scripts.shellfolders\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.srum\\_extensions module\n----------------------------------------\n\n.. automodule:: winregrc.scripts.srum_extensions\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.sysinfo module\n-------------------------------\n\n.. automodule:: winregrc.scripts.sysinfo\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.syskey module\n------------------------------\n\n.. automodule:: winregrc.scripts.syskey\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.task\\_cache module\n-----------------------------------\n\n.. automodule:: winregrc.scripts.task_cache\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.time\\_zones module\n-----------------------------------\n\n.. automodule:: winregrc.scripts.time_zones\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.type\\_libraries module\n---------------------------------------\n\n.. automodule:: winregrc.scripts.type_libraries\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.usbstor module\n-------------------------------\n\n.. automodule:: winregrc.scripts.usbstor\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nwinregrc.scripts.userassist module\n----------------------------------\n\n.. automodule:: winregrc.scripts.userassist\n   :members:\n   :show-inheritance:\n   :undoc-members:\n\nModule contents\n---------------\n\n.. automodule:: winregrc.scripts\n   :members:\n   :show-inheritance:\n   :undoc-members:\n"
  },
  {
    "path": "docs/sources/application-keys/7-Zip.md",
    "content": "# 7-Zip\n\n**TODO this page currently contains rough notes, fine tune these**\n\nThe 7-Zip application uses the following Windows Registry key to store various\nuser specific information.\n\n```\nHKEY_CURRENT_USER\\Software\\7-Zip\n```\n\nSub keys:\n\nName | Description\n--- | ---\nFM |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nLang | | Language tag, for example \"en-US\" or \"-\" if empty.\n\n## 7-Zip FM sub key\n\nSub keys:\n\nName | Description\n--- | ---\nColumns |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nFlatViewArc# | | Where # is a numeric value e.g. 0 or 1\nFolderShortcuts | |\nFolderHistory | | Contains a list of UTF-16 little-endian encoded strings with an end-of-string character\nListMode | |\nPanels | |\nPanelPath# | | Where # is a numeric value e.g. 0 or 1 <br> Contains an UTF-16 little-endian encoded string\nPosition | |\n\n### 7-Zip FM Columns sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n7-Zip.Rar | REG_BINARY |\n7-Zip.7z | REG_BINARY |\n\n"
  },
  {
    "path": "docs/sources/application-keys/CCleaner.md",
    "content": "# CCleaner\n\n**TODO this page currently contains rough notes, fine tune these**\n\nThe CCleaner application uses the following Windows Registry key to store its\nconfiguration.\n\n```\nHKEY_CURRENT_USER\\Software\\Piriform\\CCleaner\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n(App)Program Name | REG_SZ |\nAutoClose | | Automatically close program after cleaning, where 0 = Disabled and 1 = Enabled\nBackupDir | | Default path for the Issues Registry back up\nBackupPrompt | | Prompts user to back up the contents of the Issues Registry before removing them, where 0 = Disabled and 1 = Enabled\nBrowserMonitoring | | Whether automatic browser cleaning is active (CCleaner Professional), where 0 = Disabled and 1 = Enabled\nCookiesToSave | REG_SZ | Lists of cookies to preserve\nDefaultDetailedView | | Show detailed view screen (for the whole analysis or cleaning) after the operation finishes, where 0 = Disabled and 1 = Enabled\nDelayTemp | | Delete temporary (Windows) files older than 48 hours, where 0 = Disabled and 1 = Enabled\nFFDetailed | | Display a detailed log of Firefox/Mozilla temporary files, where 0 = Disabled and 1 = Enabled\nHideWarnings | | Hide warnings when advanced items is selected in the cleaning options tree, where 0 = Disabled and 1 = Enabled\nHomeScreen | | Starts on Health Check or Custom Clean, where 0 = Custom Clean and 1 = Health Check\nIEDetailed | | Display a detailed log of Internet Explorer temporary files, where 0 = Disabled and 1 = Enabled\nLanguage | | Language, contains a locale identifier (LCID).\nMinimizeSystemTray | | Minimize program to system tray on close, where 0 = Disabled and 1 = Enabled\nMonitoring | | Have Smart Cleaning, where 0 = Disabled and 1 = Enabled\nMSG_CONFIRMCLEAN | | Ask for confirmation before starting the Cleaning operation, where the value can be \"True\" or \"False\"\nMSG_WARNCHROMECACHE | | Warn when cleaning the Internet Cache in Google Chrome, where the value can be \"True\" or \"False\"\nMSG_WARNMOZCACHE | | Warn when cleaning the Internet Cache in Mozilla Firefox, where the value can be \"True\" or \"False\"\nRunICS | | No longer used, will automatically be set to 0\nSecureDeleteMethod | | Secure deletion method, where 0 = Simple Overwrite (1 pass), 1 = DOD 5220.22-M (3 passes), 2 = NSA (7 passes) or 3 = Gutmann (35 passes)\nSecureDeleteType | | Use a secure deletion method, where 0 = Disabled and 1 = Enabled\nSystemMonitoring | | Activate System Smart Cleaning (or Active Monitoring for CCleaner Professional), where 0 = Disabled and 1 = Enabled\nSystemMonitoringSavingsAction | | System Smart Cleaning (or Active Monitoring for CCleaner Professional) mode, where 3 = \"prompt to clean\", 4 = \"auto clean with notification\" and 5 = \"auto clean without notification\"\nUpdateBackgroundCheck | | Check for software updates every 10 minutes (after program start), where 0 = Disabled and 1 = Enabled\nUpdateKey | REG_SZ | The last update check date and time formatted as: \"MM/DD/YYYY hh:mm:ss [A|P]M\", for example \"07/13/2013 10:03:14 AM\".\nWINDOW_HEIGHT | REG_SZ | Window height dimension in number of pixels.\nWINDOW_LEFT | REG_SZ | Window left position in number of pixels.\nWINDOW_MAX | REG_SZ | Windows is maximized, where 0 = not maximized\nWINDOW_TOP | REG_SZ | Window top position in number of pixels.\nWINDOW_WIDTH | REG_SZ | Window width dimension in number of pixels.\nWipeMFTFreeSpace | | Wipe free space in the NTFS Master File Table (MFT), where 0 = Disabled and 1 = Enabled\n\n## (App)Program Name\n\nThese entries indicate programs that are not part of the default set of enabled\nCleaning Rules, and whether they should be cleaned.\n\nNote: Making an entry of \"App(Your Program)]=true\" will not allow CCleaner to\nclean it, as you would instead need to use the methods listed here.\n\nTrue = Checkbox selected when you start CCleaner.\nFalse = Checkbox cleared when you start CCleaner.\n\nKnown Cleaning Rules:\n\n* (App)Cookies, contains \"True\" if the cookies should be cleaned;\n* (App)Delete Index.dat files\n* (App)History\n* (App)Last Download Location\n* (App)Other Explorer MRUs\n* (App)Recent Documents\n* (App)Recently Typed URLs\n* (App)Run (in Start Menu)\n* (App)Temporary Internet Files\n* (App)Thumbnail Cache\n\n## IncludeX (e.g. Include1, Include2)\n\nCustom files or folders that should be included in cleaning\n\n[PATH|FILE]|Path|Filename\n\n## ExcludeX (e.g. Exclude1, Exclude2)\n\nCustom files or folders that should be excluded from cleaning.\n\n[REG|PATH|FILE]|Path|Filename\n\n## FinderIncludeX (e.g. FinderInclude1, FinderInclude2)\n\nDrives or folders CCleaner to use when searching for duplicate files.\n\nPATH|PATH\\|Filetype|[RECURSE]\n\n## FinderIncludeStates\n\nWhether the checkboxes have been checked or unchecked for folders referenced\nby FinderIncludeX.\n\n0 = Cleared\n1 = Selected\n\nFor example, if there are three FinderIncludeX statements, you can specify the\nchecked/cleared status using the pipe symbol:\n\nFinderIncludeStates=1|0|1 would check the first and last items, and the middle\none would be unchecked.\n\n## External Links\n\n* [Writing a CCleaner RegRipper Plugin Part 1](https://cheeky4n6monkey.blogspot.com/2012/02/writing-ccleaner-regripper-plugin-part.html)\n* [Writing a CCleaner RegRipper Plugin Part 2](http://cheeky4n6monkey.blogspot.com/2012/02/writing-ccleaner-regripper-plugin-part_05.html)\n\n"
  },
  {
    "path": "docs/sources/application-keys/MSDN-web-browser.md",
    "content": "# MSDN web browser\n\n**TODO this page currently contains rough notes, fine tune these**\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\MSDN\\9.0\\WebBrowser\\MRU\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%NUMERIC% | REG_SZ | Where %NUMERIC% is a string in the form: \"[0-9]+\"\n\n"
  },
  {
    "path": "docs/sources/application-keys/Microsoft-Office.md",
    "content": "# Microsoft Office\n\n**TODO this page currently contains rough notes, fine tune these**\n\n## Microsoft Outlook keys\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\%VERSION%\\Outlook\\\n```\n\nWhere %VERSION% corresponds to:\n\nValue | Description\n--- | ---\n8.0 | Outlook 97\n8.5 | Outlook 98\n9.0 | Outlook 2000\n10.0 | Outlook 2002/XP\n11.0 | Outlook 2003\n12.0 | Outlook 2007\n14.0 | Outlook 2010\n15.0 | Outlook 2013\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nForcePSTPath | REG_EXPAND_SZ |\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\Outlook\\Catalog\n```\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\14.0\\Outlook\\Search\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\14.0\\Outlook\\Search\\Catalog\n```\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\15.0\\Outlook\\Search\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%FILENAME% | REG_DWORD |\n\nWhere %FILENAME% is the full filename of Outlook file.\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\15.0\\Outlook\\Search\\Catalog\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%FILENAME% | REG_BINARY |\n\nWhere %FILENAME% is the full filename of Outlook file.\n\nFor \"file/options/search\" allow to search through \"deleted items\"\n\n```\nKey: HKCU\\Software\\Microsoft\\Office\\14.0\\Outlook\\Search\nValue: IncludeDeletedItems\n```\n\nWhere the value data is:\n\n```\n1 = Yes\n```\n\nOutlook generates log files in %temp%\\Outlook logging:\n\n```\nKey: HKEY_CURRENT_USER\\Software\\Microsoft\\Office\\version number\\Outlook\\Search\nValue: EnableLogging = 0xffff0000\n```\n\nProtected View mode\n\n```\nKey: HKEY_CURRENT_USER\\Software\\Microsoft\\Office\\14.0\\Outlook\\Security\nKey: HKEY_CURRENT_USER\\Software\\Policies\\Microsoft\\Office\\14.0\\Outlook\\Security\nValue: MarkInternalAsUnsafe\n```\n\nWhere the value data is:\n\n```\n1 = Yes\n```\n\n### Offline Address Book (OAB)\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\%VERSION%\\Outlook\\Cached Mode\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nDownloadOAB | REG_DWORD |\n\nSetting the value to zero prevents Offline Address Book (OAB) download and \nforces Outlook to use the global address list. If the \"Cached Mode\" key does \nnot exist, create it.\n\n### Secure Temp Folder\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\%VERSION%\\Outlook\\Security\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nOutlookSecureTempFolder | REG_SZ |\n\n## Most Recently Used (MRU) keys\n\n### File Name MRU keys\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nMaximum Entries | | Numeric value\nValue | | Numeric value\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\11.0\\Common\\Open Find\\Microsoft Office Excel\\Settings\\Open\\File Name MRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\11.0\\Common\\Open Find\\Microsoft Office Excel\\Settings\\Save As\\File Name MRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\Common\\Open Find\\Microsoft Office Excel\\Settings\\Open\\File Name MRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\Common\\Open Find\\Microsoft Office Excel\\Settings\\Save As\\File Name MRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\Common\\Open Find\\Microsoft Office Word\\Settings\\Save As\\File Name MRU\n```\n\n### Item MRU keys\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%ITEM% | | Where %ITEM% is a string in the form: \"Item [0-9]+\"\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\Excel\\File MRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\Excel\\Options\\MRUFuncs\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\PowerPoint\\File MRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\PowerPoint\\RecentAnimationList\\EntranceMRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\PowerPoint\\RecentAnimationList\\EmphasisMRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\PowerPoint\\RecentAnimationList\\ExitMRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\PowerPoint\\RecentAnimationList\\MotionPathMRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\PowerPoint\\Slide Libraries\\Taskpane MRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\12.0\\Word\\File MRU\n```\n\nEvery %ITEM% value contains:\n\nin Office 12\n\n```\n[F00000000][T%FILETIME%]*\\\\%FILENAME%\n```\n\nin Office 14\n\n```\n[F00000000][T%FILETIME%][O00000000]*%FILENAME%\n```\n\nWhere T%FILETIME% contains a FILETIME timestamp as a hexadecimal string (base-16), in upper case, e.g. T01CD10EC460129A0\n\n### Other MRU keys\n\nFind Contact toolbar button (Outlook 97 – 2003)\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\%VERSION%\\Outlook\\Contact\\QuickFindMRU\\QuickfindMRU\n```\n\nFind Pane’s Look in list\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\%VERSION%\\Outlook\\Contact\\StripSearchMRU\\StripSearchMRU\n```\n\nAppointment Locations\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\%VERSION%\\Outlook\\Preferences\\LocationMRU\n```\n\nAdvanced Find’s Search for Word(s)\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\%VERSION%\\Outlook\\Office Finder\\MRU 1\n```\n\nAdvanced Find’s More Choices, Categories\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\%VERSION%\\Outlook\\Office Finder\\MRU 3\n```\n\nChoose Form dialog (New Item-> More Items-> Choose Form) (Outlook 2010 – 2013)\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Office\\%VERSION%\\Outlook\\Office \n```\n\n## External links\n\n* [Administering the offline address book in Outlook](https://support.microsoft.com/en-us/topic/administering-the-offline-address-book-in-outlook-51958cc8-684a-83f9-aea5-97d4dddc0af4)\n\n"
  },
  {
    "path": "docs/sources/application-keys/Terminal-server-client.md",
    "content": "# Terminal server client\n\nThe most recent used (MRU) connnections of the Terminal server client can\nbe found in the key:\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client\\Default\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nMRU# | REG_SZ | The most recently used connection. <br> Where # is a string in the form: \"[0-9]+\"\n\nThe contents of MRU# is either an IP address, e.g. 192.168.16.60, or a hostname, e.g. computer.domain.com.\n\n## External Links\n\n* [How to Remove Entries from the Remote Desktop Connection Computer Box](https://learn.microsoft.com/en-us/troubleshoot/windows-server/remote/remove-entries-from-remote-desktop-connection-computer)\n\n"
  },
  {
    "path": "docs/sources/application-keys/WinRAR.md",
    "content": "# WinRAR\n\n**TODO this page currently contains rough notes, fine tune these**\n\nThe WinRAR application uses the following Windows Registry key to store various\nuser specific information.\n\n```\nHKEY_CURRENT_USER\\Software\\WinRAR\\ArcHistory\nHKEY_CURRENT_USER\\Software\\WinRAR\\DialogEditHistory\\ArcName\nHKEY_CURRENT_USER\\Software\\WinRAR\\DialogEditHistory\\ExtrPath\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%ITEM% | REG_SZ | Where %ITEM% is a string in the form: \"[0-9]+\"\n\n"
  },
  {
    "path": "docs/sources/application-keys/index.rst",
    "content": "################\nApplication keys\n################\n\n.. toctree::\n   :maxdepth: 1\n\n   7-Zip <7-Zip>\n   CCleaner <CCleaner>\n   Microsoft Office <Microsoft-Office>\n   Terminal server client <Terminal-server-client>\n   WinRAR <WinRAR>\n"
  },
  {
    "path": "docs/sources/explorer-keys/Bit-bucket.md",
    "content": "# Bit bucket\n\nThe Windows Explorer bit bucket key contains Recycler configuration\nproperties and information about the Recycler of connected volumes.\n\n```\nHKEY_CURRENT_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\BitBucket\n```\n\nSeen on Windows 2000, XP and 2003.\n\nSub keys:\n\nName | Description\n--- | ---\n%NAME% | Where %NAME% contains a drive letter, for example \"c\"\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nNoRecycleFiles | REG_DWORD | \nNukeOnDelete | REG_DWORD | \nPercent | REG_DWORD | \nUseGlobalSettings | REG_DWORD | \n\n## BitBucket\\\\%NAME% sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nIsUnicode | REG_DWORD | \nVolumeSerialNumber | REG_DWORD | \n\n"
  },
  {
    "path": "docs/sources/explorer-keys/Control-panel-item-identifiers.md",
    "content": "# Control panel item identifiers\n\nA control panel item identifier is a GUID that identifies a specific control\npanel item.\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace\\{%GUID%}\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nCategory | REG_DWORD | \n(default) | REG_SZ | Module name of the control panel item\nPreferredPlan | REG_SZ |\n\n"
  },
  {
    "path": "docs/sources/explorer-keys/Delegate-folders.md",
    "content": "# Delegate folders keys\n\nWindows explorer uses delegate folders to provide alternative graphical\nrepresentations.\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\*\\NameSpace\\DelegateFolders\\{%GUID%}\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n(default) | REG_SZ | Name (or description) of the delegate folder.\n\n## External links\n\n* [DELEGATEITEMID structure (shobjidl_core.h)](https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/ns-shobjidl_core-delegateitemid)\n\n"
  },
  {
    "path": "docs/sources/explorer-keys/Known-folder-identifiers.md",
    "content": "# Known folder identifier keys\n\nA known folder identifier is a GUID that identifies a system folder. It was\nintroduced in Windows Vista to replace the constant special item identifier list\n(CSIDL).\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FolderDescriptions\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nAttributes | REG_DWORD | \nCategory | REG_DWORD | \nName | REG_SZ | Name of the known folder\nLocalizedName | REG_EXPAND_SZ | Localized name of the known folder\nParentFolder | REG_SZ | Path of the parent directory known folder, can contain a known folder identifier\nPreCreate | REG_DWORD | \nRelativePath | REG_SZ | Relative path of the known folder\n\n### LocalizedName value data\n\nThe LocalizedName value contains a localized version of the folder name, e.g.\non Windows XP the folder identifier key:\n\n```\nHKEY_CLASSES_ROOT\\CLSID\\{450d8fba-ad25-11d0-98a8-0800361b1103}\n```\n\nHas a LocalizedString value with the following data:\n\n```\n@%SystemRoot%\\system32\\SHELL32.dll,-9227\n```\n\nWhich is the [MUI Form](https://winreg-kb.readthedocs.io/en/latest/sources/windows-registry/MUI-form.html)\nfor \"My Documents\".\n\n## External links\n\n* [libfwsi: Known Folder Identifiers](https://github.com/libyal/libfwsi/wiki/Known-Folder-Identifiers)\n\n"
  },
  {
    "path": "docs/sources/explorer-keys/MUI-cache.md",
    "content": "# Multilingual User Interface (MUI) cache\n\nSeen on Windows XP and 2003\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache\n```\n\nSeen on Windows Vista and later\n\n```\nHKEY_CURRENT_USER\\Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache\n```\n\n"
  },
  {
    "path": "docs/sources/explorer-keys/Most-recently-used.md",
    "content": "# Most recently used (MRU)\n\nThe Windows Registry contains various keys with information about Most Recently\nfiles Used (MRU). Windows Explorer (or Windows shell), extensively uses such\nkeys. Several different variants of MRU keys are known to be used, such as:\n\n* Keys with a MRUList value\n* Keys with a MRUListEx value\n* BagMRU key\n\n## Keys with a MRUList value\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nMRUList | | Contains a list of the most recently used (MRU) items. <br/> Consists of an array of UTF-16 little-endian formatted character value. <br/> The first value represents the most recently used item, the second the second recently used item and so forth. The last value indicates the end of the list and should be 0 (0x0000).\n%ALPHA% | | Where %ALPHA% is a string in the form: \"[a-z]\" <br/> The value name corresponds to a string value in the MRUList value. E.g. a MRUList value of \"a\" (0x0061) corresponds to the value \"a\".\n\n### String MRUList values\n\nThe following keys with a MRUList value contain %ALPHA% values that consists of\nan UTF-16 little-endian formatted string with an end-of-string character.\n\nSub keys of: `HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\`\n\nRegistry key | Windows version | Description\n--- | --- | ---\nComDlg32\\LastVisitedMRU | 2000, XP |\nComDlg32\\OpenSaveMRU\\%EXTENSION% | 2000, XP | <br/> Where %EXTENSION% is a file extension like \"exe\" or \"\\*\"\nDoc Find Spec MRU | | Most recently used \"Find Files\" commands\nFileExts\\%EXTENSION%\\OpenWithList | 2000, XP, Vista | Most recently used \"Open With\" commands <br/> Where %EXTENSION% is a file extension like \".exe\"\nFindComputerMRU | | Most recently used \"Find Computer\" commands\nMap Network Drive MRU | XP | Most recently used mapped network drives\nPrnPortsMRU | | Most recently used printer ports\nRecentDocs | 2000, XP |\nRecentDocs\\%EXTENSION% | 2000, XP | <br/> Where %EXTENSION% is a file extension like \".exe\" or \"Folder\"\nRunMRU | NT4, 2000, XP, Vista | Most recently used \"Run\" commands\nWordWheelQuery | |\n\n### Shell Item List MRUList values\n\nThe following keys with a MRUList value contain %ALPHA% values that consists of\na Shell Item List.\n\nSub keys of: `HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\`\n\nRegistry key | Windows version | Description\n--- | --- | ---\nDesktopStreamMRU | NT4 | How icons are arranged on the desktop. <br/> Although the key is present on later versions of Windows it does not seem to be used anymore.\n\n## Keys with a MRUListEx value\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nMRUListEx | | Contains a list of the most recently used (MRU) items. <br/> Consists of an array of 4-byte little-endian values. <br/> The first value represents the most recently used item, the second the second recently used item and so forth. The last value indicates the end of the list and should be -1 (0xffffffff).\n%NUMERIC% | | Where %NUMERIC% is a string in the form: \"[0-9]+\" <br/> The value name corresponds to a 4-byte numeric value in the MRUListEx value. E.g. a MRUListEx value of 0x00000001 corresponds to the value named \"1\".\n\nThe value data of the numeric value depends on the sub key.\n\n### String MRUListEx values\n\nThe following keys with a MRUListEx value contain %NUMERIC% values that\nconsists of an UTF-16 little-endian formatted string with an end-of-string\ncharacter.\n\n### Shell Item List MRUListEx values\n\nThe following keys with a MRUListEx value contain %NUMERIC% values that\nconsists of a Shell Item List.\n\nSub keys of: `HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\`\n\nRegistry key | Windows version | Description\n--- | --- | ---\nComDlg32\\OpenSavePidlMRU\\%EXTENSION% | Vista | <br/> Where %EXTENSION% is a file extension like \"exe\" or \"\\*\"\nStreamMRU | 2000, XP |\n\n### String and Shell Item MRUListEx values\n\nThe following keys with a MRUListEx value contain %NUMERIC% values that\nconsists of a String and Shell Item. The String and Shell Item is variable of\nsize and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | ... | | The filename stored as an UTF-16 little-endian formatted string with end-of-string character\n... | ... | | The filename stored as a Shell Item. <br/> The Shell Item is empty if not set.\n\nSub keys of: `HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\`\n\nRegistry key | Windows version | Description\n--- | --- | ---\nRecentDocs | Vista |\nRecentDocs\\%EXTENSION% | Vista | Where %EXTENSION% is a file extension like .exe or Folder\n\n### String and Shell Item List MRUListEx values\n\nThe following keys with a MRUListEx value contain %NUMERIC% values that\nconsists of a String and Shell Item List. The String and Shell Item List is\nvariable of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | ... | | The filename stored as an UTF-16 little-endian formatted string with end-of-string character\n... | ... | | The path stored as a Shell Item List. <br/> The first Shell Item is empty if not set.\n\nSub keys of: `HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\`\n\nRegistry key | Windows version | Description\n--- | --- | ---\nComDlg32\\LastVisitedPidlMRU | Vista, 7 |\n\n## BagMRU key\n\nThe values in the BagMRU and sub keys are also referred to as \"shellbags\".\n\nBagMRU keys as of XP (stored in NTUSER.DAT)\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\BagMRU\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\ShellNoRoam\\BagMRU\n```\n\nAdditional BagMRU keys as of Vista (stored in USRCLASS.DAT)\n\n```\nHKEY_CURRENT_USER\\Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\BagMRU\nHKEY_CURRENT_USER\\Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\ShellNoRoam\\BagMRU\nHKEY_CURRENT_USER\\Software\\Classes\\Wow6432Node\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\BagMRU\nHKEY_CURRENT_USER\\Software\\Classes\\Wow6432Node\\Local Settings\\Software\\Microsoft\\Windows\\ShellNoRoam\\BagMRU\n```\n\nSeen in Windows 7:\n\n```\nHKEY_CURRENT_USER\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\BagMRU\n```\n\nThe BagMRU sub keys form a hierarchy similar to a folder structure.\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nNodeSlot | REG_DWORD | Contains the node slot index number (also referred to as bag number) <br/> This number corresponds to the sub key name the corresponding Bags sub key. <br/> E.g. bag number 1 in HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\BagMRU relates to the Bags sub key HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Bags\\1\nNodeSlots | | Only present in the root BagMRU key.\nMRUListEx | REG_BINARY | Contains a list of the most recently used (MRU) items. <br/> Consists of an array of 4-byte little-endian values. <br/> The first value represents the most recently used item, the second the second recently used item and so forth. The last value indicates the end of the list and should be -1 (0xffffffff).\n%NUMERIC% | REG_BINARY | Where %NUMERIC% is a string in the form: \"[0-9]+\" <br/> The value name corresponds to a 4-byte numeric value in the MRUListEx value. E.g. a MRUListEx value of 0x00000001 corresponds to the value named \"1\". <br/> Contains a shell item\n\n### Bag number shell sub key\n\nThe numbered sub keys of the Bags key have a Shell sub key e.g.\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Bags\\1\\Shell\n```\n\nThis key contains various values:\n\nName | Data type | Description\n--- | --- | ---\nAddress | |\nButtons | |\nCol | |\nColInfo | |\nFolderType | |\nFFlags | |\nHotKey | |\nLinks | |\nMinPos%GEOMETRY%(1).bottom | | Where %GEOMETRY% is the screen geometry in the form 1100x705\nMinPos%GEOMETRY%(1).left | | Where %GEOMETRY% is the screen geometry in the form 1100x705\nMinPos%GEOMETRY%(1).right | | Where %GEOMETRY% is the screen geometry in the form 1100x705\nMinPos%GEOMETRY%(1).top | | Where %GEOMETRY% is the screen geometry in the form 1100x705\nMinPos%GEOMETRY%(1).x | | Where %GEOMETRY% is the screen geometry in the form 1100x705\nMinPos%GEOMETRY%(1).y | | Where %GEOMETRY% is the screen geometry in the form 1100x705\nMode | |\nRev | |\nScrollPos%GEOMETRY%(1).x | | Where %GEOMETRY% is the screen geometry in the form 1100x705\nScrollPos%GEOMETRY%(1).y | | Where %GEOMETRY% is the screen geometry in the form 1100x705\nShowCmd | |\nSort | |\nSortDir | |\nVid | |\nWFlags | |\n\n## Notes\n\nThis section contains some notes on explorer MRU keys that need to be completed.\n\n### Wallpaper MRU key MRUListEx value\n\nSub keys of: `HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\`\n\nRegistry key | Windows version | Description\n--- | --- | ---\nWallpaper\\MRU | XP, 2003 | Most recently used wallpapers\n\n```\n00000000  43 00 3a 00 5c 00 57 00  49 00 4e 00 44 00 4f 00  |C.:.\\.W.I.N.D.O.|\n00000010  57 00 53 00 5c 00 42 00  6c 00 75 00 65 00 20 00  |W.S.\\.B.l.u.e. .|\n00000020  4c 00 61 00 63 00 65 00  20 00 31 00 36 00 2e 00  |L.a.c.e. .1.6...|\n00000030  62 00 6d 00 70 00 00 00  70 00 00 00 00 00 00 00  |b.m.p...p.......|\n00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000050  00 00 00 00 78 01 08 00  00 00 00 00 00 00 00 00  |....x...........|\n00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000080  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n000000a0  00 00 00 00 28 f6 0b 00  00 00 00 00 70 4b 0c 00  |....(.......pK..|\n000000b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n000000c0  00 00 00 00 00 00 00 00  28 f6 0b 00 00 00 00 00  |........(.......|\n000000d0  78 5b 0c 00 00 00 00 00  20 f6 0b 00 00 00 00 00  |x[...... .......|\n000000e0  78 01 08 00 00 00 00 00  00 00 00 00 00 00 00 00  |x...............|\n000000f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000100  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000110  00 00 00 00 00 00 00 00  78 01 08 00 92 02 00 00  |........x.......|\n00000120  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000130  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000150  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000160  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000170  00 00 00 00 00 00 00 00  28 f6 0b 00 00 00 00 00  |........(.......|\n00000180  01 02 00 00 00 00 00 00  68 4b 0c 00 08 10 00 00  |........hK......|\n00000190  68 4b 0c 00 00 00 00 00  70 4b 0c 00 78 01 08 00  |hK......pK..x...|\n000001a0  08 10 00 00 2f 2d f4 77  51 8e e4 77 f8 00 00 00  |..../-.wQ..w....|\n000001b0  00 00 00 00 00 00 00 00  00 00 00 00 50 f4 a2 00  |............P...|\n000001c0  70 4b 0c 00 00 10 00 00  03 00 00 00 28 8d e4 77  |pK..........(..w|\n000001d0  f4 dc 0b 00 36 8e e4 77  04 01 00 00 ab 3d 29 77  |....6..w.....=)w|\n000001e0  40 fd a2 00 00 00 00 00  d6 0f 00 00 a8 4e 0c 00  |@............N..|\n000001f0  00 d0 fd 7f 00 00 00 00  be 20 08 00 01 00 00 00  |......... ......|\n00000200  e0 dc 0b 00 08 00 00 00  30 00 00 00 30 00 00 00  |........0...0...|\n00000210  00 60 a9 0f c6 f2 c2 01                           |.`......|\n```\n\n### Explorer MRUList\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MRU\n```\n\n### CIDSizeMRU MRUListEx\n\nSeen on Windows Vista\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\CIDSizeMRU\n```\n\n```\n00000000  66 00 69 00 72 00 65 00  66 00 6f 00 78 00 2e 00  |f.i.r.e.f.o.x...|\n00000010  65 00 78 00 65 00 00 00  00 00 00 00 00 00 00 00  |e.x.e...........|\n00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n...\n00000200  00 00 00 00 00 00 00 00  12 00 00 00 0b 00 00 00  |................|\n00000210  22 04 00 00 15 03 00 00  00 00 00 00 00 00 00 00  |\"...............|\n00000220  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000230  00 00 00 00 00 00 00 00  1a 00 00 00 27 00 00 00  |............'...|\n00000240  7c 02 00 00 d6 00 00 00  00 00 00 00 00 00 00 00  |...............|\n```\n\nMRUListEx\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\FirstFolder\n```\n\nContains an UTF-16 little-endian formatted string.\n\n## External Links\n\n* [Windows Shell Item format specification](https://github.com/libyal/libfwsi/blob/main/documentation/Windows%20Shell%20Item%20format.asciidoc)\n\n"
  },
  {
    "path": "docs/sources/explorer-keys/Mount-points.md",
    "content": "# Moint points\n\n## MountPoints\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MountPoints\n```\n\nSeen on:\n\n* Windows 2000\n\nSub keys:\n\nName | Description\n--- | ---\n%NAME% | Where %NAME% contains the name of the mount point (or drive mapping).\n\nWhere the following forms of %NAME% have been observed:\n\n* Drive letter, for example \"C\"\n\n### MountPoints name sub key\n\nSub keys:\n\nName | Description\n--- | ---\n`_Autorun` |\n`_DIL` |\n`_LabelFromReg` |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n`_UB` | REG_BINARY | \nBaseClass | REG_SZ | \nVersion | REG_DWORD | \n\n## MountPoints2\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MountPoints2\n```\n\nSeen on:\n\n* Windows XP\n* Windows 2003\n* Windows Vista\n* Windows 2008\n* Windows 7\n* Windows 8.0\n* Windows 8.1\n* Windows 10\n\nSub keys:\n\nName | Description\n--- | ---\nCPC | (Introduced in Windows Vista?)\nCPC\\LocalMOF | (Introduced in Windows 7?)\nCPC\\Volume | (Introduced in Windows Vista?)\n%NAME% | Where %NAME% contains the name of the mount point (or drive mapping).\n\nWhere the following variants of %NAME% have been observed:\n\n* Drive letter, for example \"C\"\n* Volume identifier (GUID), for example \"{01234567-89ab-cdef-0123-456789abcdef}\"\n* UNC path, for example \"##1.2.3.4#username\"\n\n### MountPoints2 name sub key\n\nSub keys:\n\nName | Description\n--- | ---\n`_Autorun` |\n`_Autorun\\Action` |\n`_Autorun\\DefaultIcon` |\n`_Autorun\\DefaultLabel` |\nShell |\nShell\\Autoplay |\nShell\\Autoplay\\DropTarget |\nShell\\AutoRun |\nShell\\AutoRun\\Command |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nBaseClass | REG_SZ | \n\n"
  },
  {
    "path": "docs/sources/explorer-keys/Program-cache.md",
    "content": "# Program cache\n\nThe Windows explorer ProgramsCache Registry values can be stored in\nthe following Windows Registry keys.\n\n* Explorer\\\\StartPage key\n* Explorer\\\\StartPage2 key\n\n## Explorer\\\\StartPage key\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage\n```\n\nSeen in Windows XP, 2003 and Vista.\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nProgramsCache | REG_BINARY | All the started the programs. <br> <mark style=\"background-color: yellow\">**Contains a Jump list?**</mark>\n\n## Explorer\\\\StartPage2 key\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage2\n```\n\nSeen in Windows 7.\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nProgramsCache | REG_BINARY | All the started the programs. <br> <mark style=\"background-color: yellow\">**Contains a Jump list?**</mark>\nProgramsCacheSMP | REG_BINARY | The applications pinned to the Start Menu. <br> Contains a Jump list.\nProgramsCacheTBP | REG_BINARY | The applications pinned to the Taskband. <br> Contains a Jump list.\n\nNote that the format of the ProgramsCache value data slightly differs from that\nof the ProgramsCacheSMP and ProgramsCacheTBP value data.\n\n## ProgramsCache value data format\n\nProgramsCacheSMP - Empty list\n\n```\n00000000  01 00 00 00                                       |.........|\n00000000              00 00 00 00                           |.........|\n00000000                           02                       |.........|\n```\n\nProgramsCacheTBP\n\n```\n0x00000000  01 00 00 00 0b 00 00 00  01 aa 02 00 00           ................\n\n0x00000000  01 00 00 00 07 00 00 00  01 0e 03 00 00           ................\n\n00000000  01 00 00 00                                       |................|\nnumber of entries?\n00000000              0e 00 00 00                           |................|\nstart of entry marker?\n00000000                           01                       |................|\nrelative offset to next entry?\n00000000                              f2 02 00 00           |................|\n00000000                                          14 00 1f  |................|\n\nshell item list\n00000010  80 c8 27 34 1f 10 5c 10  42 aa 03 2e e4 52 87 d6  |..'4..\\.B....R..|\n...\n000002f0  00 78 00 65 00 00 00 00  00 00 00 1c 00           |.x.e............|\nend of list?\n000002f0                                          00 00     |.x.e............|\nstart of entry marker?\n000002f0                                                01  |.x.e............|\n00000300  3c 02 00 00                                       |<........'4..\\.B|\n\nshell item list\n00000300              14 00 1f 80  c8 27 34 1f 10 5c 10 42  |<........'4..\\.B|\n...\n00000bb0  4f 00 4b 00 2e 00 45 00  58 00 45 00 00 00 00 00  |O.K...E.X.E.....|\n00000bc0  00 00 1c 00                                       |.......|\nend of list?\n00000bc0              00 00                                 |.......|\n00000bc0                    02                              |.......|\n```\n\nStartPage2\\ProgramsCache\n\n```\nWindow 7\n00000000  13 00 00 00 c3 53 5b 62  48 ab c1 4e ba 1f a1 ef  |.....S[bH..N....|\n00000010  41 46 fc 19 00 80 00 00  00                       |AF.......~.1....|\n\nshell item list?\n00000010                              7e 00 31 00 00 00 00  |AF.......~.1....|\n00000020  00 6a 3d 6c 3e 11 00 50  72 6f 67 72 61 6d 73 00  |.j=l>..Programs.|\n00000030  00 66 00 08 00 04 00 ef  be 6a 3d 53 3e 6a 3d 6c  |.f.......j=S>j=l|\n00000040  3e 2a 00 00 00 c1 e2 00  00 00 00 01 00 00 00 00  |>*..............|\n00000050  00 00 00 00 00 3c 00 00  00 00 00 50 00 72 00 6f  |.....<.....P.r.o|\n00000060  00 67 00 72 00 61 00 6d  00 73 00 00 00 40 00 73  |.g.r.a.m.s...@.s|\n00000070  00 68 00 65 00 6c 00 6c  00 33 00 32 00 2e 00 64  |.h.e.l.l.3.2...d|\n00000080  00 6c 00 6c 00 2c 00 2d  00 32 00 31 00 37 00 38  |.l.l.,.-.2.1.7.8|\n00000090  00 32 00 00 00 18 00 00  00                       |.2........<...:.|\n\n00000090                              01 3c 02 00 00        |.2........<...:.|\n\nshell item list?\n00000090                                             3a 02  |.2........<...:.|\n000000a0  32 00 85 05 00 00 30 3f  97 a9 20 00 49 4e 54 45  |2.....0?.. .INTE|\n000000b0  52 4e 7e 31 2e 4c 4e 4b  00 00 b8 00 08 00 04 00  |RN~1.LNK........|\n000000c0  ef be 6a 3d 6c 3e 6a 3d  6c 3e 2a 00 00 00 b8 e3  |..j=l>j=l>*.....|\n\n...\n00012e80  00 00 00 00 00 00 1c 00  00 00 02                 |...........|\n\n\n0x00019890  6d 00 2e 00 65 00 78 00  65 00 00 00 00 00 00 00  m...e.x.e.......\n0x000198a0  20 00 00 00                                        ......9....O.'H\n\nTODO: edge case or remnant data?\n0x000198a0              02 ab 95 39  9e 9c 1f 13 4f b8 27 48   ......9....O.'H\n0x000198b0  b2 4b 6c 71 74 00                                 .Klqt.T...R.1...\n\n0x000198b0                    54 00  00 00 52 00 31 00 00 00  .Klqt.T...R.1...\n0x000198c0  00 00 0c 3d a4 33 11 00  54 61 73 6b 42 61 72 00  ...=.3..TaskBar.\n0x000198d0  3c 00 08 00 04 00 ef be  0c 3d a4 33 0c 3d a4 33  <........=.3.=.3\n0x000198e0  2a 00 00 00 69 ee 00 00  00 00 04 00 00 00 00 00  *...i...........\n```\n\nStartPage\\ProgramsCache\n\n```\nWindows XP and 2003\n00000000  09 00 00 00 0b 00                                 |......V...T.1...|\n\ndata size\n00000000                    56 00  00 00                    |......V...T.1...|\nshell item list\n00000000                                 54 00 31 00 00 00  |......V...T.1...|\n00000010  00 00 04 3b a3 79 11 00  50 72 6f 67 72 61 6d 73  |...;.y..Programs|\n00000020  00 00 3c 00 03 00 04 00  ef be 04 3b 8c 79 04 3b  |..<........;.y.;|\n00000030  a3 79 14 00 26 00 50 00  72 00 6f 00 67 00 72 00  |.y..&.P.r.o.g.r.|\n00000040  61 00 6d 00 73 00 00 00  40 73 68 65 6c 6c 33 32  |a.m.s...@shell32|\n00000050  2e 64 6c 6c 2c 2d 32 31  37 38 32 00 18 00 00 00  |.dll,-21782.....|\n\n00000060  01 d4 00 00 00                                    |.......2.#....;.|\n\n00000060                 d2 00 32  00 23 03 00 00 04 3b a3  |.......2.#....;.|\n00000070  79 20 00 49 4e 54 45 52  4e 7e 31 2e 4c 4e 4b 00  |y .INTERN~1.LNK.|\n00000080  00 42 00 03 00 04 00 ef  be 04 3b a3 79 04 3b a3  |.B........;.y.;.|\n...\n0x000003e0  1c 00 00 00                                       .........T.1....\nsentinel of 0x00 seen before shell item list with more than one shell item?\n0x000003e0              00 b0 00 00  00                       .........T.1....\nshell item list\n0x000003e0                              54 00 31 00 00 00 00  .........T.1....\n0x000003f0  00 04 3b a3 79 11 00 50  72 6f 67 72 61 6d 73 00  ..;.y..Programs.\n...\n0x00001020  00 00 00 00 00 1c 00 00  00                       ................\nunknown data 9 bytes (0x02 end marker?)\n0x00001020                              02 16 00 02 00 00 00  ................\n0x00001030  00 00                                             .........2.....:\ndata size\n0x00001030        01 ea 00 00 00                              .........2.....:\nshell item list\n0x00001030                       e8  00 32 00 1b 06 00 00 3a  .........2.....:\n...\n0x00004a40  00 65 00 78 00 65 00 00  00 00 00 1c 00 00 00     .e.x.e..........\nunknown data 11 bytes\n0x00004a40                                                02  .e.x.e..........\n0x00004a50  10 02 19 00 02 00 00 00  00 00                    ................\n0x00004a50                                 01 ca 00 00 00     ................\n0x00004a50                                                c8  ................\n0x00004a60  00 32 00 42 06 00 00 04  3b 12 7a 20 00 4d 4f 5a  .2.B....;.z .MOZ\n...\n00004b10  00 65 00 66 00 6f 00 78  00 2e 00 65 00 78 00 65  |.e.f.o.x...e.x.e|\n00004b20  00 00 00 00 00 1c 00 00  00                       |..........|\n00004b20                              02                    |..........|\n```\n\n```\nWindows Vista (c3535b62-48ab-c14e-ba1f-a1ef4146fc19 FOLDERID_StartMenu)\n\n0x00000000  0c 00 00 00 c3 53 5b 62  48 ab c1 4e ba 1f a1 ef  .....S[bH..N....\n0x00000010  41 46 fc 19                                       AF...|...z.1....\n0x00000010              00 7c 00 00  00                       AF...|...z.1....\n...\n0x00009fe0  72 00 33 00 32 00 2e 00  65 00 78 00 65 00 00 00  r.3.2...e.x.e...\n0x00009ff0  00 00 00 00 1c 00 00 00                           .........a.O..M.\n\nTODO: edge case or remnant data?\n0x00009ff0                           02 61 ae 4f 05 d8 4d 87  .........a.O..M.\n0x0000a000  47 80 b6 09 02 20 c4 b7  00 02                    G.... ....\n```\n\nValue data header Windows XP and 2003.\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 0x00000009 | Format version\n4 | 2 | 0x000b | <mark style=\"background-color: yellow\">**Unknown**</mark>\n\nValue data header Windows Vista.\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 0x0000000c | Format version\n4 | 16 | | Known folder identifier <br> Contains a GUID <br> c3535b62-48ab-c14e-ba1f-a1ef4146fc19 (FOLDERID_StartMenu)\n20 | 1 | | <mark style=\"background-color: yellow\">**Unknown (sentinel?)**</mark>\n\nProgramsCache value data header Windows 7 and 2008.\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 0x00000013 | Format version\n4 | 16 | | Known folder identifier <br> Contains a GUID <br> c3535b62-48ab-c14e-ba1f-a1ef4146fc19 (FOLDERID_StartMenu)\n20 | 1 | | <mark style=\"background-color: yellow\">**Unknown (sentinel?)**</mark>\n\nProgramsCacheSMP and ProgramsCacheTBP value data header Windows 7 and 2008.\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 0x00000001 | Format version\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n5 | 1 | | <mark style=\"background-color: yellow\">**Unknown (sentinel?)**</mark>\n\nValue data entry.\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | | Entry data size\n4 | ... | | Entry data <br> Contains a shell item list\n... | 1 | | <mark style=\"background-color: yellow\">**Unknown (sentinel?)**</mark> <br> <mark style=\"background-color: yellow\">**Seen 0x00, 0x01, 0x02 (end marker?)**</mark>\n\n<mark style=\"background-color: yellow\">**if sentinel is 0x02 and there is more data then look\nfor 0x00 which should be followed by 02 00 00 00 00 00 01**</mark>\n\n"
  },
  {
    "path": "docs/sources/explorer-keys/Shell-folders.md",
    "content": "# Shell folders\n\nShell Folder identifiers are class identifiers with Shell Folder sub key. In\nthe Windows Registry Some Class identifiers (CLSID) have a ShellFolder sub key\nfor example:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\CLSID\\{%GUID%}\\ShellFolder\n```\n\nWhere {%GUID%} is a GUID in the form: {00000000-0000-0000-0000-000000000000}.\n\nA shell folder can be system or user specific.\n\nSystem shell folders:\n\n```\nHKEY_CURRENT_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\nHKEY_CURRENT_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\nHKEY_CURRENT_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\Backup\n```\n\nWoW64 (Windows 32-bit on Windows 64-bit) system shell folders:\n\n```\nHKEY_CURRENT_MACHINE\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\nHKEY_CURRENT_MACHINE\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\nHKEY_CURRENT_MACHINE\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\Backup\n```\n\nPer-user shell folders:\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%NAME% | REG_SZ or REG_EXPAND_SZ | Path to the corresponding directory\n\n"
  },
  {
    "path": "docs/sources/explorer-keys/Typed-paths.md",
    "content": "# Typed paths\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\TypedPaths\n```\n\nValue| Data type| Description\n--- | --- | ---\n%ITEM% | REG_SZ | Where %ITEM% is a string in the form: \"url[0-9]+\"\n\n"
  },
  {
    "path": "docs/sources/explorer-keys/User-assist.md",
    "content": "# User Assist key\n\nThe User Assist key contains settings and data of programs that were launched\nvia Windows Explorer (explorer.exe).\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Currentversion\\Explorer\\UserAssist\n```\n\nSub keys:\n\nName | Description\n--- | ---\n{%GUID%} | The User Assist logged data\nSettings | Settings to control User Assist logging\n\nNote that the Settings sub key does not exist by default.\n\n## Known GUIDs\n\nGUID | Windows Versions | Description\n--- | --- | ---\n{0D6D4F41-2994-4BA0-8FEF-620E43CD2812} | XP, Vista | *TODO assumed as: IE7*\n{5E6AB780-7743-11CF-A12B-00AA004AE837} | 2000, XP, 2003, Vista | Microsoft Internet Toolbar\n{75048700-EF1F-11D0-9888-006097DEACF9} | 2000, XP, 2003, Vista | ActiveDesktop\n{9E04CAB2-CC14-11DF-BB8C-A2F1DED72085} | 8, 10 |\n{A3D53349-6E61-4557-8FC7-0028EDCEEBF6} | 8, 10 |\n{B267E3AD-A825-4A09-82B9-EEC22AA3B847} | 8 |\n{BCB48336-4DDD-48FF-BB0B-D3190DACB3E2} | 8.1 |\n{CAA59E3C-4792-41A5-9909-6A6A8D32490E} | 8 |\n{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA} | 2008 (R2?), 7, 8, 10 | *TODO assumed as: Application or Executable File Execution*\n{F2A1CB5A-E3CC-4A2E-AF9D-505A7009D442} | 8, 10 |\n{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F} | 2008 (R2?), 7, 8, 10 | *TODO assumed as: Shortcut File Execution*\n{FA99DFC7-6AC2-453A-A5E2-5E2AFF4507BD} | 8, 10 |\n\nNote that the User Assist key does not seem to be present on NT4, therefore this\nfunctionality was likely introduced in Windows 2000.\n\nSometimes more information about the GUID can be found in the key:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Classes\\CLSID\\{%GUID%}\\\n```\n\n## GUID sub key\n\nSub keys:\n\nName | Description\n--- | ---\nCount | Contains the User Assist log entries\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nVersion | REG_DWORD | Indicates the User Assist log format version\n\n### Version value data\n\nValue | Windows Versions\n--- | ---\n3 | 2000, XP, 2003, Vista\n5 | 2008 (R2?), 7, 8\n\n### Count sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%NAME% | REG_SZ | Where %NAME% is obfuscated using a technique described below.\n\nWindows Versions | Obfuscation technique\n--- | ---\n2000, XP, 2003, Vista, 2008 (R2?), 7, 8 | ROT-13 of character values in the ASCII `[A-Za-z]` range. +\nValues outside of this range e.g. `[0-9]` and values outside the basic ASCII range (>= 0x80) are not obfuscated.\n7 beta | Vigenère cipher with key: BWHQNKTEZYFSLMRGXADUJOPIVC\n\n#### Named value\n\nValue | Description\n--- | ---\nUEME_CTLSESSION | Session identifier\nUEME_CTLCUACount:ctor |\nUEME_RUNCPL | Executed control applets (.cpl)\nUEME_RUNPATH | Executed programs\nUEME_RUNPIDL | Programs started via a PIDL (shell item list) e.g. using a Shortcut\nUEME_RUNWMCMD | Programs started via a Run Command\nUEME_UIHOTKEY | Programs started via a Hotkey\nUEME_UIQCUT | Programs started via a Quick Launch menu shortcut\nUEME_UISCUT | Programs started via a Desktop shortcut\nUEME_UITOOLBAR | Programs started via Windows Explorer Toolbar buttons\n\nNote does UEME stand for User Experience Monitoring Element/Extension?\nNote does CTL stand for client?\nNote does CUA stand for current user (file) associations?\n\nWith the exception of the UEME_CTLSESSION value, these values appear to use\na similar data types. The structure of a data type depends on the Version value\nof the GUID sub key. The following versions have been observed:\n\n* version 3, that is used by Windows 2000, XP, 2003 and Vista.\n* version 5, that is used by Windows 2008 (R2?), 7, 8.\n\n#### UEME_CTLSESSION value data\n\n##### UEME_CTLSESSION value data - version 3\n\nThe UEME_CTLSESSION value data - version 3 is 8 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | | Unknown\n4 | 4 | | Current session identifier\n\n##### UEME_CTLSESSION value data - version 5\n\nThe UEME_CTLSESSION value data - version 5 is 1612 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 1 | Unknown (version?)\n4 | 4 | | Unknown\n8 | 4 | | Unknown\n12 | 4 | | Unknown\n16 | ... | | Unknown (array of 3x records at offset 0x10, 0x224, 0x438)\n\nThe UEME_CTLSESSION value data - version 5 record is 532 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | | Unknown\n8 | 4 | | Unknown\n12 | 4 | | Unknown\n16 | ... | | Unknown (UTF-16 little-endian string with end-of-string character)\n... | ... | | Unknown\n\n#### Other value data\n\n##### Other value data - version 3\n\nThe other value data - version 3 is 16 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | | Session identifier\n4 | 4 | | Number of executions\n8 | 8 | | Last execution time, which contains a FILETIME\n\n##### Other value data - version 5\n\nThe other value data - version 5 is 72 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | | Unknown (Seen: 0, -1 (0xffffffff) or 1)\n4 | 4 | | Number or executions\n8 | 4 | | Unknown (sometimes referred to as number of application focuses)\n12 | 4 | | Unknown (sometimes referred to as application focus time, does its meaning differ per GUID?)\n16 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?)\n20 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?)\n24 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?)\n28 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?)\n32 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?)\n36 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?)\n40 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?)\n44 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?)\n48 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?)\n52 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?)\n56 | 4 | | Unknown, sometimes -1 (0xffffffff)\n60 | 8 | | Last execution time, contains a FILETIME or 0 if not set\n68 | 4 | 0 | Unknown (empty value ?)\n\n## Settings sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nNoLog | REG_DWORD | Turn of logging. Set to 1 to disable logging of the User Assist information\nNoEncrypt | REG_DWORD | Turn of obfuscation of %NAME% values. Set to 1 to disable name obfuscation\n\n## External links\n\n* [UserAssist](https://blog.didierstevens.com/programs/userassist), by Didier Stevens\n* [Windows 7 Beta: ROT13 Replaced With Vigenère? Great Joke!](https://blog.didierstevens.com/2009/01/18/quickpost-windows-7-beta-rot13-replaced-with-vigenere-great-joke/)\n* [Windows-userassist-keys](https://www.aldeid.com/wiki/Windows-userassist-keys)\n* [libfwsi: Known Folder Identifiers](https://github.com/libyal/libfwsi/wiki/Known-Folder-Identifiers)\n\n"
  },
  {
    "path": "docs/sources/explorer-keys/index.rst",
    "content": "#####################\nWindows explorer keys\n#####################\n\n.. toctree::\n   :maxdepth: 1\n\n   Bit bucket <Bit-bucket>\n   Control panel item identifiers <Control-panel-item-identifiers>\n   Delegate folders <Delegate-folders>\n   Known folder identifiers <Known-folder-identifiers>\n   Mount points <Mount-points>\n   Most recently used (MRU) <Most-recently-used>\n   Multilingual User Interface (MUI) cache <MUI-cache>\n   Program cache <Program-cache>\n   Shell folders <Shell-folders>\n   Typed paths <Typed-paths>\n   User assist <User-assist>\n"
  },
  {
    "path": "docs/sources/internet-explorer-keys/Browser-helper-objects.md",
    "content": "# Browser helper objects (BHO)\n\n```\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects\n```\n\n"
  },
  {
    "path": "docs/sources/internet-explorer-keys/Policies.md",
    "content": "# Policies\n\nThe Internet Explorer polices are stored in multiple keys.\n\nOrder of application:\n\n1. HKEY_LOCAL_MACHINE policy key (Administrative override)\n1. HKEY_CURRENT_USER policy key\n1. HKEY_CURRENT_USER preference key\n1. HKEY_LOCAL_MACHINE preference key (System default settings)\n\nNote that the location of the HKEY_LOCAL_MACHINE policy and preference key\nis dependent on the usage of WoW64 (Windows 32-bit on Windows 64-bit).\n\nNormal:\n\n1. HKEY_LOCAL_MACHINE\\\\Software\\\\Policies\\\\Microsoft\\\\Internet Explorer\\\\Main\\\\FeatureControl\n1. HKEY_CURRENT_USER\\\\Software\\\\Policies\\\\Microsoft\\\\Internet Explorer\\\\Main\\\\FeatureControl\n1. HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Internet Explorer\\\\Main\\\\FeatureControl\n1. HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Internet Explorer\\\\Main\\\\FeatureControl\n\nWoW64:\n\n1. HKEY_LOCAL_MACHINE\\\\Wow6432Node\\\\Software\\\\Policies\\\\Microsoft\\\\Internet Explorer\\\\Main\\\\FeatureControl\n1. HKEY_CURRENT_USER\\\\Software\\\\Policies\\\\Microsoft\\\\Internet Explorer\\\\Main\\\\FeatureControl\n1. HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Internet Explorer\\\\Main\\\\FeatureControl\n1. HKEY_LOCAL_MACHINE\\\\Wow6432Node\\\\Software\\\\Microsoft\\\\Internet Explorer\\\\Main\\\\FeatureControl\n\n## Policies\n\n```\nHKEY_CURRENT_USER\\Software\\Policies\\Microsoft\\Internet Explorer\n```\n\nValues:\n\nValue | Data type | Description\n--- | --- | ---\nDownload Directory | REG_SZ | The user specific download directory\n\n### Download policies\n\n```\nHKEY_CURRENT_USER\\Software\\Policies\\Microsoft\\Internet Explorer\\Download\n```\n\nValues:\n\nValue | Data type | Description\n--- | --- | ---\nCheckExeSignatures | REG_SZ |\nRunInvalidSignatures | REG_DOWRD |\n\n## Feature controls\n\n### Security Zones\n\nValue | Description\n--- | ---\n0 | My Computer\n1 | Local Intranet Zone\n2 | Trusted sites Zone\n3 | Internet Zone\n4 | Restricted Sites Zone\n\nAlso stored in \"Description\" Registry value in zone-specific Registry key.\n\n### Local Machine Zone Lockdown\n\nApplies the Lockdown Zones instead of the Zones.\n\n```\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_LOCALMACHINE_LOCKDOWN\\\n\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_LOCALMACHINE_LOCKDOWN\\\n\nHKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_LOCALMACHINE_LOCKDOWN\\\n```\n\nAdd a REG_DWORD value to this key named for your application (for example, \nMyApplication.exe) and set it to 1. Any other setting for this value will \ndisable Local Machine Zone Lockdown for the application.\n\n### Network Protocol Lockdown\n\n```\nHKEY_LOCAL_MACHINE\\Software\\(Policies)\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_PROTOCOL_LOCKDOWN \n\nHKEY_CURRENT_USER\\Software\\(Policies)\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_PROTOCOL_LOCKDOWN\n\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_PROTOCOL_LOCKDOWN\n```\n\n### HTML from CD\n\n```\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_LOCALMACHINE_LOCKDOWN\\Settings\\LOCALMACHINE_CD_UNLOCK\n```\n\n## Notes\n\n```\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\nHKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\n```\n\n## External Links\n\n* [About URL Security Zones](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/ms537183(v=vs.85))\n* [Internet Explorer Local Machine Zone Lockdown](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc782928(v=ws.10))\n* [Internet Explorer Network Protocol Lockdown](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc737488(v=ws.10))\n* [Internet Explorer Protected Mode Elevation Policy and Administrative Templates](https://learn.microsoft.com/en-us/archive/blogs/juanand/internet-explorer-protected-mode-elevation-policy-and-administrative-templates)\n* [Internet Explorer security zones registry entries for advanced users](https://learn.microsoft.com/en-us/previous-versions/troubleshoot/browsers/security-privacy/ie-security-zones-registry-entries)\n* [Internet Feature Controls](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/general-info/ee330720(v=vs.85))\n* [Introduction to Feature Controls](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/ms537184(v=vs.85))\n* [Understanding user-agent strings](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/ms537503(v=vs.85))\n\n"
  },
  {
    "path": "docs/sources/internet-explorer-keys/Types-URLs.md",
    "content": "# Typed URLs\n\n....\nHKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\TypedURLs\n....\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%ITEM% | REG_SZ | Where %ITEM% is a string in the form: \"url[0-9]+\"\n\n"
  },
  {
    "path": "docs/sources/internet-explorer-keys/index.rst",
    "content": "######################\nInternet explorer keys\n######################\n\n.. toctree::\n   :maxdepth: 1\n\n   Browser helper objects <Browser-helper-objects>\n   Policies <Policies>\n   Typed URLs <Typed-URLs>\n"
  },
  {
    "path": "docs/sources/security-accounts-manager-keys/Domains.md",
    "content": "# Domains\n\nThe Security Accounts Manager (SAM) domains are stored in the key:\n\n```\nHKEY_LOCAL_MACHINE\\SAM\\SAM\\Domains\n```\n\nSub keys:\n\nName | Description\n--- | ---\nAccount | user, group, and local group accounts.\nBuiltin | built-in local groups, such as the Administrators and Users groups, that are established when the operating system is installed.\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n(default) | |\n\n## Account or Builtin sub key\n\nSub keys:\n\nName | Description\n--- | ---\nAliases |\nGroups |\nUsers |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nF | REG_BINARY |\nV | REG_BINARY |\n\n### F value data\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | ... | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n\n### V value data\n\nThe V value data consists of:\n\n* 17 x user information descriptors\n  * security descriptor\n  * username\n  * full name\n  * comment\n  * user comment\n  * <mark style=\"background-color: yellow\">**Unknown**</mark>\n  * home directory\n  * home directory connect\n  * script path\n  * profile path\n  * workstations\n  * hours allowed\n  * <mark style=\"background-color: yellow\">**Unknown**</mark>\n  * LM hash (LANMAN)\n  * NTLM hash\n  * <mark style=\"background-color: yellow\">**Unknown**</mark>\n  * <mark style=\"background-color: yellow\">**Unknown**</mark>\n* user information data\n\n#### User information descriptor\n\nA user information descriptor is 12 byte of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | | Data offset <br> The offset is relative to the end of the last user information descriptor\n4 | 4 | | Data size\n8 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n\n## Aliases sub key\n\nSub keys:\n\nName | Description\n--- | ---\nMembers |\nNames |\n%RID% |\n\nWhere %RID% is the relative identifier (RID) which corresponds to the last sub authority of the SID.\n\n### Aliases RID sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nC | REG_BINARY |\n\n#### C value data\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | | The relative identifier (RID)\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n8 | 4 | | Size of unknown data at offset 52\n12 | 2 | 2 | <mark style=\"background-color: yellow\">**Unknown: major format version ?**</mark>\n14 | 2 | 1 | <mark style=\"background-color: yellow\">**Unknown: minor format version ?**</mark>\n16 | 4 | | Name string offset <br> Relative from offset 52\n20 | 4 | | Name string size <br> Contains number of bytes\n24 | 4 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n28 | 4 | | Description string offset <br> Relative from offset 52\n32 | 4 | | Description string size <br> Contains number of bytes\n36 | 4 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n40 | 4 | | SID array offset <br> Relative from offset 52\n44 | 4 | | SID array size\n48 | 4 | | SID array number of values\n52 | ... | | Contains an https://code.google.com/p/libfwnt/wiki/SecurityDescriptor[NT security descriptor]\n... | ... | | Name string <br> Contains an UTF-16 little-endian formatted string without end-of-string character <br> The data is stored using 4-byte alignment\n... | ... | | Description string <br> Contains an UTF-16 little-endian formatted string without end-of-string character <br> The data is stored using 4-byte alignment\n... | ... | | SID array <br> Contains Windows NT Security Identifiers (SIDs)\n\n### Aliases Members sub key\n\nSub keys:\n\nName | Description\n--- | ---\n%SID% |\n\nWhere %SID% is the security identifier (SID) in the form of a string e.g. S-1-5.\n\n#### Aliases Members SID sub key\n\nSub keys:\n\nName | Description\n--- | ---\n%RID% |\n\nWhere %RID% is the relative identifier (RID) which corresponds to the last sub authority of the SID.\n\n## Groups sub key\n\nSub keys:\n\nName | Description\n--- | ---\nNames |\n%RID% |\n\n### C value data\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 2 | 2 | <mark style=\"background-color: yellow\">**Unknown: major format version ?**</mark>\n2 | 2 | 1 | <mark style=\"background-color: yellow\">**Unknown: minor format version ?**</mark>\n4 | 4 | | The relative identifier (RID)\n8 | 20 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n28 | 2 | 2 | <mark style=\"background-color: yellow\">**Unknown: major format version ?**</mark>\n30 | 2 | 1 | <mark style=\"background-color: yellow\">**Unknown: minor format version ?**</mark>\n32 | 4 | | Name string offset <br> Relative from offset 68\n36 | 4 | | Name string size <br> Contains number of bytes\n40 | 4 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n44 | 4 | | Description string offset <br> Relative from offset 68\n48 | 4 | | Description string size <br> Contains number of bytes\n52 | 4 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n56 | 4 | | Group member array offset <br> Relative from offset 68\n60 | 4 | | Group member array size <br> Contains number of bytes\n64 | 4 | | Group member array number of values\n68 | ... | | Contains a [security descriptor](https://github.com/libyal/libfwnt/blob/main/documentation/Security%20Descriptor.asciidoc)\n... | ... | | Name string <br> Contains an UTF-16 little-endian formatted string without end-of-string character <br> The data is stored using 4-byte alignment\n... | ... | | Description string <br> Contains an UTF-16 little-endian formatted string without end-of-string character <br> The data is stored using 4-byte alignment\n... | ... | | Group member array <br> Contains 4-byte RID values\n\n## Users sub key\n\nSub keys:\n\nName | Description\n--- | ---\nNames |\n%RID% |\n\nWhere %RID% is the relative identifier (RID) which corresponds to the last sub authority of the SID.\n\n### Users RID sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nF | REG_BINARY |\nV | REG_BINARY |\n\n#### F value data\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 2 | 2 | <mark style=\"background-color: yellow\">**Unknown: major version ?**</mark>\n2 | 2 | 2 | <mark style=\"background-color: yellow\">**Unknown: minor version ?**</mark>\n4 | 2 | | <mark style=\"background-color: yellow\">**Unknown: Extended data flags ?**</mark>\n6 | 2 | | <mark style=\"background-color: yellow\">**Unknown: Extended data size ?**</mark>\n8 | 8 | | Last logon date and time (lastLogon) <br> Contains a FILETIME\n16 | 8 | | <mark style=\"background-color: yellow\">**Unknown (lastLogoff?)**</mark>\n24 | 8 | | Password last set date and time (pwdLastSet) <br> Contains a FILETIME\n32 | 8 | | Account expires date and time (accountExpires) <br> Contains a FILETIME, where 0x7fffffffffffffff represents Never\n40 | 8 | | Last password failure date and time (badPasswordTime) <br> Contains a FILETIME\n48 | 4 | | Relative identifier (UserId) <br> The relative identifier (RID) corresponds to the the last authority of the SID\n52 | 4 | | Primary group identifier (PrimaryGroupId)\n56 | 4 | | User account control flags (UserAccountControl) <br> See section: [User account control flags](#user-account-control-flags)\n60 | 2 | | Country code (countryCode) <br> See section: [Country code](#country-code)\n62 | 2 | | Codepage (codePage)\n64 | 2 | | Number of password failures (badPwdCount)\n66 | 2 | | Number of logons (logonCount)\n68 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n72 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n76 | 4 | | <mark style=\"background-color: yellow\">**Unknown (checksum?)**</mark>\n\nExtended data:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n80 | | |\n\nNote that the relative identifier (RID) is sometimes referred to as user number\nor user identifier.\n\n##### User account control flags\n\nThe user account control flags (or USER_ACCOUNT Codes) are defined in subauth.h\n\nValue | Identifier | Description\n--- | --- | ---\n0x00000001 | USER_ACCOUNT_DISABLED | Account disabled (inactive)\n0x00000002 | USER_HOME_DIRECTORY_REQUIRED | Home directory required\n0x00000004 | USER_PASSWORD_NOT_REQUIRED | User password not required\n0x00000008 | USER_TEMP_DUPLICATE_ACCOUNT | Temporary duplicate account\n0x00000010 | USER_NORMAL_ACCOUNT | Normal user account\n0x00000020 | USER_MNS_LOGON_ACCOUNT | Majority Node Set (MNS) logon user account\n0x00000040 | USER_INTERDOMAIN_TRUST_ACCOUNT | Interdomain trust account\n0x00000080 | USER_WORKSTATION_TRUST_ACCOUNT | Workstation trust account\n0x00000100 | USER_SERVER_TRUST_ACCOUNT | Server trust account <br> Object is a domain controller (DC)\n0x00000200 | USER_DONT_EXPIRE_PASSWORD | User password does not expire\n0x00000400 | USER_ACCOUNT_AUTO_LOCKED | Account auto locked\n0x00000800 | USER_ENCRYPTED_TEXT_PASSWORD_ALLOWED | Encryped text password is allowed\n0x00001000 | USER_SMARTCARD_REQUIRED | Smart Card required\n0x00002000 | USER_TRUSTED_FOR_DELEGATION | Trusted for Delegation\n0x00004000 | USER_NOT_DELEGATED | Not delegated\n0x00008000 | USER_USE_DES_KEY_ONLY | Use DES key only\n0x00010000 | USER_DONT_REQUIRE_PREAUTH | Preauth not required\n0x00020000 | USER_PASSWORD_EXPIRED | Password Expired\n0x00040000 | USER_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION | Used by Kerberos see MS-KILE\n0x00080000 | USER_NO_AUTH_DATA_REQUIRED | Used by Kerberos see RFC4120\n0x00100000 | USER_PARTIAL_SECRETS_ACCOUNT | Partial secrets account <br> Object is a read-only domain controller (RODC)\n0x00200000 | USER_USE_AES_KEYS | Use AES keys\n\nNote that these flags differ from ADS_USER_FLAG_ENUM. Mappings between the two\nare defined in \"MS-SAMR: userAccountControl Mapping Table\".\n\nNote that the samba project defines these as flags with the WBC_ACB prefix,\nwhere WBC is short for winbind client.\n\n##### Country code\n\n<mark style=\"background-color: yellow\">**Unknown. Is this suppose to be the country phone prefix?**</mark>\n\nValue | Description\n--- | ---\n000 | System Default\n001 | United States\n002 | Canada (French)\n003 | Latin America\n031 | Netherlands\n032 | Belgium\n033 | France\n034 | Spain\n039 | Italy\n041 | Switzerland\n044 | United Kingdom\n045 | Denmark\n046 | Sweden\n047 | Norway\n049 | Germany\n061 | Australia\n081 | Japan\n082 | Korea\n086 | China (PRC)\n088 | Taiwan\n099 | Asia\n351 | Portugal\n358 | Finland\n785 | Arabic\n972 | Hebrew\n\n#### V value data\n\n### Account types\n\nValue | Identifier | Description\n--- | --- | ---\n0x00000000 | SAM_DOMAIN_OBJECT | Represents a domain object\n0x10000000 | SAM_GROUP_OBJECT | Represents a group object\n0x10000001 | SAM_NON_SECURITY_GROUP_OBJECT | Represents a group object that is not used for authorization context generation\n0x20000000 | SAM_ALIAS_OBJECT | Represents an alias object\n0x20000001 | SAM_NON_SECURITY_ALIAS_OBJECT | Represents an alias object that is not used for authorization context generation\n0x30000000 | SAM_USER_OBJECT | Represents a user object\n0x30000001 | SAM_MACHINE_ACCOUNT | Represents a computer object\n0x30000002 | SAM_TRUST_ACCOUNT | Represents a user object that is used for domain trusts\n0x40000000 | SAM_APP_BASIC_GROUP | Represents an application-defined group\n0x40000001 | SAM_APP_QUERY_GROUP | Represents an application-defined group whose members are determined by the results of a query\n\n### Predefined RIDs\n\nValue | Identifier | Description\n--- | --- | ---\n0x000001f4 | DOMAIN_USER_RID_ADMIN | User: Administrator\n0x000001f5 | DOMAIN_USER_RID_GUEST | User: Guest\n0x000001f6 | DOMAIN_USER_RID_KRBTGT | User: krbtgt (Key Distribution Center Service)\n0x00000201 | DOMAIN_GROUP_RID_USERS | Group: Domain Users\n0x00000203 | DOMAIN_GROUP_RID_COMPUTERS | Group: Domain Computers\n0x00000204 | DOMAIN_GROUP_RID_CONTROLLERS | Group: Domain Controllers\n0x00000220 | DOMAIN_ALIAS_RID_ADMINS | Group: Administrators\n0x00000209 | DOMAIN_GROUP_RID_READONLY_CONTROLLERS | Group: Read-only Domain Controllers\n\n## External Links\n\n* [ACCOUNT_TYPE Values](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/e742be45-665d-4576-b872-0bc99d1e1fbe)\n* [Built-in and Account Domains](https://learn.microsoft.com/en-us/windows/win32/secmgmt/built-in-and-account-domains)\n* [Predefined RIDs](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/565a6584-3061-4ede-a531-f5c53826504b)\n* [SAMPR_USER_ALL_INFORMATION](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/dc966b81-da27-4dae-a28c-ec16534f1cb9)\n* [Security Account Manager (SAM)](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc756748(v=ws.10))\n* [SysKey and the SAM](https://moyix.blogspot.com/2008/02/syskey-and-sam.html), by Brendan Dolan-Gavitt, February 21, 2008\n* [USER_ACCOUNT Codes](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/b10cfda1-f24f-441b-8f43-80cb93e786ec)\n* [userAccountControl Mapping Table](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/8a193181-a7a2-49df-a8b1-f689aaa6987c)\n* [USER_ALL_INFORMATION structure](https://learn.microsoft.com/en-us/windows/win32/api/subauth/ns-subauth-user_all_information)\n* [Well-known SIDs](https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids)\n\n"
  },
  {
    "path": "docs/sources/security-accounts-manager-keys/Security-accounts-manager.md",
    "content": "# Security Accounts Manager (SAM)\n\nThe Security Accounts Manager (SAM) is stored in the key:\n\n```\nHKEY_LOCAL_MACHINE\\SAM\\SAM\n```\n\nSub keys:\n\nName | Description\n--- | ---\nDomains | Built-in and account domains\nRXACT |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nC | REG_BINARY |\n\n### C value data\n\nThe C value data is variable of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 2 | | <mark style=\"background-color: yellow\">**Unknown (Format version?)**</mark>\n2 | 2 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown (empty?)**</mark>\n8 | 4 | | Security descriptor data size\n12 | 2 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n14 | 2 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n16 | ... | | Security descriptor data\n\n#### Format version\n\nValue | Description\n--- | ---\n1 | Used in Windows NT 3.1\n2 | Used in Windows NT 3.5\n3 | Used in Windows NT 4\n6 | Used in Windows 2000\n7 | Used in Windows XP and later\n9 | Used in Windows Windows 11\n\n"
  },
  {
    "path": "docs/sources/security-accounts-manager-keys/index.rst",
    "content": "##############################\nSecurity accounts manager keys\n##############################\n\n.. toctree::\n   :maxdepth: 1\n\n   Security accounts manager <Security-accounts-manager>\n   Domains <Domains>\n"
  },
  {
    "path": "docs/sources/system-keys/Application-compatibility-cache.md",
    "content": "# Application compatibility cache\n\nThe Application compatibility cache can be found in the following Windows\nRegistry keys.\n\nIn Windows 2000 and XP:\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCompatibility\n```\n\nIn Windows 2003 and later:\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCompatCache\n```\n\nNote that several sources claim that the Application Compatibility Cache is\npart of the [Application Compatibility Database](https://learn.microsoft.com/en-us/windows/win32/devnotes/application-compatibility-database).\nHowever unfortunately these claims are not backed by sources or facts. Since\nthe previous article does not mention the relationship between the cache and\nthe database, this document the Application Compatibility Cache to part of\nthe Windows Application Compatibility subsystem instead.\n\nNote that the actual difference between the Application Compatibility Cache\nand Shim (Database) Cache is currently unknown. Be aware that in other sources\nthe terms can be used interchangeable. Since MSDN explicitly defines\nBaseFlushAppcompatCache and ShimFlushCache, there is likely a subtle difference\nto what data is cached. Also see: [Understanding Shims](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-7/dd837644(v=ws.10)).\n\n## Windows 2000\n\nWindows 2000 stores Application Compatibility related data in subkeys in:\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCompatibility\n```\n\nAt this time it is unclear if these subkeys serve the same purpose as the\nAppCompatCache value in later versions of Windows.\n\nThe subkeys are named as the executable files e.g. `Uninstall.exe` and have been\nseen to contain the following values:\n\nName | Data type | Description\n--- | --- | ---\n%NAME% | | <mark style=\"background-color: yellow\">**Unknown (seen: x, 462)**</mark>\nDllPatch-%NAME% | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n\nAlso seen values named like `00008 WindowsNT4.0`.\n\n### Windows 2000 unknown value\n\nThe Windows 2000 unknown value is variable of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 0x0000000c | <mark style=\"background-color: yellow\">**Unknown 1 (header size?)**</mark>\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown 2 (empty values)**</mark>\n8 | 4 | | <mark style=\"background-color: yellow\">**Unknown 3**</mark>\n12 | 4 | | <mark style=\"background-color: yellow\">**Unknown 4**</mark>\n\nContains additional data if \"Unknown 4 > 0\"\n\n```\nEmpty?\n00000000  0c 00 00 00 00 00 00 00  06 00 00 00 00 00 00 00  |................|\n\nWith data:\n00000000  0c 00 00 00 00 00 00 00  06 00 00 00 04 00 00 00  |................|\n\n00000010  10 00 00 00 00 00 00 00  00 00 15 00 ff ff ff ff  |................|\n00000020  ff ff ff ff 0f 00 00 00                           |........(...A.u.|\n\nSting byte size followed by string:\n00000020                           28 00 00 00 41 00 75 00  |........(...A.u.|\n00000030  74 00 6f 00 43 00 41 00  44 00 20 00 41 00 70 00  |t.o.C.A.D. .A.p.|\n00000040  70 00 6c 00 69 00 63 00  61 00 74 00 69 00 6f 00  |p.l.i.c.a.t.i.o.|\n00000050  6e 00 00 00                                       |n.......|\n\n00000050              00 00 00 00                           |n.......|\n```\n\n### Windows 2000 DllPatch value\n\nThe Windows 2000 DllPatch value is variable of size and contains an UTF-16\nlittle-endian formatted string with end-of-string character e.g. 'shcmn.dll 7'.\n\n<mark style=\"background-color: yellow\">**It is currently unclear what the trailing number represents.**</mark>\n\n## Windows XP\n\nWindows XP stores the application compatibility cache in the value:\nAppCompatCache.\n\nThe value data consists of:\n\n* header\n  * array of LRU cache entry index values\n* array of cache entries (suggested that the maximum is 92)\n\nNote that 64-bit versions of Windows XP will use the Windows 2003 64-bit format.\n\n### Windows XP application compat cache header\n\nThe Windows XP application compat cache header is 400 bytes of size and\nconsists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 0xef, 0xbe, 0xad, 0xde | Signature\n4 | 4 | | Number of cached entries\n8 | 4 | | Number of LRU array entries\n12 | 4 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n16 | ... | | LRU array <br> Contains 32-bit value of the index within the array of cache entries <br> <mark style=\"background-color: yellow\">**Currently it is unclear if the top or the bottom of the array is the LRU**</mark>\n... | ... | | <mark style=\"background-color: yellow\">**Unknown (padding?)**</mark> <br> Contains 0-byte values\n\n### Windows XP 32-bit application compat cache entry\n\nThe Windows XP 32-bit application compat cache entry is 552 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 2 x ( MAX_PATH + 4 ) = 528 | | Path <br> UTF-16 little-endian string with end-of-character <br> Note that the unused bytes can contain remnant data\n528 | 8 | | Last modification time <br> Contains a FILETIME\n536 | 8 | | File size\n544 | 8 | | Last update time <br> Contains a FILETIME\n\nNote that the last modification time applies to that of the file e.g. for NTFS\nthis is the last modified time of the file as stored in the\n$STANDARD_INFORMATION attribute.\n\n## Windows 2003\n\nWindows 2003 stores the application compatibility cache in the value: AppCompatCache\n\nThe value data consists of:\n\n* header\n* array of cache entries (suggested that the maximum is 512)\n* string data\n\n### Windows 2003 application compat cache header\n\nThe Windows 2003 application compat cache header is 8 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 0xfe, 0x0f, 0xdc, 0xba | Signature\n4 | 4 | | Number of cached entries\n\n### Windows 2003 32-bit application compat cache entry\n\nThe Windows 2003 32-bit application compat cache entry is 24 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 2 | | Path size\n2 | 2 | | Maximum path size\n4 | 4 | | Path offset <br> The offset value is relative to the start of the header\n8 | 8 | | Last modification time <br> Contains a FILETIME\n16 | 8 | | File size\n\nNote that the last modification time applies to that of the file e.g. for NTFS\nthis is the last modified time of the file as stored in the\n$STANDARD_INFORMATION attribute.\n\n### Windows 2003 64-bit application compat cache entry\n\nThe Windows 2003 64-bit application compat cache entry is 32 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 2 | | Path size\n2 | 2 | | Maximum path size\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown (padding)**</mark>\n8 | 8 | | Path offset <br> The offset value is relative to the start of the header\n16 | 8 | | Last modification time <br> Contains a FILETIME\n24 | 8 | | File size\n\nNote that the last modification time applies to that of the file e.g. for NTFS\nthis is the last modified time of the file as stored in the\n$STANDARD_INFORMATION attribute.\n\n## Windows Vista and 2008\n\nWindows Vista and 2008 store the application compatibility cache in the value: AppCompatCache\n\nThe value data consists of:\n\n* header\n* array of cache entries (suggested that the maximum is 1024)\n* string data\n\n[NOTE]\nIf the cache is empty it will only consists of a header.\n \n### Windows Vista application compat cache header\n\nThe Windows Vista application compat cache header is 8 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 0xfe, 0x0f, 0xdc, 0xba | Signature\n4 | 4 | | Number of cached entries\n\n### Windows Vista 32-bit application compat cache entry\n\nThe Windows Vista 32-bit application compat cache entry is 24 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 2 | | Path size\n2 | 2 | | Maximum path size\n4 | 4 | | Path offset <br> The offset value is relative to the start of the header\n8 | 8 | | Last modification time <br> Contains a FILETIME\n16 | 4 | | Insertion flags\n20 | 4 | | Shim flags\n\nNote that the last modification time applies to that of the file e.g. for NTFS\nthis is the last modified time of the file as stored in the\n$STANDARD_INFORMATION attribute.\n\n### Windows Vista 64-bit application compat cache entry\n\nThe Windows Vista 64-bit application compat cache entry is 32 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 2 | | Path size\n2 | 2 | | Maximum path size\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown (padding)**</mark>\n8 | 8 | | Path offset <br> The offset value is relative to the start of the header\n16 | 8 | | Last modification time <br> Contains a FILETIME\n24 | 4 | | Insertion flags\n28 | 4 | | Shim flags\n\nNote that the last modification time applies to that of the file e.g. for NTFS\nthis is the last modified time of the file as stored in the\n$STANDARD_INFORMATION attribute.\n\n## Windows 7 and 2008 R2\n\nWindows 7 and 2008 R2 store the application compatibility cache in the value: AppCompatCache\n\nThe value data consists of:\n\n* header\n* array of cache entries (suggested that the maximum is 1024)\n* data\n* string data\n\n### Windows 7 application compat cache header\n\nThe Windows 7 application compat cache header is 128 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 0xee, 0x0f, 0xdc, 0xba | Signature\n4 | 4 | | Number of cached entries\n8 | 4 | 120 | <mark style=\"background-color: yellow\">**Unknown (size?)**</mark>\n12 | 116 | | <mark style=\"background-color: yellow\">**Unknown (cache statistics?)**</mark>\n\n### Windows 7 32-bit application compat cache entry\n\nThe Windows 7 32-bit application compat cache entry is 32 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 2 | | Path size <br> The byte of the path without the end-of-string character\n2 | 2 | | Maximum path size <br> The byte of the path with the end-of-string character\n4 | 4 | | Path offset <br> The offset value is relative to the start of the header\n8 | 8 | | Last modification time <br> Contains a FILETIME\n16 | 4 | | Insertion flags\n20 | 4 | | Shim flags\n24 | 4 | | Data size\n28 | 4 | | Data offset <br> The offset value is relative to the start of the header\n\nNote that the last modification time applies to that of the file e.g. for NTFS\nthis is the last modified time of the file as stored in the\n$STANDARD_INFORMATION attribute.\n\n### Windows 7 64-bit application compat cache entry\n\nThe Windows 7 64-bit application compat cache entry is 48 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 2 | | Path size <br> The byte of the path without the end-of-string character\n2 | 2 | | Maximum path size <br> The byte of the path with the end-of-string character\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown (padding)**</mark>\n8 | 8 | | Path offset <br> The offset value is relative to the start of the header\n16 | 8 | | Last modification time <br> Contains a FILETIME\n24 | 4 | | Insertion flags\n28 | 4 | | Shim flags\n32 | 8 | | Data size\n40 | 8 | | Data offset <br> The offset value is relative to the start of the header\n\nNote that the last modification time applies to that of the file e.g. for NTFS\nthis is the last modified time of the file as stored in the\n$STANDARD_INFORMATION attribute.\n\n## Windows 8\n\nWindows 8 store the application compatibility cache in the value: AppCompatCache\n\nThe value data consists of:\n\n* header\n* array of cache entries\n\n### Windows 8 application compat cache header\n\nThe Windows 8 application compat cache header is 128 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 128 | Header size (or cache entry array offset)\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n8 | 120 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n\n### Windows 8.0 application compat cache entry\n\nThe Windows 8.0 application compat cache entry is variable bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | \"00ts\" | Signature\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n8 | 4 | | Cache entry data size <br> The size of the cache entry without the first 12 bytes\n12 | 2 | | Path size\n14 | ... | | Path <br> UTF-16 little-endian string without end-of-character\n... | 4 | | <mark style=\"background-color: yellow\">**Unknown (Insertion flags?)**</mark>\n... | 4 | | <mark style=\"background-color: yellow\">**Unknown (Shim flags?)**</mark>\n... | 8 | | Last modification time <br> Contains a FILETIME\n... | 4 | | Data size\n... | ... | | Data\n\nNote that the last modification time applies to that of the file e.g. for NTFS\nthis is the last modified time of the file as stored in the\n$STANDARD_INFORMATION attribute.\n\n### Windows 8.1 application compat cache entry\n\nThe Windows 8.1 application compat cache entry is variable bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | \"10ts\" | Signature\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n8 | 4 | | Cache entry data size <br> The size of the cache entry without the first 12 bytes\n12 | 2 | | Path size\n14 | ... | | Path <br> UTF-16 little-endian string without end-of-character\n... | 4 | | <mark style=\"background-color: yellow\">**Unknown (Insertion flags?)**</mark>\n... | 4 | | <mark style=\"background-color: yellow\">**Unknown (Shim flags?)**</mark>\n... | 2 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n... | 8 | | Last modification time <br> Contains a FILETIME\n... | 4 | | Data size\n... | ... | | Data\n\nNote that the last modification time applies to that of the file e.g. for NTFS\nthis is the last modified time of the file as stored in the\n$STANDARD_INFORMATION attribute.\n\n## Windows 10\n\nWindows 10 store the application compatibility cache in the value: AppCompatCache\n\nThe value data consists of:\n\n* header\n* array of cache entries\n\n### Windows 10 application compat cache header\n\nThe Windows 10 application compat cache header is 48 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 48 | Header size (or cache entry array offset)\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n8 | 4 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n12 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n16 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n20 | 16 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n36 | 4 | | Number of cached entries\n40 | 8 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n\nThe Windows 10 Creator update application compat cache header is 52 bytes of\nsize and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 52 | Header size (or cache entry array offset)\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n8 | 4 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n12 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n16 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n20 | 8 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n28 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n32 | 8 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n40 | 4 | | Number of cached entries\n44 | 8 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n\n### Windows 10 application compat cache entry\n\nThe Windows 10 application compat cache entry is variable bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | \"10ts\" | Signature\n4 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n8 | 4 | | Cache entry data size <br> The size of the cache entry without the first 12 bytes\n12 | 2 | | Path size\n14 | ... | | Path <br> UTF-16 little-endian string without end-of-character\n... | 8 | | Last modification time <br> Contains a FILETIME\n... | 4 | | Data size\n... | ... | | Data\n\nNote that the last modification time applies to that of the file e.g. for NTFS\nthis is the last modified time of the file as stored in the\n$STANDARD_INFORMATION attribute.\n\n## Insertion flags\n\n<mark style=\"background-color: yellow\">**TODO describe**</mark>\n\nValue | Identifier | Description\n--- | --- | ---\n0x00000001 | |\n0x00000002 | | <mark style=\"background-color: yellow\">**Indicated as executed by CSRSS.EXE flag**</mark> <br> <mark style=\"background-color: yellow\">**Client/Server Runtime Subsystem (CSRSS)**</mark>\n0x00000004 | |\n0x00000008 | |\n0x00000010 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.0, 8.1)**</mark>\n0x00000020 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.0, 8.1)**</mark>\n0x00000040 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.0, 8.1)**</mark>\n0x00000080 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.0, 8.1)**</mark>\n| |\n0x00010000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.1)**</mark>\n0x00020000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.1)**</mark>\n0x00030000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.1)**</mark>\n0x00040000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.1)**</mark>\n0x00100000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.1)**</mark>\n0x00200000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.1)**</mark>\n0x00400000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.1)**</mark>\n0x00800000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.1)**</mark>\n\n## Shim flags\n\n<mark style=\"background-color: yellow\">**TODO describe**</mark>\n\nValue | Identifier | Description\n--- | --- | ---\n0x00000001 | | <mark style=\"background-color: yellow\">**Unknown (Has data?)**</mark>\n| |\n0x00000020 | |\n| |\n0x00000100 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 7)**</mark>\n| |\n0x00001000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 7, 8.0)**</mark>\n| |\n0x00010000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.0, 8.1)**</mark>\n0x00020000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.0)**</mark>\n| |\n0x00100000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.1)**</mark>\n0x00200000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.1)**</mark>\n| |\n0x01000000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.0, 8.1)**</mark>\n0x02000000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.0)**</mark>\n| |\n0x10000000 | | <mark style=\"background-color: yellow\">**Unknown (Seen in Windows 8.1)**</mark>\n\n## Data\n\n<mark style=\"background-color: yellow\">**TODO describe**</mark>\n\n## Notes\n\n```\nhttps://technet.microsoft.com/en-us/library/cc787360(v=ws.10).aspx\n\nAre these related?\n0x00000001 MS-DOS-based program\n0x00000002 OS/2-based program\n0x00000004 Windows-based 16-bit program\n0x00000008 Windows-based 32-bit program\n0x0000000C Windows-based 16-bit and 32-bit program\n0x0000000F Any version of a program\n0x00000010 Return user name instead of computer name for GetComputerName.\n0x00000020 Return Terminal Server build number instead of Windows 2000 build number for GetVersion.\n0x00000040 Synchronize user .ini file to system version.*\n0x00000080 Do not substitute user \\Windows directory.**\n0x00000100 Disable registry mapping for program or registry key.\n0x00000200 Per-object user/system global mapping\n0x00000400 Return system \\Windows directory instead of user \\Windows directory for GetWindowsDir.\n0x00000800 Limit the reported physical memory for GlobalMemoryStatus.\n0x00001000 Log object creation to file.\n0x20000000 Do not put program to sleep on unsuccessful keyboard polling (Windows-based 16-bit programs only).\n```\n\nRelated DLLs:\n\n* apphelp.dll; related to \"AppHelp\" functionality and Application Compatibility database\n* kernel32.dll; base cache management functionality\n\nIs the Application compatibility cache in Windows also referred to as\nAppHelpCache?\n\nAppHelp: https://msdn.microsoft.com/en-us/library/bb432181(v=vs.85).aspx\n\nDifferent shim types? MSIE and RPC shim types?\n\nRelated Registry keys:\n\n```\nHKLM\\Sofware\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\n```\n\nFlushing the cache Windows Vista and later:\n\n```\nRundll32.exe apphelp.dll,ShimFlushCache\n```\n\nFlushing the cache Windows XP and Windows Server 2003\n\n```\nRundll32.exe kernel32.dll,BaseFlushAppcompatCache\n```\n\n"
  },
  {
    "path": "docs/sources/system-keys/Background-activity-moderator.md",
    "content": "# Background activity moderator (BAM)\n\nThe Background Activity Moderator (BAM) key seems to have been introduced in\nWindows 10 after version 1709.\n\nThe BAM keys can be found in the following Registry paths:\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\bam\\UserSettings\\\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\bam\\State\\UserSettings\\\n```\n\nWithin the UserSettings key, there is a key for each user SID containing\na value for each tracked executable.\n\n## Example Entry\n\nRegistry Key:\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\bam\\State\\UserSettings\\S-1-5-21-321011808-3761883066-353627080-1000\n```\n\nValue Name:\n\n```\n\\Device\\HarddiskVolume1\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\n```\n\nValue Data:\n\n```\n00000000  15 3e ae 36 57 de d4 01 00 00 00 00 00 00 00 00  |.>®6WÞÔ.........|\n00000010  00 00 00 00 02 00 00 00                          |........|\n```\n\n## Value Data Format\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 8 | | Execution time <br> Contains a FILETIME\n8 | 8 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n16 | 4 | | Flag indicating whether the entry is a \"Windows app\"\n20 | 4 | 0x02, 0x00, 0x00, 0x00 | <mark style=\"background-color: yellow\">**Unknown (always 2)**</mark>\n"
  },
  {
    "path": "docs/sources/system-keys/Boot-verification.md",
    "content": "# Boot Verification key\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\BootVerification\n```\n\nThe BootVerification key stores configuration for Bootvrfy.exe, a program\nincluded in Windows Server 2003 that notifies the system that startup was\nsuccessful. Bootvrfy.exe can be run on a local or remote computer.\n\nKnown values of the BootVerification key:\n\nName | Data type | Description\n--- | --- | ---\nErrorControl | REG_DWORD | Known value: 1\n%SERVICE%\\ImagePath | REG_EXPAND_SZ | Known value: \"Bootvrfy.exe\"\nObjectName | REG_SZ | Known value: \"LocalSystem\"\nStart Entry | REG_DWORD | Known value: 3\nType Entry | REG_DWORD | Known value: 2\n\nTo run a custom startup verification program the standard startup verification\nfunctions in Winlogon need to be disabled. This can be done by setting the\nWinlogon ReportBootOk value to 0.\n\n```\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\n```\n\n## Boot Verification Program key\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\BootVerificationProgram\n```\n\nThe BootVerificationProgram key stores configuration for a custom startup\nverification program.\n\nKnown values of the BootVerificationProgram key:\n\nName | Data type | Description\n--- | --- | ---\nImagePath | REG_SZ, REG_EXPAND_SZ | path of a custom startup verification program\n\nAccording Windows server 2003 documentation Bootvrfy.exe and a custom startup\nverification program cannot be used in parallel.\n\n## External links\n\n* [BootVerification](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc778559(v=ws.10))\n* [BootVerificationProgram](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc782537(v=ws.10))\n* [BootVerificationProgram\\ImagePath](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc786702(v=ws.10))\n* [ReportBootOk](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc739989(v=ws.10))\n\n"
  },
  {
    "path": "docs/sources/system-keys/COM-class-identifiers.md",
    "content": "# Component object model (COM) class identifiers (CLSIDs)\n\nThe component object model (COM) class Identifier (CLSID) key can be found in:\n\n```\nHKEY_CLASSES_ROOT\\CLSID\\{%GUID%}\nHKEY_CLASSES_ROOT\\Wow6432Node\\CLSID\\{%GUID%}\n```\n\nSub keys:\n\nName | Description\n--- | ---\nAuxUserType | Application's short display name and names\nCLSID | Class identifiers\nControl | ActiveX Control settings\nConversion | Convert dialog box format conversion settings\nDataFormats | Data formats supported by an application\nDefaultIcon | Default icon settings\nImplemented Categories |\nInprocServer | 16-bit in-process server settings\nInProcServer32 | 32-bit (and 64-bit) in-process server settings\nInsertable | Insert Object dialog box list box settings\nInterface | Supported interface IDs (IIDs)\nLocalServer32 | 32-bit local server application settings\nMiscStatus | Settings how to create and display the object\nPersistentHandler |\nVerb | Application verbs\n\nMSDN defines DefaultIcon as a REG_SZ value but in Windows XP it seems to be a\nkey where the icon resource identifier is stored in the default value of the\nkey.\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nAppID | REG_SZ | Associated application identifier <br> Contains a string in the form: \"{GUID}\"\nAutoConvertTo | REG_SZ | Automatic conversion class identifier\nAutoTreatAs | REG_SZ | Automatically treat as (emulation) class identifier\nInprocHandler | REG_SZ | 16-bit custom in-process handler\nInprocHandler32 | REG_SZ | 32-bit custom in-process handler\nLocalServer | REG_SZ| 16-bit local server application\nProgID | REG_SZ | Associated program identifier <br> Contains a string in the form: \"Program.Component\"\nToolBoxBitmap32 | REG_SZ | Toolbar or toolbox button bitmap <br> Contains a resource identifier\nTreatAs | REG_SZ | Identifier of class that can emulate the current class\nVersion | REG_SZ | version number\nVersionIndependentProgID | REG_SZ | Version independent associated program identifier\n\n## Type libraries key\n\nThe type libraries (typelib or tlb) key can be found in:\n\n```\nHKEY_CLASSES_ROOT\\TypeLib\\{%GUID%}\nHKEY_CLASSES_ROOT\\Wow6432Node\\TypeLib\\{%GUID%}\n```\n\nSub keys:\n\nName | Description\n--- | ---\n%GUID% | Type library identifier\n\n## Type library identifier subkey\n\nSub keys:\n\nName | Description\n--- | ---\n%VERSION% | Type library version in the format: \"major.minor\"\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n(Default) | REG_SZ | Type library description\n\n### Type library version subkey\n\nSub keys:\n\nName | Description\n--- | ---\n%LCID% | Locale identifier such as: \"409\", where \"0\" is the system default language (LANG_SYSTEM_DEFAULT).\nFLAGS |\nHELPDIR |\n\nTODO: Determine what MSDN means with the LCID may have a neutral sublanguage\nID. Is 0 the neutral sublanguage ID?\n\n#### Type library locale subkey\n\nSub keys:\n\nName | Description\n--- | ---\n%PLATFORM% | Platform identifier such as: \"win32\"\n\n##### Type library platform subkey\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n(Default) | REG_SZ | Path to the type library file. <br> This can be a stand-alone .tlb file or the \"typelib\" resource inside a PE/COFF file.\n\n#### Type library help directory subkey\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n(Default) | REG_SZ | Path of the directory where the Help file for type library is located\n\n## External Links\n\n* [CLSID Key](https://learn.microsoft.com/en-us/windows/win32/com/clsid-key-hklm)\n* [ProxyStubClsid](https://learn.microsoft.com/en-us/windows/win32/com/proxystubclsid)\n* [Registering a Type Library](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/automat/registering-a-type-library)\n\n"
  },
  {
    "path": "docs/sources/system-keys/Cached-credentials.md",
    "content": "# Cached credentials\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nCachedLogonsCount | REG_SZ | Number of cached log-ons. <br/> According to MSDN the value must be in the range \"0\" - \"50\"\n\n## Credentials cache\n\n```\nHKEY_LOCAL_MACHINE\\Security\\Cache\n```\n\nValues:\n\nName | Description\n--- | ---\nNL$Control |\nNL$%NUMBER% | Cached credential\n\nWhere %NUMBER% contains the number of the cached credential.\n\n### NL$Control value\n\n```\n00000000  04 00 01 00 0a 00 00 00                           |........|\n```\n\n### NL$%NUMBER% value\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n_Metadata_ |||\n0 | 2 | | Username string size\n2 | 2 | | Hostname string size\n4 | 2 | | <mark style=\"background-color: yellow\">**Unknown (username string size)**</mark>\n6 | 2 | | <mark style=\"background-color: yellow\">**Unknown (Full name string size)**</mark>\n8 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n12 | 2 | | <mark style=\"background-color: yellow\">**Unknown (Profile path string size)**</mark>\n14 | 2 | | <mark style=\"background-color: yellow\">**Unknown (Profile mount drive letter string size)**</mark>\n16 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n20 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n24 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n28 | 2 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n30 | 2 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n32 | 8 | | <mark style=\"background-color: yellow\">**Unknown (date and time)**</mark> <br/> Contains a FILETIME timestamp\n40 | 2 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n42 | 2 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n44 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n48 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n52 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n56 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n60 | 2 | | Hostname with domain string size\n62 | 2 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n_Data_ |||\n64 | 16 | | <mark style=\"background-color: yellow\">**Unknown (CH)**</mark>\n80 | 16 | | <mark style=\"background-color: yellow\">**Unknown (T)**</mark>\n96 | ... | | Encrypted data\n\n```\nmetadata\n* username size\n* domain size\n* Length of the full domain name\n\n0x00000000  0e 00 14 00 0e 00 1c 00  00 00 00 00 38 00 04 00  ............8...\n0x00000010  53 04 00 00 01 02 00 00  02 00 00 00 14 00 18 00  S...............\n\n0x00000020  72 0f 92 b3 b1 f8 cc 01                           r...............\nFILETIME\n\n0x00000020                           04 00 01 00 01 00 00 00  r...............\n0x00000030  01 00 00 00 20 00 00 00  10 00 00 00 20 00 00 00  .... ....... ...\n\nCH: random 16 byte key that is used to generate the decryption key for the encrypted data\n0x00000040  e6 ad 1f 22 b9 d1 d3 48  22 f6 d6 61 33 d7 32 74  ...\"...H\"..a3.2t\n\nT\n0x00000050  29 4c 83 1b af bc ca c9  fc 27 9c be 1e 44 2b 69  )L.......'...D+i\n\nEncrypted data\n0x00000060  52 46 67 5f f6 85 b0 0f  7a a3 69 03 cc 72 4b 8b  RFg_....z.i..rK.\n0x00000070  8b 51 e9 9c 4a 65 92 2d  19 7d 6f 94 d2 81 93 0d  .Q..Je.-.}o.....\n0x00000080  f2 9e 7d 2e 11 17 46 a0  31 ac 2c 65 49 89 c2 c0  ..}...F.1.,eI...\n0x00000090  92 7a 63 6c ca b2 74 ba  5f 73 c0 d3 6c 0c 58 51  .zcl..t._s..l.XQ\n0x000000a0  46 e9 45 48 9b ce 86 a1  68 ae f7 12 f8 d2 c7 7e  F.EH....h......~\n0x000000b0  4d 39 a9 bd d4 ad fc e8  b0 b1 94 36 c5 4d 1f 3b  M9.........6.M.;\n0x000000c0  3c ce b8 dc a9 50 41 54  f4 5a 31 61 57 66 66 7a  <....PAT.Z1aWffz\n0x000000d0  0d 54 9a c0 7e d4 1a a8  e6 af 83 fb cd 61 a1 fe  .T..~........a..\n0x000000e0  85 31 ce c9 24 fa f3 a5  7e 71 c9 a4 81 11 e3 b7  .1..$...~q......\n0x000000f0  7c ce fb 38 b0 81 b9 75  cc 78 7e 66 9c 7b 4d a7  |..8...u.x~f.{M.\n0x00000100  7d 6e 55 d6 8d 22 2d e9  8d 48 0c 22 f1 bc 6b 58  }nU..\"-..H.\"..kX\n0x00000110  17 84 db 5b ba 91 8a 39  70 a1 d8 b5 16 df 99 cf  ...[...9p.......\n0x00000120  ea f1 af dc 75 27 ea 83  22 ff 8a 5e 63 b2 a9 f9  ....u'..\"..^c...\n0x00000130  b4 05 47 26 b8 e7 e4 b7  06 bc d9 4b 0f 20 92 25  ..G&.......K. .%\n0x00000140  07 7a a5 6b 4e 54 4a 19  19 51 bf 5f c2 09 8b 5e  .z.kNTJ..Q._...^\n0x00000150  f1 a3 be aa 1f c3 66 c3  cd 09 7b 85 45 02 0d 28  ......f...{.E..(\n0x00000160  02 a5 f8 8a f2 b1 52 a3  a3 dc a4 c7 ed f5 ca 6c  ......R........l\n0x00000170  13 3c e5 18 3d fe b3 fc  28 3f be 9b 62 d0 1a 5a  .<..=...(?..b..Z\n0x00000180  90 ce e2 a6 c2 aa 2d 40  78 d8 cc db a4 a7 44 e8  ......-@x.....D.\n0x00000190  0d ff c8 08 49 19 5b 21  67 f2 62 be 7b f2 be d3  ....I.[!g.b.{...\n0x000001a0  37 18 53 33 61 3e 21 7a  e6 08 e3 f2 d5 1c 81 ce  7.S3a>!z........\n0x000001b0  9a 45 71 85 bf a6 e9 fd  ea 7e b7 2f 01 0d 7d c7  .Eq......~./..}.\n0x000001c0  46 9f e5 73                                       F..s\n```\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 16 | | <mark style=\"background-color: yellow\">**Unknown (password hash)**</mark>\n16 | 16 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n32 | 8 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n40 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n44 | 4 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n48 | 8 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n56 | 16 | | <mark style=\"background-color: yellow\">**Unknown**</mark>\n72 | ... | | Username string\n... | ... | | 32-bit alignment padding\n... | ... | | Hostname string\n... | ... | | 32-bit alignment padding\n... | ... | | Hostname and domain string\n... | ... | | 32-bit alignment padding\n... | ... | | Profile path string\n... | ... | | 32-bit alignment padding\n... | ... | | Profile mount drive letter string\n... | ... | | 32-bit alignment padding\n\n```\nDecrypted data:\n0x00000000  6e 37 5e e6 a7 99 6c 5c  55 85 74 67 09 af a0 65  n7^...l\\U.tg...e\n0x00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................\n0x00000020  01 00 00 00 00 00 00 00  c4 01 00 00 02 00 00 00  ................\n0x00000030  14 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................\n0x00000040  00 00 00 00 00 00 00 00                           ........t.d.u.n.\n\nSizes from metadata\n0e 00 14 00 0e 00 1c 00\n\n0x00000040                           74 00 64 00 75 00 6e 00  ........t.d.u.n.\n0x00000050  67 00 61 00 6e 00                                 g.a.n...S.H.I.E.\n\n0x00000050                    00 00                           g.a.n...S.H.I.E.\n\n0x00000050                           53 00 48 00 49 00 45 00  g.a.n...S.H.I.E.\n0x00000060  4c 00 44 00 42 00 41 00  53 00 45 00              L.D.B.A.S.E.S.H.\n\n0x00000060                                       53 00 48 00  L.D.B.A.S.E.S.H.\n0x00000070  49 00 45 00 4c 00 44 00  42 00 41 00 53 00 45 00  I.E.L.D.B.A.S.E.\n\n0x00000080  2e 00 4c 00 4f 00 43 00  41 00 4c 00              ..L.O.C.A.L.t.d.\n\n0x00000080                                       74 00 64 00  ..L.O.C.A.L.t.d.\n0x00000090  75 00 6e 00 67 00 61 00  6e 00 00 00              u.n.g.a.n...T.i.\n\n0x00000090                                       54 00 69 00  u.n.g.a.n...T.i.\n0x000000a0  6d 00 6f 00 74 00 68 00  79 00 20 00 44 00 75 00  m.o.t.h.y. .D.u.\n0x000000b0  6e 00 67 00 61 00 6e 00                           n.g.a.n.\\.\\.c.o.\n\n0x000000b0                           5c 00 5c 00 63 00 6f 00  n.g.a.n.\\.\\.c.o.\n0x000000c0  6e 00 74 00 72 00 6f 00  6c 00 6c 00 65 00 72 00  n.t.r.o.l.l.e.r.\n0x000000d0  5c 00 68 00 6f 00 6d 00  65 00 5c 00 25 00 75 00  \\.h.o.m.e.\\.%.u.\n0x000000e0  73 00 65 00 72 00 6e 00  61 00 6d 00 65 00 25 00  s.e.r.n.a.m.e.%.\n\n0x000000f0  48 00 3a 00 01 02 00 00  07 00 00 00 07 02 00 00  H.:.............\n0x00000100  07 00 00 00 53 00 48 00  49 00 45 00 4c 00 44 00  ....S.H.I.E.L.D.\n0x00000110  42 00 41 00 53 00 45 00  07 00 00 20 01 05 00 00  B.A.S.E.... ....\n0x00000120  00 00 00 05 15 00 00 00  97 2a 67 79 a0 54 4a b6  .........*gy.TJ.\n0x00000130  19 87 28 7e 3c 02 00 00  01 04 00 00 00 00 00 05  ..(~<...........\n0x00000140  15 00 00 00 97 2a 67 79  a0 54 4a b6 19 87 28 7e  .....*gy.TJ...(~\n0x00000150  43 00 4f 00 4e 00 54 00  52 00 4f 00 4c 00 4c 00  C.O.N.T.R.O.L.L.\n0x00000160  45 00 52 00                                       E.R.\n```\n\nNL$7\n\n```\n00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000020  00 00 00 00 00 00 00 00  04 00 01 00 00 00 00 00  |................|\n00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000080  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n000000a0  00 00 00 00 00 00 00 00                           |........|\n```\n\n## External Links\n\n* [Cached domain logon information](https://learn.microsoft.com/en-us/troubleshoot/windows-server/user-profiles-and-logon/cached-domain-logon-information)\n\n"
  },
  {
    "path": "docs/sources/system-keys/Certificates.md",
    "content": "# Certificates\n\n```\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\SystemCertificates\\AuthRoot\\Certificates\n```\n\n## External Links\n\n* [Certificates Tools and Settings](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc787544(v=ws.10))\n"
  },
  {
    "path": "docs/sources/system-keys/Codepage.md",
    "content": "# Codepage\n\nThe codepage settings are stored in the key:\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n`#` | REG_SZ | The name of the code page National Language Support file (.nls) <br/> Where # is the code page number, e.g. 1252 <br/> Contains a string with the name of the corresponding file e.g. c_1252.nls\nACP | REG_SZ | The default ANSI (extended ASCII) code page <br/> Contains a string with the number of the corresponding code page e.g. 1252\nMACCP | REG_SZ | The default Macintosh code page <br/> Contains a string with the number of the corresponding code page e.g. 1252\nOEMCP | REG_SZ | The default OEM code page <br/> Contains a string with the number of the corresponding code page e.g. 1252\nOEMHAL | REG_SZ | <mark style=\"background-color: yellow\">**Unknown**</mark> <br/> Contains a string with the name of the corresponding file e.g. vgaoem.fon\n\n"
  },
  {
    "path": "docs/sources/system-keys/Current-control-set.md",
    "content": "# Current control set\n\nThe Windows Registry contains the Current control set key:\n\n```\nHKEY_LOCAL_MACHINE\\System\\CurrentControlSet\n```\n\n## Current Control Set - Windows 9x/Me\n\nIn Windows 9x/Me the Current Control Set key is stored in the SYSTEM.DAT\nRegistry file.\n\n## Current Control Set - Windows NT\n\nOn Windows NT the Current Control Set key is only present at run-time. The\ncontents of the key is stored in the SYSTEM Registry file and can be\ndetermined by reading the Current value from the key:\n\n```\n<RootKey>\\Select\n```\n\nThe Current value contains number of the current control set. Normally 1 or 2 \nbut other values like 3 or 47 are known to be used. For example a value of 1\nmaps to the Control Set key:\n\n```\n<RootKey>\\ControlSet001\n```\n\nNormally there are multiple Control Set keys the role each of the Control Set\nkeys can be different:\n\n> ControlSet001 may be the last control set you booted with, while\n> ControlSet002 could be what is known as the last known good control set, or\n> the control set that last successfully booted Windows.\n\nThese roles are defined by the other values in the Select key:\n\nName | Data type | Description\n--- | --- | ---\nCurrent | REG_DWORD | Current Control Set\nDefault | REG_DWORD | Default Control Set\nFailed | REG_DWORD | Control Set that failed to boot\nLastKnownGood | REG_DWORD | Last known good Control Set\n\n### Notes\n\n* Determine if a value of 0 indicates not set\n* Confirm if speculations that 9 is the largest value ControlSet00#\n\n"
  },
  {
    "path": "docs/sources/system-keys/Environment-variables.md",
    "content": "# Environment variables\n\nThe environment variables are stored in multiple keys.\n\n## Session Manager\\\\Environment key\n\n```\nHKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%NAME% | REG_SZ | Value of an environment variable, where %NAME% contains the name of the environment variable.\n\nFor example the \"windir\" value that contains \"%SystemRoot%\".\n\n## Windows\\\\CurrentVersion key\n\nValues of environment variables such as %%ProgramFiles% can be derived from\nvalues in the Windows\\\\CurrentVersion key:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nCommonFilesDir | REG_SZ | Value of %CommonProgramFiles% environment variable\nCommonFilesDir (x86) | REG_SZ | Value of %CommonProgramFiles(x86)% environment variable\nCommonW6432Dir | REG_SZ | Value of %CommonProgramW6432% environment variable\nProgramFilesDir | REG_SZ | Value of %ProgramFiles% environment variable\nProgramFilesDir (x86) | REG_SZ | Value of %ProgramFiles(x86)% environment variable\nProgramW6432Dir | REG_SZ | Value of %ProgramW6432% environment variable\n\nFor example the \"ProgramFilesDir (x86)\" value that contains\n\"C:\\Program Files (x86)\".\n\n## Windows NT\\\\CurrentVersion key\n\nThe %SystemRoot% environment variable can be derived from values in\nthe Windows NT\\\\CurrentVersion key:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nSystemRoot | REG_SZ | Value of %SystemRoot% environment variable\n\nFor example the \"SystemRoot\" value that contains \"C:\\\\Windows\"\n\n## CurrentVersion\\\\ProfileList key\n\nValues of environment variables such as %ProgramData% can be derived from\nvalues in the CurrentVersion\\\\ProfileList key:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nAllUsersProfile | REG_SZ | Value of the %AllUsersProfile% environment variable (Seen on Windows XP)\nDefault | REG_SZ | (Seen on Windows Vista)\nDefaultUserProfile | REG_SZ | (Seen on Windows XP)\nProfilesDirectory | REG_EXPAND_SZ | Profiles directory, for example \"C:\\Documents and Settings\" on Windows XP or \"C:\\Users\" on Windows Vista.\nProgramData | REG_SZ | Value of the %ProgramData% environment variable (Seen on Windows Vista)\nPublic | REG_SZ | Value of the %Public% environment variable\n\nIf the AllUsersProfile value does not start with an environment variable or\nan absolute path, but a relative path, it is currently assumed that the value\nshould be prefixed with the value in ProfilesDirectory.\n\n## User specific environment variables\n\n```\nHKEY_CURRENT_USER\\Environment\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%NAME% | REG_SZ | Value of an user specific environment variable, where %NAME% contains the name of the environment variable.\n\n"
  },
  {
    "path": "docs/sources/system-keys/File-system.md",
    "content": "# File system\n\nWindows file system settings are stored in the File system key.\n\n```\nHKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\FileSystem\n```\n\n# File System key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nNtfsAllowExtendedCharacterIn8dot3Name | REG_DWORD |\nNtfsDisable8dot3NameCreation | REG_DWORD |\nNtfsDisableLastAccessUpdate | REG_DWORD |\nNtfsEncryptionService | REG_SZ |\nWin31FileSystem | REG_DWORD |\nWin95TruncatedExtensions | REG_DWORD |\n\n## NTFS Disable Short (8.3) Filename Creation value\n\nValue | Description\n--- | ---\n0 | For NTFS short (8.3) filenames are created\n1 | For NTFS short (8.3) filenames are *not* created\n\n## NTFS Disable Last Access Time value\n\nValue | Description\n--- | ---\n0 | For NTFS the last-accessed timestamp of a file is updated whenever the file is opened.\n1 | For NTFS the last-accessed timestamp of a file is *not* updated whenever the file is opened.\n\n**TODO the explanation of the values differs between versions of Windows**\n\nThe meaning of the value 0 for Windows 2000 according to\n[NtfsDisableLastAccessUpdate](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc959914(v=technet.10)):\n\n```\nWhen listing directories, NTFS updates the last-access timestamp on each\ndirectory it detects, and it records each time change in the NTFS log.\n```\n\nIn contrast to the meaning of the value 0 for Windows 2003 according to\n[NtfsDisableLastAccessUpdate](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc758569(v=ws.10)):\n\n```\nNTFS updates the last-accessed timestamp of a file whenever that file is opened.\n```\n\n**TODO value does not exist by default until Windows XP SP3/Vista**\n\n## External Links\n\n### Windows 2000\n\n* [NtfsDisable8dot3NameCreation](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc959352(v=technet.10))\n* [NtfsDisableLastAccessUpdate](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc959914(v=technet.10))\n* [Win31FileSystem](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc976058(v=technet.10))\n* [NtfsEncryptionService](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc976057(v=technet.10))\n* [NtfsAllowExtendedCharacterIn8dot3Name](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc963196(v=technet.10))\n\n### Windows 2003\n\n* [NtfsAllowExtendedCharacterIn8dot3Name](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc781607(v=ws.10))\n* [NtfsDisable8dot3NameCreation](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc778996(v=ws.10))\n* [NtfsDisableLastAccessUpdate](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc758569(v=ws.10))\n* [NtfsEncryptionService](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc739602(v=ws.10))\n* [Win95TruncatedExtensions](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc756733(v=ws.10))\n\n"
  },
  {
    "path": "docs/sources/system-keys/Language.md",
    "content": "# Language\n\nThe language settings are stored in the key:\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Nls\\Language\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n`#` | REG_SZ | The name of the code page National Language Support file (.nls) <br/> Where # is a hexadecimal formatted LCID, e.g. 0409 <br/> Contains \"l_intl.nls\", which is a reference to \"\\Windows\\System32\\l_intl.nls\"\nDefault | REG_SZ | The default system language, contains a hexadecimal formatted LCID\nInstallLanguage | REG_SZ | contains a hexadecimal formatted LCID\n\n## Language groups\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Nls\\Language Groups\n```\n\n"
  },
  {
    "path": "docs/sources/system-keys/Local-security-authority.md",
    "content": "# Local Security Authority (LSA)\n\nWindows 2000 and later.\n\n```\nHKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Lsa\n```\n\n## Boot key\n\nThe boot key can be determined as following.\n\nDetermine a 32-character string by combining the classnames of the following\nsubkeys:\n\n* JD\n* Skew1\n* GBG\n* Data\n\nThe string contains a base16 encoded 16-byte binary data that contains the\nscrambled key data. To unscramble the key data:\n\n```\nscrambled_key = codecs.decode(class_name_string, 'hex')\n\nkey = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\nfor index, scrambled_index in enumerate([\n    8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7]):\n  key[index] = scrambled_key[scrambled_index]\n\nkey = codecs.encode(b''.join(key), 'hex')\n```\n\n## LSA key\n\nThe Local Security Authority (LSA) (or Syskey) is a 128-bit RC4 encryption key\nused to protect credentials stored in the Windows Registry.\n\n```\nKey: HKEY_LOCAL_MACHINE\\Security\\Policy\\PolSecretEncryptionKey\nDefault value\n```\n\n```\nWindows XP\n\n00000000  01 00 00 00 01 00 00 00  00 00 00 00              |..............?.|\n\nRC4 encrypted data\n00000000                                       fd d4 3f b3  |..............?.|\n00000010  ee 4f cd 45 2d 02 e8 1e  f2 ac bd 4f fc 15 12 09  |.O.E-......O....|\n00000020  0a b5 48 17 33 8f 42 79  8b 89 11 d8 ec 6e 1c ec  |..H.3.By.....n..|\n00000030  38 5f 27 df 72 ca 57 96  8d 16 d9 37              |8_'.r.W....7..d.|\n\nRC4 key material\n00000030                                       c4 14 64 d1  |8_'.r.W....7..d.|\n00000040  a8 47 7a d4 4b a3 62 d8  e7 2b ef 76              |.Gz.K.b..+.v|\n```\n\n```\nmd5 = MD5.new()\nmd5.update(boot_key)\n\niteration = 0\nwhile iteration < 1000:\n  md5.update(value_data[60:76])\n  iteration += 1\n\nrc4_key = md5.digest()\n\nrc4 = ARC4.new(rc4_key)\ndecrypted_data = rc4.decrypt(value_data[12:60])\n\nlsa_key = decrypted_data[16:32]\n```\n\n```\n0x00000000  80 3a ce f0 5f 15 d3 11  b7 e6 00 80 5f 48 ca eb  .:.._......._H..\n\n0x00000010  01 d6 5d f4 43 aa 0a 86  d9 42 d1 17 34 ce 66 7c  ..].C....B..4.f|\n0x00000020  24 9a 83 44 c6 a7 57 30  44 dc 27 06 26 94 77 8a  $..D..W0D.'.&.w.\n```\n\n## NL$KM\n\n```\nKey: HKEY_LOCAL_MACHINE\\Security\\Policy\\Secrets\\NL$KM\\CurrVal\nDefault value\n```\n\n```\nWindows XP\n00000000  48 00 00 00 48 00 00 20  9c c3 0c 00              |H...H.. ........|\n\nDES encrypted data\n00000000                                       c2 0d 08 10  |H...H.. ........|\n00000010  9a 04 04 bf 14 8b c7 d0  0b e2 9c 40 52 a7 8e aa  |...........@R...|\n00000020  01 49 25 70 71 dc a0 69  8e 6c 03 1c b7 db 19 5c  |.I%pq..i.l.....\\|\n00000030  8f f4 11 d1 8d 73 07 b0  6f 1a db 0b ee cb 69 7f  |.....s..o.....i.|\n00000040  73 50 24 82 f8 e1 a6 27  97 a9 cc 04 8e e4 ca bb  |sP$....'........|\n00000050  33 68 00 7c                                       |3h.||\n```\n\n```\ndecrypted data (_LSA_BLOB)\n\n0x00000000  40 00 00 00 01 00 00 00  09 fe 44 48 1b 35 73 b7  @.........DH.5s.\n0x00000010  3b 1d fc f7 48 9f c9 60  3b 60 7d cf 62 35 50 fd  ;...H..`;`}.b5P.\n0x00000020  b5 d8 8f 21 75 ec 01 e9  85 25 96 6c 68 52 c9 30  ...!u....%.lhR.0\n0x00000030  fb 1d b6 9d cd 8c 14 90  91 de f1 dd 5d d7 64 2a  ............].d*\n0x00000040  ce 40 97 5a f1 59 71 20                           .@.Z.Yq \n```\n\n```\nWindows 7\n00000000  00 00 00 01                                       |....a.!v.......N|\n\n00000000              61 d8 21 76  d9 02 af de bd aa ba 4e  |....a.!v.......N|\n00000010  f3 3f de 78 03 00 00 00  00 00 00 00 1a 7a 20 be  |.?.x.........z .|\n00000020  73 10 0b 57 34 88 16 81  00 42 50 a1 8f 5e 78 46  |s..W4....BP..^xF|\n00000030  bb f3 5e 61 9b 59 fa de  ff 14 7c c1 70 97 66 8e  |..^a.Y....|.p.f.|\n00000040  c8 98 54 5c 8e 0e 13 7d  e7 ba 9a 98 8b cf a4 6f  |..T\\...}.......o|\n00000050  6d 84 5f 84 9c 9f d9 08  c3 5d 5c bd e9 1a 78 c6  |m._......]\\...x.|\n00000060  63 de 80 2d ec 3c 75 1f  1b e0 10 f5 24 1c 5d 41  |c..-.<u.....$.]A|\n00000070  dd fa 85 7c 6e 20 cd 5e  a4 ac c0 53 7e c3 d6 ef  |...|n .^...S~...|\n00000080  23 e2 2c b0 bd 74 52 19  cd a0 4e b2 00 00 00 00  |#.,..tR...N.....|\n00000090  00 00 00 00 00 00 00 00  00 00 00 00              |............|\n```\n\n"
  },
  {
    "path": "docs/sources/system-keys/Mounted-devices.md",
    "content": "# Mounted devices\n\nThe mounted devices settings are stored in the key:\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\MountedDevices\n```\n\nNote that the mounted devices settings are also referred to as\n\"Mount manager's persistent name database\".\n\nSeen on:\n\n* Windows 2000\n* Windows XP\n* Windows 2003\n* Windows Vista\n* Windows 2008\n* Windows 7\n* Windows 8.0\n* Windows 8.1\n* Windows 10\n* Windows 11\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%IDENTIFIER% | REG_BINARY | \n\nWhere the following variants of %IDENTIFIER% can be used:\n\n* \"\\DosDevices\\C:\" - drive letter that is assigned to the root of a file system\n* \"\\DosDevices\\F:\\path\\name\" - drive letter that is assigned to a specific directory within a file system (has not been observed)\n* \"\\??\\Volume{01234567-89ab-cdef-0123-456789abcdef}\" - unique volume identifier used within the Windows Kernel-Mode Object Manager\n* \"#{01234567-89ab-cdef-0123-456789abcdef}\" - purpose current unknown\n\nWhere the value data consist of either:\n\n* Device string value data\n* GPT partition value data\n* MBR partition value data\n\n## Device string value data\n\nThe device string value data is variable of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | ... | | UTF-16 little-endian encoded string, without an end-of-string character\n\nFor example:\n\n```\n\\??\\FDC#GENERIC_FLOPPY_DRIVE#6&12345678&0&0#{01234567-89ab-cdef-0123-456789abcdef}\n\\??\\IDE#CdRomQEMU_QEMU_DVD-ROM_______________________1.6.____#5&12345678&0&0.1.0#{01234567-89ab-cdef-0123-456789abcdef}\n\\??\\SCSI#CdRom&Ven_VBOX&Prod_CD-ROM#4&0123456&0&010000#{01234567-89ab-cdef-0123-456789abcdef}\n_??_USBSTOR#Disk&Ven_Generic&Prod_Flash_Disk&Rev_8.07#01234567&0#{01234567-89ab-cdef-0123-456789abcdef}\n```\n\n## GPT partition value data\n\nThe GPT partition value data is 24 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 8 | \"DMIO:ID:\" | Signature, where DMIO is presumed to refer to Disk Manager I/O Driver\n8 | 16 | | GUID Partition Table (GPT) partition identifier (little-endian GUID)\n\n## MBR fixed-disk value data\n\nThe MBR partition value data is 12 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | | Master Boot Record (MBR) Disk identity (signature) (also referred to as disk identifier)\n4 | 8 | | Offset of the partition, in bytes, that contains the previously mounted file system\n\n## Notes\n\nThe Windows `mountvol.exe` command-line tool can show information about mounted and unmounted\ndevices. Its PowerShell equivalant is `Get-Volume`.\n\nEntries of volumes that are not presently mounted can be removed from the database with:\n\n```\nmountvol /r\n```\n\n## External Links\n\n* [Supporting Mount Manager Requests in a Storage Class Driver](https://learn.microsoft.com/en-us/windows-hardware/drivers/storage/supporting-mount-manager-requests-in-a-storage-class-driver)\n* [Windows Kernel-Mode Object Manager](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/windows-kernel-mode-object-manager)\n\n"
  },
  {
    "path": "docs/sources/system-keys/Prefetch.md",
    "content": "# Prefetch\n\n## Prefetch Parameters key\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nEnablePrefetcher | REG_DWORD |\n\n### Enable Prefetcher value\n\nValues:\n\nValue | Description\n--- | ---\n0 | Disabled\n1 | Application start prefetching enabled\n2 | Boot prefetching enabled\n3 | Application start and boot enabled\n\n## External Links\n\n* [Disabling Prefetch](https://learn.microsoft.com/en-us/previous-versions/windows/embedded/ms940847(v=winembedded.5))\n* [Disable Prefetch (Standard 7 SP1)](https://learn.microsoft.com/en-us/previous-versions/windows/embedded/ff794503(v=winembedded.60))\n\n"
  },
  {
    "path": "docs/sources/system-keys/Run-and-RunOnce.md",
    "content": "# Run and RunOnce\n\nRun and RunOnce keys cause programs to run each time a user logs on. There are\nsystem and per-user Run and RunOnce keys.\n\n## Run and RunOnce keys\n\nSystem Run and RunOnce keys:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnceEx\n```\n\nPer-user Run and RunOnce keys:\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%NAME% | REG_SZ | Command to run or run once\n\n### RunOnce\\\\Setup sub key\n\nContains first-boot activities after setup or when the Add/Remove Programs \nWizard was used.\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\\Setup\n```\n\n## RunServices and RunServicesOnce\n\nOnly on Windows 9x/Me.\n\nRun in the background when the logon dialog box first appears, or at the boot \nprocess stage if there is no logon.\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServices\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnce\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%NAME% | REG_SZ | Command to run or run once\n\n## Notes\n\n```\ndescription-string=commandline\n```\n\nAccording to [Microsoft](https://learn.microsoft.com/en-us/windows/win32/setupapi/run-and-runonce-registry-keys):\n\n```\nBy default, the value of a RunOnce key is deleted before the command line is \nrun. You can prefix a RunOnce value name with an exclamation point (!) to defer \ndeletion of the value until after the command runs. Without the exclamation \npoint prefix, if the RunOnce operation fails the associated program will not be \nasked to run the next time you start the computer.\n\nBy default, these keys are ignored when the computer is started in Safe Mode. \nThe value name of RunOnce keys can be prefixed with an asterisk (*) to force \nthe program to run even in Safe mode.\n```\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\policies\\Explorer\\Run\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows\\Run\n```\n\nInstalled \"Programs and Features\"\n\n```\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\n```\n\n## External Links\n\n* [Run and RunOnce Registry Keys](https://learn.microsoft.com/en-us/windows/win32/setupapi/run-and-runonce-registry-keys)\n\n"
  },
  {
    "path": "docs/sources/system-keys/Services-and-drivers.md",
    "content": "# Services and drivers\n\n**TODO this page currently contains rough notes, fine tune these**\n\nSettings to load/run drivers and services are stored in the Services key:\n\n```\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\n```\n\nSub keys:\n\nName | Description\n--- | ---\n%NAME% | The driver or service sub key. Where %NAME% corresponds with the name of the driver or service.\n\n## Name sub key\n\nSub keys:\n\nName | Description\n--- | ---\nCache |\nDeviceInRange |\nLinkage |\nOptions |\nParameters |\nPerformance |\nSecurity |\nSettings |\nStartOverride |\ntracing |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nDependOnGroup | REG_MULTI_SZ | Other groups the device or service is dependent on.\nDependOnService | REG_MULTI_SZ | Other services the device or service is dependent on.\nDescription | REG_SZ | Description.\nDisplayName | REG_SZ, REG_MULTI_SZ | Display name.\nDriverPackageId | |\nErrorControl | REG_DWORD | The level of error control.\nFailureActions | |\nGroup | REG_SZ | Name of the group the device or service is part of.\nImagePath | REG_SZ | Path and filename of device or service executable file (or image).\nObjectName | REG_SZ | See section: ObjectName value\nRequiredPrivileges | |\nStart | REG_DWORD | The start control value.\nServiceSidType | |\nTag | REG_DWORD |\nType | REG_DWORD | The driver or service type.\n\n### Parameters sub key\n\nSub keys:\n\nName | Description\n--- | ---\nPnpInterface |\nPolicy |\nTriggerInfo |\nWakeUp |\nWdf |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nAmdXataOptions | REG_DWORD | \nAMLIMaxCTObjs | REG_BINARY | \nAPEIOSCGranted | REG_BINARY | \nAthDfuWaitInfinite | REG_DWORD | \nBusType | REG_DWORD | \nDebugFlags | REG_DWORD | \nIoTimeoutValue | REG_DWORD | \nMaintainServerList | REG_SZ | \nServiceDll | REG_EXPAND_SZ | \nServiceDllUnloadOnStop | REG_DWORD | \nServiceMain | REG_SZ | \nWHEAOSCImplemented | REG_BINARY | \n\n### ErrorControl value\n\nValue | Identifier | Description\n--- | --- | ---\n0x00000000 | Ignore |\n0x00000001 | Normal |\n0x00000002 | Severe |\n0x00000003 | Critical |\n\n### ObjectName value\n\nThe ObjectName value has a different meaning for different types of Driver or\nService Name sub keys.\n\n* For a driver type the ObjectName value contains the Windows NT driver object name that the I/O Manager uses to load the device driver.\n* For a service type the ObjectName value contains the account name under which the service will log on to run.\n\nWindows Services shows this value as \"LogOn As\".\n\n### Start value\n\nValue | Identifier | Description\n--- | --- | ---\n0x00000000 | Boot | Driver or service controlled by the kernel that is loaded by the boot loader.\n0x00000001 | System | Driver or service controlled by the I/O sub system that is loaded at kernel initialization.\n0x00000002 | Automatic | Driver or service controlled by the Services Control Manager that is loaded at start up. Also referred to as: Auto load\n0x00000003 | On demand | Driver or service controlled by the Services Control Manager that is loaded on demand. Also referred to as: Load on demand or Automatic (Delayed start)\n0x00000004 | Disabled | Driver or service controlled by the Services Control Manager that is disabled.\n\nWindows Services shows this value as \"Startup Type\".\n\n### Type value\n\nValue | Identifier | Description\n--- | --- | ---\n0x00000001 | | Kernel device driver\n0x00000002 | | File system driver\n0x00000004 | | A set of argument for an adapter\n0x00000008 | | *Unknown, seen in combination Fs_Rec*\n0x00000010 | | Stand-alone (self-contained) service\n0x00000020 | | Shared service\n0x00000100 | | *Unknown, seen in combination with 0x00000010 and 0x00000020. Goes back to Windows 2000 maybe to indicate a network service.*\n\n"
  },
  {
    "path": "docs/sources/system-keys/Session-manager.md",
    "content": "# Session manager\n\nThe session manager settings are stored in the key:\n\n```\nHKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nBootExecute | REG_BINARY, REG_MULTI_SZ | Applications, services and commands executed during start-up.\n\n## External links\n\n* [MSDN: BootExecute](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc963230(v=technet.10))\n\n"
  },
  {
    "path": "docs/sources/system-keys/Shell-folder-identifiers.md",
    "content": "# Shell folder identifiers\n\nShell folder identifiers are class identifiers (CLSID) with ShellFolder sub\nkey of some [COM Class Identifier (CLSID) keys](https://winreg-kb.readthedocs.io/en/latest/sources/system-keys/COM-class-identifiers.html).\n\n```\nHKEY_CLASSES_ROOT\\CLSID\\{%GUID%}\\ShellFolder\n```\n\n## Shell Folder class identifier (CLSID) sub key\n\nSub keys specific to shell folder identifiers:\n\nName | Description\n--- | ---\nshell |\nshellex |\nShellFolder |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n(default) | |\nInfoTip | |\nLocalizedString | |\nSortOrderIndex | |\n\n### Shell Folder sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nAttributes | REG_DWORD |\nCallForAttributes | |\nHideOnDesktopPerUser | |\n\n### Attributes values\n\nValue | Identifier | Description\n--- | --- | ---\n0x00000010 | SFGAO_CANRENAME | The extension's root folder can be renamed by the user. The folder's shortcut menu will have a Rename item.\n0x00000020 | SFGAO_CANDELETE | The extension's root folder can be deleted by the user. The folder's shortcut menu will have a Delete item.\n0x00000040 | SFGAO_HASPROPSHEET | The extension's root folder has a Properties property sheet. The folder's shortcut menu will have a Properties item.\n| |\n0x20000000 | SFGAO_FOLDER | The extension's root folder contains one or more items.\n0x80000000 | SFGAO_HASSUBFOLDER | The extension's root folder contains one or more subfolders. Windows Explorer will place a plus sign ( `+` ) next to the folder icon.\n\n### LocalizedString value data\n\nThe LocalizedString value contains a localized version of the folder name, e.g.\non Windows XP the folder identifier key:\n\n```\nHKEY_CLASSES_ROOT\\CLSID\\{450d8fba-ad25-11d0-98a8-0800361b1103}\n```\n\nHas a LocalizedString value with the following data:\n\n```\n@%SystemRoot%\\system32\\SHELL32.dll,-9227\n```\n\nWhich is the [MUI Form](https://winreg-kb.readthedocs.io/en/latest/sources/windows-registry/MUI-form.html)\nfor \"My Documents\".\n\n## External Links\n\n* [Implementing the Basic Folder Object Interfaces](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/cc144093(v=vs.85))\n* [libfwsi: Shell Folder identifiers](https://github.com/libyal/libfwsi/wiki/Shell-Folder-identifiers)\n\n"
  },
  {
    "path": "docs/sources/system-keys/System-restore.md",
    "content": "# System restore\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\SystemRestore\n```\n\n"
  },
  {
    "path": "docs/sources/system-keys/Task-scheduler.md",
    "content": "# Task scheduler\n\n## SchedulingAgent key\n\nIn Windows XP:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\SchedulingAgent\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nDataVersion | |\nLastTaskRun | |\nLogPath | |\nMaxLogSizeKB | |\nMinutesBeforeIdle | |\nOldName | |\nPriorDataVersion | |\nTasksFolder | |\n\n## Schedule key\n\nIn Windows Vista and later:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\n```\n\nSub keys:\n\nName | Description\n--- | ---\nAliases |\nCompatibilityAdapter |\nConfiguration |\nCredWom |\nHandlers |\nHandshake |\nTaskCache |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nDomainJoinDetected | |\nHashingCompleted | |\nMigrationCleanupCompleted | |\n\n### TaskCache sub key\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\n```\n\nSub keys:\n\nName | Description\n--- | ---\nBoot |\nLogon |\nPlain |\nTasks |\nTree |\n\n#### TaskCache\\\\Tree sub key\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tree\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nId | | Contains a GUID that corresponds to an entry in the Task Cache\nIndex | |\n\n#### TaskCache\\\\Tree\\\\%GUID% sub key\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tasks\\%GUID%\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nDynamicInfo | |\nHash | | Integrity hash of the of XML task file (in %windir%\\\\System32\\\\Tasks) <br> Contains a SHA-256 or CRC32, before KB2305420. A byte-order-mark at beginning of the file is not included in the calculation of the hash.\nPath | | Path of the corresponding Registry key in the TaskCache Tree sub key\nTriggers | |\n\n##### TaskCache\\\\Tree\\\\%GUID%\\\\DynamicInfo sub key\n\nSeen in Windows Vista, Windows 2008 and Windows 7:\n\nThe dynamic information entry is 28 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 3 | <mark style=\"background-color: yellow\">**Unknown**</mark>\n4 | 8 | | <mark style=\"background-color: yellow\">**Unknown timestamp (last registered or update time?)**</mark> <br> Contains a FILETIME or 0 if not set\n12 | 8 | | <mark style=\"background-color: yellow\">**Unknown timestamp (launch time?)**</mark> <br> Contains a FILETIME or 0 if not set\n20 | 4 | | <mark style=\"background-color: yellow\">**Unknown (flags?)**</mark>\n24 | 4 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n\n```\n0x00000000  03 00 00 00 1c ec 45 16  3f 04 ca 01 00 00 00 00  ......E.?.......\n0x00000010  00 00 00 00 00 00 00 00  00 00 00 00              ............\n\n0x00000000  03 00 00 00 16 6f 4a 0f  7f fe c6 01 66 b7 6c 0d  .....oJ.....f.l.\n0x00000010  6b 4c c9 01 2b 04 07 80  00 00 00 00              kL..+.......\n```\n\nSeen in Windows 8 and Windows 10:\n\n<mark style=\"background-color: yellow\">**TODO: check Windows 2012**</mark>\n\nThe dynamic information entry is 36 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | 3 | <mark style=\"background-color: yellow\">**Unknown**</mark>\n4 | 8 | | <mark style=\"background-color: yellow\">**Unknown timestamp (last registered or update time?)**</mark> <br> Contains a FILETIME or 0 if not set\n12 | 8 | | <mark style=\"background-color: yellow\">**Unknown timestamp (launch time?)**</mark> <br> Contains a FILETIME or 0 if not set\n20 | 4 | | <mark style=\"background-color: yellow\">**Unknown (flags?)**</mark>\n24 | 4 | | <mark style=\"background-color: yellow\">**Unknown (empty values)**</mark>\n28 | 8 | | <mark style=\"background-color: yellow\">**Unknown timestamp**</mark> <br> Contains a FILETIME or 0 if not set\n\n```\n0x00000000  03 00 00 00 4b 5a 0b 60  ff 6a cd 01 5c 32 e7 45  ....KZ.`.j..\\2.E\n0x00000010  1b b6 ce 01 20 04 07 80  00 00 00 00 a2 b1 86 4f  .... ..........O\n0x00000020  1b b6 ce 01                                       ....\n```\n\n##### Path value\n\nThe path value is relative from:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tree\n```\n\nFor example the path:\n\n```\n\\Microsoft\\Windows\\Media Center\\ehDRMInit\n```\n\nCorresponds to:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tree\\Microsoft\\Windows\\Media Center\\ehDRMInit\n```\n\n##### Triggers value\n\nNote that the FILETIME value appear to be stored in local time.\n\n"
  },
  {
    "path": "docs/sources/system-keys/Time-zones.md",
    "content": "# Time zones\n\n## Time zone information key\n\nThe time zone information is stored in the following key:\n\n```\nHKEY_LOCAL_MACHINE\\CurrentControlSet\\Control\\TimeZoneInformation\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nActiveTimeBias | REG_DWORD | The active time bias, in minutes, as configured for the time zone accounting for daylight saving. This is the bias that was used to configure the CMOS clock.\nBias | REG_DWORD | The current bias, in minutes, for local time translation on this computer.\nDaylightBias | REG_DWORD | The bias value, in minutes, to be used during local time translations that occur during daylight saving time.\nDaylightName | REG_SZ | A description for daylight saving time.\nDaylightStart | REG_BINARY | The date and local time when the transition from standard time to daylight saving time occurs on this operating system. <br/> Contains a SYSTEMTIME structure.\nDynamicDaylightTimeDisabled | REG_DWORD | Indicates whether dynamic daylight saving time is disabled. <br/> 0 indicates automatic adjustment <br/> 1 indicates automatic adjustment is disabled\nRealTimeIsUniversal | REG_DWORD | Indicates if the CMOS clock is configured by using the local date/time (default) or UTC. <br/> 0 indicates that the CMOS clock is configured for local date/time <br/> 1 indicates that the CMOS clock is configured by using UTC\nStandardBias | REG_DWORD | The bias value, in minutes, to be used during local time translations that occur during standard time.\nStandardName | REG_SZ | A description for standard time.\nStandardStart | REG_BINARY | The date and local time when the transition from daylight saving time to standard time occurs on this operating system. <br/> Contains a SYSTEMTIME structure.\nTimeZoneKeyName | REG_SZ | The name of the Time Zones name sub key.\n\nNotes:\n\n* the relation between the local time and bias is as following:\n\n```\nUTC = local time + bias\n```\n\n* the names are stored outside the Windows Registry and are references using [MUI Form](https://winreg-kb.readthedocs.io/en/latest/sources/windows-registry/MUI-form.html)\nfor example:\n\n```\n@tzres.dll,-931\n```\n\n* the TimeZoneKeyName is not always present\n* The RealTimeIsUniversal value is not installed in the system by default and is not officially supported by Windows\n\nThe values in this key corresponds with the [TIME_ZONE_INFORMATION](https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-time_zone_information)\nand [DYNAMIC_TIME_ZONE_INFORMATION](https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-dynamic_time_zone_information)\nstructures.\n\n## Time Zones key\n\nThe time zones definitions are stored in the following key:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\n```\n\nSub keys:\n\nName | Description\n--- | ---\n%TIMEZONENAME% |\n\n%TIMEZONENAME% represents the name of the Windows name of the time zone. The\nUnicode organization maintains windowsZones.xml to map the Windows names to\ncorresponding IANA names.\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nTzVersion | REG_DWORD |\n\n### Time Zones %TIMEZONENAME% sub key\n\nSub keys:\n\nName | Description\n--- | ---\nDynamic DST | Contains the dynamic daylight saving time values\n\nNote that not every Time Zones name sub key contains a Dynamic Daylight Saving\nTime sub key (Dynamic DST).\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nDisplay | REG_SZ | The display name\nDlt | REG_SZ | The description for daylight time\nIndex | |\nMapID | |\nMUI_Display | REG_SZ | The display name in [MUI Form](https://winreg-kb.readthedocs.io/en/latest/sources/windows-registry/MUI-form.html)\nMUI_Dlt | REG_SZ | The description for daylight time in [MUI Form](https://winreg-kb.readthedocs.io/en/latest/sources/windows-registry/MUI-form.html)\nMUI_Std | REG_SZ | The description for standard time in [MUI Form](https://winreg-kb.readthedocs.io/en/latest/sources/windows-registry/MUI-form.html)\nStd | REG_SZ | The description for standard time\nTZI | REG_BINARY | Time zone information <br/> Contains a Registry Time Zone information structure\n\n#### Dynamic Daylight Saving Time sub key\n\nThe Dynamic Daylight Saving Time sub key contains time zone information for time zones that apply different daylight saving per year.\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nFirstEntry | REG_DWORD | The first year in the key\nLastEntry | REG_DWORD | The last year in the key\n%YEAR% | REG_BINARY | Time zone information <br/> Contains a Registry Time Zone information structure\n\nWhere %YEAR% represents the year the dynamic daylight saving time zone\ninformation applies to, e.g. 2006.\n\n### Data Structures\n\n#### SYSTEMTIME structure\n\nThe SYSTEMTIME structure is 16 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 2 | | Year\n2 | 2 | | Month <br/> Where 1 represents January\n4 | 2 | | Day of week <br/> Where 0 represents Sunday\n6 | 2 | | Day of month <br/> Where 1 represents the first day\n8 | 2 | | Hour <br/> Where hour ranges from 0 to 23\n10 | 2 | | Minutes <br/> Where minutes ranges from 0 to 59\n12 | 2 | | Seconds <br/> Where seconds ranges from 0 to 59\n14 | 2 | | Milli seconds <br/> Where milli seconds ranges from 0 to 999\n\n#### Registry Time Zone information structure\n\nThe Registry Time Zone information (`TIME_ZONE_INFORMATION` or\n`_REG_TZI_FORMAT`) structure is 44 bytes of size and consists of:\n\nOffset | Size | Value | Description\n--- | --- | --- | ---\n0 | 4 | | Bias <br/> Contains the difference between UTC and local time, in minutes\n4 | 4 | | StandardBias <br/> Contains the difference between UTC and local time, in minutes, or 0 if not set\n8 | 4 | | DaylightBias <br/>Contains the difference between standard and daylight savings time, in minutes <br/> The total difference is: Bias + DaylightBias\n12 | 16 | | StandardDate <br/> Date and time when the daylight savings time switches to standard time, in local time <br/> Contains a SYSTEMTIME structure with year set to 0\n28 | 16 | | DaylightDate <br/> Date and time when the standard time switches to daylight savings time, in local time <br/> Contains a SYSTEMTIME structure with year set to 0\n\nThe wDayOfWeek member of a SYSTEMTIME structure represents the appropriate\nweekday, and the wDay member represents the occurrence of the day of the week\nwithin the month, where 5 indicates the final occurrence during the month if\nthat day of the week only occurs 4 times in the month.\n\nIf the wYear member is 0, the date is relative, meaning the daylight savings\noccurs yearly. Otherwise the date is abosule, meaning daylight savings only\nchanges once.\n\nNote that DaylightBias can be set when DaylightDate is not set.\n\n## External Links\n\n* [Computer Time Management and Embedded Systems (Standard 7 SP1)](https://learn.microsoft.com/en-us/previous-versions/windows/embedded/ff794720(v=winembedded.60))\n* [TIME_ZONE_INFORMATION structure (timezoneapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-time_zone_information)\n* [DYNAMIC_TIME_ZONE_INFORMATION structure (timezoneapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-dynamic_time_zone_information)\n* [SYSTEMTIME structure (minwinbase.h)](https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime)\n* [windowsZones.xml](https://github.com/unicode-org/cldr/blob/main/common/supplemental/windowsZones.xml)\n\n"
  },
  {
    "path": "docs/sources/system-keys/USB-storage.md",
    "content": "# USB storage\n\nThe USBSTOR driver tracks various information about attached USB storage\ndevices in the key.\n\n```\nHKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Enum\\USBSTOR\n```\n\nThe USBSTOR key contains one or more device keys.\n\n## Device key\n\nThe name of the device key is formatted as:\n\n```\n<Device Type>&Ven_<Vendor>&Prod_<Product>&Rev_<Revision Number>\n```\n\nNote that the number of values in the name is variable.\n\nFor example: `Disk&Ven_&Prod_&Rev_0.00` or `Disk&Ven_&Prod_`\n\nThe device key contains one or more device instance keys.\n\n## Device instance key\n\nThe name of the device instance key is formatted as:\n\nFor example: `1002131402536a&0`\n\nSub keys:\n\nName | Description\n--- | ---\nDevice Parameters |\nLogConf |\nProperties |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nCapabilities | REG_DWORD_LITTLE_ENDIAN |\nClass | REG_SZ |\nClassGUID | REG_SZ |\nCompatibleIDs | REG_MULTI_SZ |\nConfigFlags | REG_DWORD_LITTLE_ENDIAN |\nContainerID | REG_SZ |\nDeviceDesc | REG_SZ |\nDriver | REG_SZ |\nFriendlyName | REG_SZ | Human readable description of the USB storage device\nHardwareID | REG_MULTI_SZ |\nMfg | REG_SZ | Manufacturer information\nService | REG_SZ |\n\n## Device Parameters key\n\nSub keys:\n\nName | Description\n--- | ---\nMediaChangeNotification |\nPartmgr |\n\n### Device Parameters\\Partmgr key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nAttributes | REG_DWORD_LITTLE_ENDIAN |\nDiskId | REG_SZ | Contains a GUID\n\n## LogConf key\n\n## Properties key\n\nSub keys:\n\nName | Description\n--- | ---\n%GUID% | Property set identifier\n\n### Property set key (Properties\\\\%GUID%)\n\nSub keys:\n\nName | Description\n--- | ---\n%NUMERIC% | Property identifier\n\n#### Property key (Properties\\\\%GUID%\\\\%NUMERIC%)\n\nSub keys:\n\nName | Description\n--- | ---\n%NUMERIC% |\n\n#### Property value key (Properties\\\\%GUID%\\\\%NUMERIC%\\\\%NUMERIC%)\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nData | REG_BINARY | Value data\nType | REG_BINARY | Value type\n\nValue type:\n\n* 0x0007 value data contains a 32-bit little-endian integer\n* 0x0010 value data contains a FILETIME\n* 0x0012 value data contains an UTF-16 litte-endian encoded string\n\n### Example\n\n```\nHKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Enum\\USBSTOR\\Disk&Ven_HP&Prod_v100w&Rev_1024\\AA951D0000007252&0\\Properties\\{540b947e-8b40-45bc-a8a2-6a0b894cbda2}\\00000004\\00000000\n\nProperty set: 540b947e-8b40-45bc-a8a2-6a0b894cbda2 (System.Devices)\nProperty identifier: 4 (PKEY_Device_BusReportedDeviceDesc)\nType: 0x00000012 (UTF-16 litte-endian encoded string)\nData: \"HP v100w USB Device\"\n```\n\n## External links\n\n* [USB device registry entries](https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/usb-device-specific-registry-settings)\n* [Identifiers Generated by USBSTOR.SYS](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-generated-by-usbstor-sys)\n* [DEVPKEY_Device_InstallDate](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/devpkey-device-installdate)\n* [DEVPKEY_Device_FirstInstallDate](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/devpkey-device-firstinstalldate)\n\n"
  },
  {
    "path": "docs/sources/system-keys/Volume-shadow-copies.md",
    "content": "# Volume shadow copies\n\n## FilesNotToSnapshot key\n\n```\nHKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\BackupRestore\\FilesNotToSnapshot\n```\n\nValue| Data type| Description\n--- | --- | ---\n| %NAME% | REG_MULTI_SZ | Where %NAME% contains an array of strings that contain the path of files that are excluded from being added to a volume shadow snapshot. <br/> The files paths can contain the * wildcard.\n\n## External Links\n\n* [Excluding Files from Shadow Copies](https://learn.microsoft.com/en-us/windows/win32/vss/excluding-files-from-shadow-copies)\n\n"
  },
  {
    "path": "docs/sources/system-keys/Windows-error-reporting.md",
    "content": "# Windows Error Reporting (WER) keys\n\n## Windows Error Reporting (WER) system key\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\Windows Error Reporting\n```\n\nSub keys:\n\nName | Description\n--- | ---\nAssert Filtering Policy |\nBrokerUp |\nConsent |\nDebug |\nHangs |\nHeapControlledList |\nLocalDumps |\nRuntimeExceptionHelperModules |\nWMR |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nBypassDataThrottling | REG_DWORD | Bypass WER client data throttling\nConfigureArchive | REG_DWORD | Archive only the parameters or all data\nEnableZip | REG_DWORD |\nErrorPort | REG_SZ |\nMachineID | |\nMaxQueueSizePercentage | |\nPurgeThreshholdValueInKB | |\nServiceTimeout | REG_DWORD |\n\n### BypassDataThrottling value\n\n0 - Disable data bypass throttling\n1 - Enable data bypass throttling\n\n### ConfigureArchive value\n\n1 - Parameters only (default on Windows 7)\n2 - All data (default on Windows Vista)\n\n### Consent sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nDefaultConsent | REG_DWORD | The default consent choice\nDefaultOverrideBehavior | REG_DWORD | The default consent overrides the vertical consent\nNewUserDefaultConsent | REG_DWORD |\n\n#### DefaultConsent value\n\n1 - Always ask (default)\n2 - Parameters only\n3 - Parameters and safe data\n4 - All data\n\n#### DefaultOverrideBehavior value\n\n0 - Vertical consent will override the default consent (default)\n1 - Default consent will override the application-specific consent|\n\n### Debug sub key\n\nSub keys:\n\nName | Description\n--- | ---\nUIHandles |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nStoreLocation | REG_SZ | Location of last report?\n\n#### UIHandles sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nCheckingForSolutionDialog | |\nCloseDialog | |\nFirstLevelConsentDialog | |\nRecoveryDialog | |\nRestartDialog | |\n\n### Hangs sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nNHRTimes | |\n\n### LocalDumps sub key\n\nPer-application setting can be define by an application-specific key under:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps\n```\n\nFor example an application-key for MyApplication.exe\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps\\MyApplication.exe\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nDumpCount | REG_DWORD | The maximum number of dump files in the folder. Older dump files are overwritten if the maximum has been reached. <br> By default: 10\nDumpFolder | REG_EXPAND_SZ | The path where the dump files are to be stored. <br> By default: %LOCALAPPDATA%\\CrashDumps\nDumpType | REG_DWORD | The dump type <br> By default: 1 (Mini dump)\nCustomDumpFlags | REG_DWORD | Custom dump flag when dump type is 0 (Custom dump).\n\n#### DumpType value\n\nValue | Description\n--- | ---\n0 | Custom dump\n1 | Mini dump (default)\n2 | Full dump\n\n#### CustomDumpFlags value\n\nThe CustomDumpFlags value contains a bitwise combination of the MINIDUMP_TYPE\nenumeration values.\n\n## Windows Error Reporting (WER) user key\n\n```\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Windows Error Reporting\n```\n\nSub keys:\n\nName | Description\n--- | ---\nConsent |\nHangs |\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nAutoApproveOSDumps | REG_DWORD |\nDisabled | REG_DWORD |\nDisableArchive | REG_DWORD |\nDisableQueue | REG_DWORD |\nDontSendAdditionalData | REG_DWORD |\nDontShowUI | REG_DWORD |\nForceQueue | REG_DWORD |\nLastCrashSelfReportTime | |\nLastQueuePesterTime | REG_QWORD_LITTLE_ENDIAN |\nLastResponsePesterTime | |\nLoggingDisabled | REG_DWORD |\nMaxArchiveCount | REG_DWORD |\nMaxQueueCount | REG_DWORD |\nMaxQueueSize | REG_DWORD |\n\n## Notes\n\n### Kernel faults sub key\n\nSub keys:\n\nName | Description\n--- | ---\nQueue |\n\n#### Queue sub key\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\n%FILENAME% | | Creation time of the minidump? <br> Contains a FILETIME\n\n```\nC:\\\\Windows\\\\Minidump\\\\MMDDYY-#-01.dmp\n```\n\n### Other\n\nC:\\Users\\%USERNAME%\\AppData\\Local\\Microsoft\\Windows\\WER\n\nSub directories:\n\nName | Description\n--- | ---\nERC |\nReportArchive |\nReportQueue |\n\n## External Links\n\n* [Collecting User-Mode Dumps](https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps)\n* [MINIDUMP_TYPE enumeration](https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ne-minidumpapiset-minidump_type)\n* [WER Settings](https://learn.microsoft.com/en-us/windows/win32/wer/wer-settings)\n"
  },
  {
    "path": "docs/sources/system-keys/Windows-product-information.md",
    "content": "# Windows product information\n\nWindows product information can be found in the key:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nBuildLab | REG_SZ |\nCSDVersion | REG_SZ | Service pack\nCurrentBuild | REG_SZ | Current build (obsolete) e.g. 1.511.1\nCurrentBuildNumber | REG_SZ | Current build number e.g. 2600\nCurrentType | REG_SZ |\nCurrentVersion | REG_SZ | Current major and minor version e.g. 5.1\nDigitalProductId | REG_BINARY |\nInstallDate | REG_LONG |\nLicenseInfo | REG_BINARY |\nPathName | REG_SZ | Windows path name e.g. C:\\Windows\nProductId | REG_SZ | Product identifier\nProductName | REG_SZ | Product name e.g Microsoft Windows XP\nRegDone | |\nRegisteredOrganization | REG_SZ | Registered organization\nRegisteredOwner | REG_SZ | Registered owner\nSoftwareType | REG_SZ | Software type e.g. SYSTEM\nSourcePath | REG_SZ |\nSubVersionNumber | |\nSystemRoot | REG_SZ | The system root also the value of %SystemRoot%\n\n"
  },
  {
    "path": "docs/sources/system-keys/Windows-system-locations.md",
    "content": "# Windows system locations\n\nWindows system locations can be found in the key:\n\n```\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\n```\n\nValues:\n\nName | Data type | Description\n--- | --- | ---\nCommonFilesDir | REG_SZ | path of the common program files directory, also set in the %CommomProgramFiles% environment variable\nCommonFilesDir (x86) | REG_SZ | path of the 32-bit common program directory folder on a 64-bit Windows installation, also set in the %CommomProgramFiles(x86)% environment variable\nDevicePath | REG_SZ |\nMediaPath | REG_SZ |\nMediaPathUnexpanded | REG_SZ |\nPF_AccessoriesName | |\nProductId | |\nProgramFilesDir | REG_SZ | path of the \"Program Files\" directory, also set in the %ProgramFiles% environment variable\nProgramFilesDir (x86) | REG_SZ | path of the 32-bit \"Program Files\" directory on a 64-bit Windows installation, also set in the %ProgramFiles(x86)% environment variable\nSM_AccessoriesName | |\nSM_ConfigureProgramsExisted | |\nSM_ConfigureProgramsName | |\nSM_GamesName | |\nWallPaperDir | REG_SZ |\n\n"
  },
  {
    "path": "docs/sources/system-keys/index.rst",
    "content": "###################\nWindows system keys\n###################\n\n.. toctree::\n   :maxdepth: 1\n\n   Application compatibility cache <Application-compatibility-cache>\n   Background activity moderator <Background-activity-moderator>\n   Boot verification <Boot-verification>\n   Cached credentials <Cached-credentials>\n   Certificates <Certificates>\n   Codepage <Codepage>\n   COM class identifiers <COM-class-identifiers>\n   Current control set <Current-control-set>\n   Environment variables <Environment-variables>\n   File system <File-system>\n   Language <Language>\n   Local security authority <Local-security-authority>\n   Mounted devices <Mounted-devices>\n   Prefetch <Prefetch>\n   Run and RunOnce <Run-and-RunOnce>\n   Services and drivers <Services-and-drivers>\n   Session manager <Session-manager>\n   Shell folder identifiers <Shell-folder-identifiers>\n   System restore <System-restore>\n   Task scheduler <Task-scheduler>\n   Time zones <Time-zones>\n   USB storage <USB-storage>\n   Volume shadow copies <Volume-shadow-copies>\n   Windows error reporting <Windows-error-reporting>\n   Windows product information <Windows-product-information>\n   Windows system locations <Windows-system-locations>\n"
  },
  {
    "path": "docs/sources/windows-registry/Files.md",
    "content": "# Windows Registry files\n\n## Windows Registry files - Windows 3.1\n\nOn Windows 3.1 the SHCC file format is used to store Windows Registry data.\n\nPaths of known Windows Registry files:\n\nFilename | Path | Description\n--- | --- | ---\nREG.DAT | %SystemRoot% | Entire registry\n\n## Windows Registry files - Windows 9x/Me\n\nOn Windows 9x/Me the [CREG](https://github.com/libyal/libcreg/blob/main/documentation/Windows%209x%20Registry%20File%20(CREG)%20format.asciidoc)\nfile format is used to store Windows Registry data.\n\nPaths of known Windows Registry files:\n\nFilename | Path | Description | Corresponding Registry Key\n--- | --- | --- | ---\nSYSTEM.DAT | %SystemRoot% | System specific part of the Registry | `HKEY_LOCAL_MACHINE`\nUSER.DAT | %SystemRoot% | User specific part of the Registry | `HKEY_USERS`\n\n### Root keys\n\nThe root key of both SYSTEM.DAT and USER.DAT contains an empty name string.\n\n## Windows Registry files - Windows NT\n\nOn Windows NT and later the [REGF](https://github.com/libyal/libregf/blob/main/documentation/Windows%20NT%20Registry%20File%20(REGF)%20format.asciidoc)\nfile format is used to store Windows Registry data.\n\nPaths of known Windows Registry files:\n\nFilename | Path | Description | Corresponding Registry Key | Windows version\n--- | --- | --- | --- | ---\nAmcache.hve | %SystemRoot%\\AppCompat\\Programs | *TODO* | | 8, 10\nBBI | %SystemRoot%\\System32\\config | *TODO* | | 10\nBCD | \\Boot or \\EFI\\Microsoft\\Boot (on boot volume) | Boot Configuration Data (BCD) | `HKEY_LOCAL_MACHINE\\BCD00000000` | Windows Vista and later\ndefault | %SystemRoot%\\System32\\config | *TODO* | | NT 4 and later\nDRIVERS | %SystemRoot%\\System32\\config | *TODO* | | 10\nELAM | %SystemRoot%\\System32\\config | *TODO* | | 10\nNTUSER.DAT | %UserProfile% | User specific part of the Registry | `HKEY_CURRENT_USER` | NT 4 and later\nNTUSER.MAN | %UserProfile% | Mandatory user specific part of the Registry | | NT 4 and later\nSAM | %SystemRoot%\\System32\\config | Security Account Manager (SAM) part of the Registry | `HKEY_LOCAL_MACHINE\\SAM` | NT 4 and later\nSECURITY | %SystemRoot%\\System32\\config | *TODO* | `HKEY_LOCAL_MACHINE\\Security` | NT 4 and later\nSOFTWARE | %SystemRoot%\\System32\\config | Software specific part of the Registry | `HKEY_LOCAL_MACHINE\\Software` | NT 4 and later\nSyscache.hve | System Volume Information | *TODO* | | 7, 2008\nSYSTEM | %SystemRoot%\\System32\\config | System specific part of the Registry | `HKEY_LOCAL_MACHINE\\System` | NT 4 and later\nuserdiff | %SystemRoot%\\System32\\config | *TODO* | | NT 4 and later\nUsrClass.dat | %UserProfile%\\Local Settings\\Application Data\\Microsoft\\Windows | `HKEY_CURRENT_USER\\Software\\Classes` | | 2000, XP, 2003\nUsrClass.dat | %UserProfile%\\AppData\\Local\\Microsoft\\Windows | File associations and COM Registry entries | `HKEY_CURRENT_USER\\Software\\Classes` | Vista and later\n\n*TODO Windows NT 3.1 user specific file under %SystemRoot%\\System32\\config*\n*TODO BCD check Windows 8 and 10*\n*TODO userdiff no longer present in Windows 10 ?*\n*TODO what about \\Windows\\profiles\\user profile\\user.dat ?*\n*TODO what about \\Windows\\System32\\SMI\\Store\\Machine\\SCHEMA.DAT (Windows 7)*\n\n### Root keys\n\nThe root key names of the different Windows Registry files differ per version\nof Windows.\n\n#### Root key - default\n\n*TODO*\n\n#### Root key - NTUSER.DAT\n\nWindows version | Root key name\n--- | ---\nNT 4 | .Default\n2000, XP, 2003 | $$$PROTO.HIV\nVista | CMI-CreateHive{B01E557D-7818-4BA7-9885-E6592398B44E}\n2008 | *TODO*\n2016 | *TODO*\n2019 | *TODO*\n7 | CMI-CreateHive{D43B12B8-09B5-40DB-B4F6-F6DFEB78DAEC}\n8 | CsiTool-CreateHive-{00000000-0000-0000-0000-000000000000}\n10 | ROOT\n\n#### Root key - SAM\n\nWindows version | Root key name\n--- | ---\nNT4, 2000, XP, 2003 | SAM\nVista | CMI-CreateHive{87E016C8-C811-4B12-9C3A-CDA552F3458D}\n2008 | *TODO*\n2016 | *TODO*\n2019 | *TODO*\n7 | CMI-CreateHive{C4E7BA2B-68E8-499C-B1A1-371AC8D717C7}\n8 | *TODO*\n10 | *TODO*\n\n#### Root key - SECURITY\n\nWindows version | Root key name\n--- | ---\nNT4, 2000, XP, 2003 | SECURITY\nVista | *TODO*\n2008 | *TODO*\n2016 | *TODO*\n2019 | *TODO*\n7 | *TODO*\n8 | *TODO*\n10 | *TODO*\n\n#### Root key - SOFTWARE\n\nWindows version | Root key name\n--- | ---\nNT4 | Software\n2000, XP | $$$PROTO.HIV\n2003 | *TODO*\nVista | CMI-CreateHive{29EE1162-53C9-4474-A2B6-D90A7F6B0A7C}\n2008 | *TODO*\n2016 | *TODO*\n2019 | *TODO*\n7 | CMI-CreateHive{199DAFC2-6F16-4946-BF90-5A3FC3A60902}\n8 | CsiTool-CreateHive-{00000000-0000-0000-0000-000000000000}\n10 | *TODO*\n\n#### Root key - Syscache.hve\n\nWindows version | Root key name\n--- | ---\n7, 2008 | {%GUID%}\n2016 | *TODO*\n2019 | *TODO*\n8 | *TODO*\n10 | *TODO*\n\nWhere {%GUID%} is a placeholder for a random GUID in the form: {00000000-0000-0000-0000-000000000000}\n\n*Note how consistent are the GUIDs icw CreateHive ?*\n\n#### Root key - SYSTEM\n\nWindows version | Root key name\n--- | ---\nNT4 | System\n2000, XP, 2003 | $$$PROTO.HIV\nVista | CMI-CreateHive{C619BFE8-791A-4B77-922B-F114AB570920}\n2008 | *TODO*\n7 | CMI-CreateHive{2A7FB991-7BBE-4F9D-B91E-7CB51D4737F5}\n8 | CsiTool-CreateHive-{00000000-0000-0000-0000-000000000000}\n\n#### Root key - userdiff\n\n*TODO*\n\n#### Root key - UsrClass.dat\n\nWindows version | Root key name\n--- | ---\n2000 | *TODO*\nXP | %SID%_Classes, where %SID%_Classes is a string of the SID of the user\n2003 | *TODO*\nVista, 7 | %SID%_Classes, where %SID%_Classes is a string of the SID of the user\n2008 | *TODO*\n2016 | *TODO*\n2019 | *TODO*\n8 | *TODO*\n10 | %SID%_Classes, where %SID%_Classes is a string of the SID of the user\n\n\n### Virtual keys\n\nWindows version | Key path | Description\n--- | --- | ---\n2000 and later | `HKEY_LOCAL_MACHINE\\System\\CurrentControlSet` | See [Current control set](../system-keys/Current-control-set.html)\n2000 and later | `HKEY_CURRENT_USER\\Software\\Classes` | Maps to UsrClass.dat\n2000 and later | `HKEY_CLASSES_ROOT` | Combination of system (`HKEY_LOCAL_MACHINE\\Software\\Classes`) and user-specific (`HKEY_CURRENT_USER\\Software\\Classes`) settings\nVista and later | `HKEY_CURRENT_USER\\Software\\Classes\\VirtualStore\\Machine\\Software` | User-specific changes to `HKEY_LOCAL_MACHINE\\Software`\n\n## External Links\n\n* [HKEY_CLASSES_ROOT Key](https://learn.microsoft.com/en-us/windows/win32/sysinfo/hkey-classes-root-key)\n* [Registry Virtualization](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-virtualization)\n"
  },
  {
    "path": "docs/sources/windows-registry/Hives.md",
    "content": "# Windows Registry hives\n\nName | Short name | Description\n--- | --- | ---\nHKEY_CLASSES_ROOT | HKCR | Used by Windows 3.1, 9x/Me and NT 4 and later <br> Refers to values in both HKEY_CURRENT_USER\\\\Software\\\\Classes and HKEY_LOCAL_MACHINE\\\\Software\\\\Classes\nHKEY_CURRENT_CONFIG | HKCC | Used by Windows 9x/Me and NT 4 and later <br> Refers to the current control set in HKLM\nHKEY_CURRENT_USER | HKCU | Information regarding the current active user <br> Used by Windows 9x/Me and NT 4 and later <br> Refers to the active user key in HKEY_USERS\nHKEY_DYN_DATA | | Dynamic data <br> Used by Windows 9x/Me\nHKEY_LOCAL_MACHINE | HKLM | Local settings <br>Used by Windows 9x/Me and NT 4 and later\nHKEY_PERFORMANCE_DATA | | Performance data <br> Used by Windows NT 4 and later\nHKEY_USERS | HKU | Information about all active users <br> Used by Windows 9x/Me and NT 4 and later\n\n"
  },
  {
    "path": "docs/sources/windows-registry/MUI-form.md",
    "content": "# Multilingual User Interface (MUI) form\n\nThe Multilingual User Interface (MUI) form is used to store strings in multiple\nlanguages. This is also known as Registry string redirection.\n\nThe actual strings are stored in the resource sections of PE/COFF files (also\nreferred to as resource file) e.g .exe, .dll.\n\nIn the Registry the MUI strings are referenced using the following form:\n\n```\n@path,-stringID[;comment]\n```\n\nWhere:\n\n* path; is the full path or filename of the resource file that contains the\nstring\n* stringID; the identifier of the string within the string resource of the\nresource file\n* comment; a comment\n\nFor example the MUI form string:\n\n```\n@%SystemRoot%\\system32\\SHELL32.dll,-9227\n```\n\nThis MUI form string refers to the string with identifier 9227, stored in the\nstring resource of SHELL32.dll. Which, for an English version of SHELL32.dll,\ncorresponds to: \"My Documents\".\n\nAn example of a MUI form with comment:\n\n```\n@wfplwfs.inf,%WfpLwfs_Name%;WFP LightWeight Filters\n```\n\n## Notes\n\nWhat about the form (seen in the Shell Folder value LocalizedString):\n\n```\n@%SystemRoot%\\System32\\fvecpl.dll,-1#immutable1\n```\n\nWhat does # represent here?\n\n```\n@wd.inf,%WdServiceDisplayName%;Microsoft Watchdog Timer Driver\n```\n\nYet another variation seen in Windows 2000.\n\n```\n@C:\\WINNT\\system32\\shell32.dll,-9227@1033,My Documents\n```\n\n## External Links\n\n* [Multilingual User Interface](https://learn.microsoft.com/en-us/windows/win32/intl/multilingual-user-interface)\n* [Using Registry String Redirection](https://learn.microsoft.com/en-us/windows/win32/intl/using-registry-string-redirection)\n\n"
  },
  {
    "path": "docs/sources/windows-registry/index.rst",
    "content": "################\nWindows Registry\n################\n\n.. toctree::\n   :maxdepth: 1\n\n   Hives <Hives>\n   Files <Files>\n   Multilingual User Interface (MUI) form <MUI-form>\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[build-system]\nrequires = [\"setuptools\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"winregrc\"\nversion = \"20260506\"\ndescription = \"Windows Registry resources (winregrc)\"\nmaintainers = [\n    { name = \"Joachim Metz\", email = \"joachim.metz@gmail.com\" },\n]\nlicense = \"Apache-2.0\"\nlicense-files = [\"ACKNOWLEDGEMENTS\", \"AUTHORS\", \"LICENSE\"]\nreadme = \"README.md\"\nclassifiers = [\n    \"Development Status :: 2 - Pre-Alpha\",\n    \"Programming Language :: Python\",\n]\nrequires-python = \">=3.10\"\ndependencies = [\n    \"PyYAML >= 3.10\",\n    \"acstore >= 20230101\",\n    \"artifacts >= 20220219\",\n    \"dfdatetime >= 20221112\",\n    \"dfimagetools >= 20240301\",\n    \"dfvfs >= 20240115\",\n    \"dfwinreg >= 20240229\",\n    \"dtfabric >= 20230518\",\n    \"libbde-python >= 20220121\",\n    \"libcaes-python >= 20240114\",\n    \"libcreg-python >= 20200725\",\n    \"libewf-python >= 20131210\",\n    \"libfcrypto-python >= 20240114\",\n    \"libfsapfs-python >= 20220709\",\n    \"libfsext-python >= 20220829\",\n    \"libfsfat-python >= 20220925\",\n    \"libfshfs-python >= 20220831\",\n    \"libfsntfs-python >= 20211229\",\n    \"libfsxfs-python >= 20220829\",\n    \"libfvde-python >= 20220121\",\n    \"libfwnt-python >= 20210717\",\n    \"libfwps-python >= 20240225\",\n    \"libfwsi-python >= 20240315\",\n    \"libhmac-python >= 20230205\",\n    \"libluksde-python >= 20220121\",\n    \"libmodi-python >= 20210405\",\n    \"libphdi-python >= 20220228\",\n    \"libqcow-python >= 20201213\",\n    \"libregf-python >= 20201002\",\n    \"libsigscan-python >= 20230109\",\n    \"libsmdev-python >= 20140529\",\n    \"libsmraw-python >= 20140612\",\n    \"libvhdi-python >= 20201014\",\n    \"libvmdk-python >= 20140421\",\n    \"libvsapm-python >= 20230506\",\n    \"libvsgpt-python >= 20211115\",\n    \"libvshadow-python >= 20160109\",\n    \"libvslvm-python >= 20160109\",\n    \"pytsk3 >= 20210419\",\n    \"xattr >= 0.7.2 ; platform_system != \\\"Windows\\\"\",\n]\n\n[project.scripts]\nappcompatcache = \"winregrc.scripts.appcompatcache:Main\"\napplication_identifiers = \"winregrc.scripts.application_identifiers:Main\"\ncached_credentials = \"winregrc.scripts.cached_credentials:Main\"\ncatalog = \"winregrc.scripts.catalog:Main\"\ncontrolpanel_items = \"winregrc.scripts.controlpanel_items:Main\"\ndelegatefolders = \"winregrc.scripts.delegatefolders:Main\"\nenvironment_variables = \"winregrc.scripts.environment_variables:Main\"\neventlog_providers = \"winregrc.scripts.eventlog_providers:Main\"\nknownfolders = \"winregrc.scripts.knownfolders:Main\"\nmounted_devices = \"winregrc.scripts.mounted_devices:Main\"\nmru = \"winregrc.scripts.mru:Main\"\nmsie_zone_info = \"winregrc.scripts.msie_zone_info:Main\"\nprofiles = \"winregrc.scripts.profiles:Main\"\nprogramscache = \"winregrc.scripts.programscache:Main\"\nsam = \"winregrc.scripts.sam:Main\"\nservices = \"winregrc.scripts.services:Main\"\nshellfolders = \"winregrc.scripts.shellfolders:Main\"\nsrum_extensions = \"winregrc.scripts.srum_extensions:Main\"\nsysinfo = \"winregrc.scripts.sysinfo:Main\"\nsyskey = \"winregrc.scripts.syskey:Main\"\ntask_cache = \"winregrc.scripts.task_cache:Main\"\ntime_zones = \"winregrc.scripts.time_zones:Main\"\ntype_libraries = \"winregrc.scripts.type_libraries:Main\"\nusbstor = \"winregrc.scripts.usbstor:Main\"\nuserassist = \"winregrc.scripts.userassist:Main\"\n\n[project.urls]\nDocumentation = \"https://winregrc.readthedocs.io/en/latest\"\nHomepage = \"https://github.com/libyal/winreg-kb\"\nRepository = \"https://github.com/libyal/winreg-kb\"\n\n[tool.setuptools]\npackage-dir = {\"winregrc\" = \"winregrc\"}\n\n[tool.setuptools.package-data]\nwinregrc = [\n    \"*.yaml\",\n    \"data/*.yaml\",\n]\n"
  },
  {
    "path": "run_tests.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to run the tests.\"\"\"\n\nimport sys\nimport unittest\n\n# Change PYTHONPATH to include winregrc.\nsys.path.insert(0, '.')\n\nimport utils.dependencies  # pylint: disable=wrong-import-position\n\n\nif __name__ == '__main__':\n  fail_unless_has_test_file = '--fail-unless-has-test-file' in sys.argv\n  setattr(unittest, 'fail_unless_has_test_file', fail_unless_has_test_file)\n  if fail_unless_has_test_file:\n    # Remove --fail-unless-has-test-file otherwise it will conflict with\n    # the argparse tests.\n    sys.argv.remove('--fail-unless-has-test-file')\n\n  dependency_helper = utils.dependencies.DependencyHelper()\n\n  if not dependency_helper.CheckTestDependencies():\n    sys.exit(1)\n\n  test_suite = unittest.TestLoader().discover('tests', pattern='*.py')\n  test_results = unittest.TextTestRunner(verbosity=2).run(test_suite)\n  if not test_results.wasSuccessful():\n    sys.exit(1)\n"
  },
  {
    "path": "test_dependencies.ini",
    "content": ""
  },
  {
    "path": "tests/__init__.py",
    "content": ""
  },
  {
    "path": "tests/appcompatcache.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Application Compatibility Cache collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import appcompatcache\nfrom winregrc import output_writers\n\nfrom tests import test_lib\n\n\n_CACHE_DATA_WINDOWS_XP = bytes(bytearray([\n    0xef, 0xbe, 0xad, 0xde, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,\n    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x5c, 0x00,\n    0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x49, 0x00, 0x4e, 0x00,\n    0x44, 0x00, 0x4f, 0x00, 0x57, 0x00, 0x53, 0x00, 0x5c, 0x00, 0x73, 0x00,\n    0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x33, 0x00,\n    0x32, 0x00, 0x5c, 0x00, 0x68, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00,\n    0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x6c, 0x00,\n    0x6c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x6e, 0x00,\n    0x6c, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x64, 0x00, 0x5c, 0x00, 0x62, 0x00,\n    0x37, 0x00, 0x66, 0x00, 0x30, 0x00, 0x62, 0x00, 0x32, 0x00, 0x38, 0x00,\n    0x39, 0x00, 0x32, 0x00, 0x62, 0x00, 0x32, 0x00, 0x31, 0x00, 0x32, 0x00,\n    0x31, 0x00, 0x31, 0x00, 0x61, 0x00, 0x35, 0x00, 0x36, 0x00, 0x33, 0x00,\n    0x30, 0x00, 0x35, 0x00, 0x31, 0x00, 0x38, 0x00, 0x64, 0x00, 0x30, 0x00,\n    0x35, 0x00, 0x38, 0x00, 0x66, 0x00, 0x34, 0x00, 0x38, 0x00, 0x64, 0x00,\n    0x39, 0x00, 0x5c, 0x00, 0x75, 0x00, 0x70, 0x00, 0x64, 0x00, 0x61, 0x00,\n    0x74, 0x00, 0x65, 0x00, 0x5c, 0x00, 0x75, 0x00, 0x70, 0x00, 0x64, 0x00,\n    0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00,\n    0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xe9, 0x54, 0x2b, 0x7a, 0xc4, 0x01,\n    0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xd3, 0x0e, 0xc7,\n    0xe9, 0x39, 0xca, 0x01\n]))\n\n_CACHE_DATA_WINDOWS_2003 = bytes(bytearray([\n    0xfe, 0x0f, 0xdc, 0xba, 0x01, 0x00, 0x00, 0x00, 0x72, 0x00, 0x74, 0x00,\n    0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x86, 0x76, 0x44, 0xf2, 0xc2, 0x01,\n    0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x3f, 0x00,\n    0x3f, 0x00, 0x5c, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x57, 0x00,\n    0x49, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x4f, 0x00, 0x57, 0x00, 0x53, 0x00,\n    0x5c, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00,\n    0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x4e, 0x00,\n    0x45, 0x00, 0x54, 0x00, 0x5c, 0x00, 0x46, 0x00, 0x72, 0x00, 0x61, 0x00,\n    0x6d, 0x00, 0x65, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6b, 0x00,\n    0x5c, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x2e, 0x00,\n    0x34, 0x00, 0x33, 0x00, 0x32, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x6e, 0x00,\n    0x67, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00,\n    0x65, 0x00, 0x00, 0x00\n]))\n\n_CACHE_DATA_WINDOWS_VISTA = bytes(bytearray([\n    0xfe, 0x0f, 0xdc, 0xba, 0x01, 0x00, 0x00, 0x00, 0x46, 0x00, 0x48, 0x00,\n    0x20, 0x00, 0x00, 0x00, 0xc2, 0xfe, 0x87, 0x5e, 0x7b, 0xfe, 0xc6, 0x01,\n    0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x3f, 0x00,\n    0x3f, 0x00, 0x5c, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x57, 0x00,\n    0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00,\n    0x5c, 0x00, 0x53, 0x00, 0x59, 0x00, 0x53, 0x00, 0x54, 0x00, 0x45, 0x00,\n    0x4d, 0x00, 0x33, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x49, 0x00,\n    0x53, 0x00, 0x50, 0x00, 0x54, 0x00, 0x49, 0x00, 0x53, 0x00, 0x2e, 0x00,\n    0x45, 0x00, 0x58, 0x00, 0x45, 0x00, 0x00, 0x00\n]))\n\n_CACHE_DATA_WINDOWS_8_0 = bytes(bytearray([\n    0x80, 0x00, 0x00, 0x00, 0x2e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,\n    0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x74, 0x73,\n    0x9e, 0x6b, 0x3c, 0x8a, 0x68, 0x00, 0x00, 0x00, 0x52, 0x00, 0x53, 0x00,\n    0x59, 0x00, 0x53, 0x00, 0x56, 0x00, 0x4f, 0x00, 0x4c, 0x00, 0x5c, 0x00,\n    0x57, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00,\n    0x73, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00,\n    0x65, 0x00, 0x6d, 0x00, 0x33, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x77, 0x00,\n    0x62, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x6d, 0x00,\n    0x69, 0x00, 0x50, 0x00, 0x72, 0x00, 0x76, 0x00, 0x53, 0x00, 0x45, 0x00,\n    0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x43, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x01, 0xf0, 0xa4, 0xa4, 0xbc, 0xfc, 0xed, 0xcc, 0x01,\n    0x00, 0x00, 0x00, 0x00\n]))\n\n_CACHE_DATA_WINDOWS_8_1 = bytes(bytearray([\n    0x80, 0x00, 0x00, 0x00, 0x09, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x09, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x46, 0x15, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,\n    0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x38, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x30, 0x74, 0x73,\n    0xbc, 0x4c, 0xa0, 0x05, 0x5e, 0x00, 0x00, 0x00, 0x46, 0x00, 0x53, 0x00,\n    0x59, 0x00, 0x53, 0x00, 0x56, 0x00, 0x4f, 0x00, 0x4c, 0x00, 0x5c, 0x00,\n    0x57, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00,\n    0x73, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00,\n    0x65, 0x00, 0x6d, 0x00, 0x33, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x64, 0x00,\n    0x6c, 0x00, 0x6c, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x74, 0x00,\n    0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x00, 0x00, 0x7f, 0x00,\n    0x00, 0x00, 0x00, 0x11, 0x00, 0x01, 0xb5, 0x1f, 0x73, 0x13, 0x34, 0x9f,\n    0xce, 0x01, 0x00, 0x00, 0x00, 0x00\n]))\n\n_CACHE_DATA_WINDOWS_10 = bytes(bytearray([\n    0x30, 0x00, 0x00, 0x00, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0xc9, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x31, 0x30, 0x74, 0x73, 0x64, 0x7e, 0xcd, 0xc9, 0xcc, 0x00, 0x00, 0x00,\n    0x42, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x69, 0x00,\n    0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x5c, 0x00,\n    0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00,\n    0x33, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x4d, 0x00, 0x70, 0x00, 0x53, 0x00,\n    0x69, 0x00, 0x67, 0x00, 0x53, 0x00, 0x74, 0x00, 0x75, 0x00, 0x62, 0x00,\n    0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x80, 0x99, 0xe3, 0x66,\n    0x30, 0xd6, 0xcf, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,\n    0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,\n    0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,\n    0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,\n    0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00\n]))\n\n_CACHE_DATA_WINDOWS_10_CREATOR = bytes(bytearray([\n    0x34, 0x00, 0x00, 0x00, 0x1a, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x53, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x7a, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x31, 0x30, 0x74, 0x73, 0xd5, 0xf1, 0x23, 0x93,\n    0xd4, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00,\n    0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x72, 0x00, 0x61, 0x00,\n    0x6d, 0x00, 0x20, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00,\n    0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x78, 0x00, 0x38, 0x00, 0x36, 0x00,\n    0x29, 0x00, 0x5c, 0x00, 0x4e, 0x00, 0x56, 0x00, 0x49, 0x00, 0x44, 0x00,\n    0x49, 0x00, 0x41, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x72, 0x00,\n    0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00,\n    0x6f, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x33, 0x00, 0x44, 0x00, 0x20, 0x00,\n    0x56, 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00,\n    0x5c, 0x00, 0x6e, 0x00, 0x76, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,\n    0x65, 0x00, 0x67, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00,\n    0xe9, 0x09, 0x99, 0x7b, 0xa8, 0x9e, 0xd2, 0x01, 0x48, 0x00, 0x00, 0x00,\n    0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00,\n    0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,\n    0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,\n    0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00\n]))\n\n\nclass TestOutputWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Output writer for testing.\n\n  Attributes:\n    cached_entries (list[AppCompatCacheCachedEntry]): Application Compatibility\n        Cache cached entries.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes an output writer object.\"\"\"\n    super().__init__()\n    self.cached_entries = []\n\n  def WriteCachedEntry(self, cached_entry):\n    \"\"\"Writes the Application Compatibility Cache cached entry to stdout.\n\n    Args:\n      cached_entry (AppCompatCacheCachedEntry): Application Compatibility\n          Cache cached entry.\n    \"\"\"\n    self.cached_entries.append(cached_entry)\n\n\nclass AppCompatCacheDataParserTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the Application Compatibility Cache data parser.\"\"\"\n\n  # pylint: disable=protected-access\n\n  def testCheckSignature(self):\n    \"\"\"Tests the CheckSignature function.\"\"\"\n    parser = appcompatcache.AppCompatCacheDataParser()\n\n    format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_XP)\n    self.assertEqual(format_type, parser._FORMAT_TYPE_XP)\n\n    format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_2003)\n    self.assertEqual(format_type, parser._FORMAT_TYPE_2003)\n\n    format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_VISTA)\n    # TODO: add support to detect Vista format.\n    self.assertEqual(format_type, parser._FORMAT_TYPE_2003)\n\n    # TODO: add Windows 7 test.\n\n    format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_8_0)\n    self.assertEqual(format_type, parser._FORMAT_TYPE_8)\n\n    format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_8_1)\n    self.assertEqual(format_type, parser._FORMAT_TYPE_8)\n\n    format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_10)\n    self.assertEqual(format_type, parser._FORMAT_TYPE_10)\n\n    format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_10_CREATOR)\n    self.assertEqual(format_type, parser._FORMAT_TYPE_10)\n\n    # TODO: add bogus data tests.\n\n  def testParseHeader(self):\n    \"\"\"Tests the ParseHeader function.\"\"\"\n    parser = appcompatcache.AppCompatCacheDataParser()\n\n    header_object = parser.ParseHeader(\n        parser._FORMAT_TYPE_XP, _CACHE_DATA_WINDOWS_XP)\n    self.assertIsNotNone(header_object)\n\n    header_object = parser.ParseHeader(\n        parser._FORMAT_TYPE_2003, _CACHE_DATA_WINDOWS_2003)\n    self.assertIsNotNone(header_object)\n\n    # TODO: fix Vista support.\n    # header_object = parser.ParseHeader(\n    #     parser._FORMAT_TYPE_VISTA, _CACHE_DATA_WINDOWS_VISTA)\n    # self.assertIsNotNone(header_object)\n\n    # TODO: add Windows 7 test.\n\n    header_object = parser.ParseHeader(\n        parser._FORMAT_TYPE_8, _CACHE_DATA_WINDOWS_8_0)\n    self.assertIsNotNone(header_object)\n\n    header_object = parser.ParseHeader(\n        parser._FORMAT_TYPE_8, _CACHE_DATA_WINDOWS_8_1)\n    self.assertIsNotNone(header_object)\n\n    header_object = parser.ParseHeader(\n        parser._FORMAT_TYPE_10, _CACHE_DATA_WINDOWS_10)\n    self.assertIsNotNone(header_object)\n\n    # TODO: add bogus data tests.\n\n\nclass AppCompatCacheCollectorTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the Application Compatibility Cache collector.\"\"\"\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\System'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('Select')\n    registry_file.AddKeyByPath('\\\\', registry_key)\n\n    value_data = b'\\x01\\x00\\x00\\x00'\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'Current', data=value_data, data_type=dfwinreg_definitions.REG_DWORD)\n    registry_key.AddValue(registry_value)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('AppCompatibility')\n    registry_file.AddKeyByPath(\n        '\\\\ControlSet001\\\\Control\\\\Session Manager', registry_key)\n\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'AppCompatCache', data=_CACHE_DATA_WINDOWS_XP,\n        data_type=dfwinreg_definitions.REG_BINARY)\n    registry_key.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    test_output_writer = TestOutputWriter()\n    collector_object = appcompatcache.AppCompatCacheCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry, all_control_sets=True)\n    self.assertTrue(result)\n\n    test_output_writer.Close()\n\n    self.assertEqual(len(collector_object.cached_entries), 1)\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    test_output_writer = TestOutputWriter()\n    collector_object = appcompatcache.AppCompatCacheCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertFalse(result)\n\n    test_output_writer.Close()\n\n    self.assertEqual(len(collector_object.cached_entries), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/application_identifiers.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Windows application identifiers (AppID) collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import application_identifiers\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass ApplicationIdentifiersCollectorTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows application identifiers (AppID) collector.\"\"\"\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\Software'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(\n        '{fd6c8b29-e936-4a61-8da6-b0c12ad3ba00}')\n    registry_file.AddKeyByPath('\\\\Classes\\\\AppID', registry_key)\n\n    value_data = 'Wordpad'.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        '', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    collector_object = application_identifiers.ApplicationIdentifiersCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 1)\n\n    application_identifier = test_results[0]\n    self.assertIsNotNone(application_identifier)\n    self.assertEqual(application_identifier.description, 'Wordpad')\n    self.assertEqual(\n        application_identifier.guid, '{fd6c8b29-e936-4a61-8da6-b0c12ad3ba00}')\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    collector_object = application_identifiers.ApplicationIdentifiersCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/cached_credentials.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the domain cached credentials collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import cached_credentials\nfrom winregrc import output_writers\n\nfrom tests import test_lib\n\n\nclass TestOutputWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Output writer for testing.\n\n  Attributes:\n    cached_entries (list[AppCompatCacheCachedEntry]): Application Compatibility\n        Cache cached entries.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes an output writer object.\"\"\"\n    super().__init__()\n    self.cached_entries = []\n\n  def WriteCachedEntry(self, cached_entry):\n    \"\"\"Writes the Application Compatibility Cache cached entry to stdout.\n\n    Args:\n      cached_entry (AppCompatCacheCachedEntry): Application Compatibility\n          Cache cached entry.\n    \"\"\"\n    self.cached_entries.append(cached_entry)\n\n\nclass CachedCredentialsKeyCollectorTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the Application Compatibility Cache collector.\"\"\"\n\n  # pylint: disable=protected-access\n\n  _NL_KEY_MATERIAL_DATA = bytes(bytearray([\n      0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x20, 0x9c, 0xc3, 0x0c, 0x00,\n      0xc2, 0x0d, 0x08, 0x10, 0x9a, 0x04, 0x04, 0xbf, 0x14, 0x8b, 0xc7, 0xd0,\n      0x0b, 0xe2, 0x9c, 0x40, 0x52, 0xa7, 0x8e, 0xaa, 0x01, 0x49, 0x25, 0x70,\n      0x71, 0xdc, 0xa0, 0x69, 0x8e, 0x6c, 0x03, 0x1c, 0xb7, 0xdb, 0x19, 0x5c,\n      0x8f, 0xf4, 0x11, 0xd1, 0x8d, 0x73, 0x07, 0xb0, 0x6f, 0x1a, 0xdb, 0x0b,\n      0xee, 0xcb, 0x69, 0x7f, 0x73, 0x50, 0x24, 0x82, 0xf8, 0xe1, 0xa6, 0x27,\n      0x97, 0xa9, 0xcc, 0x04, 0x8e, 0xe4, 0xca, 0xbb, 0x33, 0x68, 0x00, 0x7c]))\n\n  _POLICY_ENCRYPTION_DATA = bytes(bytearray([\n      0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0xfd, 0xd4, 0x3f, 0xb3, 0xee, 0x4f, 0xcd, 0x45, 0x2d, 0x02, 0xe8, 0x1e,\n      0xf2, 0xac, 0xbd, 0x4f, 0xfc, 0x15, 0x12, 0x09, 0x0a, 0xb5, 0x48, 0x17,\n      0x33, 0x8f, 0x42, 0x79, 0x8b, 0x89, 0x11, 0xd8, 0xec, 0x6e, 0x1c, 0xec,\n      0x38, 0x5f, 0x27, 0xdf, 0x72, 0xca, 0x57, 0x96, 0x8d, 0x16, 0xd9, 0x37,\n      0xc4, 0x14, 0x64, 0xd1, 0xa8, 0x47, 0x7a, 0xd4, 0x4b, 0xa3, 0x62, 0xd8,\n      0xe7, 0x2b, 0xef, 0x76]))\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\Security'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('Cache')\n    registry_file.AddKeyByPath('\\\\', registry_key)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('PolSecretEncryptionKey')\n    registry_file.AddKeyByPath('\\\\Policy', registry_key)\n\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        '', data=self._POLICY_ENCRYPTION_DATA,\n        data_type=dfwinreg_definitions.REG_BINARY)\n    registry_key.AddValue(registry_value)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('CurrVal')\n    registry_file.AddKeyByPath('\\\\Policy\\\\Secrets\\\\NL$KM', registry_key)\n\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        '', data=self._NL_KEY_MATERIAL_DATA,\n        data_type=dfwinreg_definitions.REG_BINARY)\n    registry_key.AddValue(registry_value)\n\n    registry_file.Open(None)\n    registry.MapFile(key_path_prefix, registry_file)\n\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\System'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(\n        'Data', class_name='902a3f2c')\n    registry_file.AddKeyByPath(\n        '\\\\CurrentControlSet\\\\Control\\\\Lsa', registry_key)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(\n        'GBG', class_name='c0d054a4')\n    registry_file.AddKeyByPath(\n        '\\\\CurrentControlSet\\\\Control\\\\Lsa', registry_key)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('JD', class_name='1ae33251')\n    registry_file.AddKeyByPath(\n        '\\\\CurrentControlSet\\\\Control\\\\Lsa', registry_key)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(\n        'Skew1', class_name='be6a589c')\n    registry_file.AddKeyByPath(\n        '\\\\CurrentControlSet\\\\Control\\\\Lsa', registry_key)\n\n    registry_file.Open(None)\n    registry.MapFile(key_path_prefix, registry_file)\n\n    return registry\n\n  def testGetBootKey(self):\n    \"\"\"Tests the _GetBootKey function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    collector_object = cached_credentials.CachedCredentialsKeyCollector()\n\n    boot_key = collector_object._GetBootKey(registry)\n    self.assertEqual(boot_key, b'\\xc0j\\xbe2\\xa4\\xd0*Q\\x1aX\\xe3\\x90?T,\\x9c')\n\n  def testGetLSAKey(self):\n    \"\"\"Tests the _GetLSAKey function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    collector_object = cached_credentials.CachedCredentialsKeyCollector()\n\n    lsa_key = collector_object._GetLSAKey(\n        registry, b'\\xc0j\\xbe2\\xa4\\xd0*Q\\x1aX\\xe3\\x90?T,\\x9c')\n    self.assertEqual(lsa_key, b'\\x01\\xd6]\\xf4C\\xaa\\n\\x86\\xd9B\\xd1\\x174\\xcef|')\n\n  def testGetNLKey(self):\n    \"\"\"Tests the _GetNLKey function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    collector_object = cached_credentials.CachedCredentialsKeyCollector()\n\n    expected_nl_key = (\n        b'\\t\\xfeDH\\x1b5s\\xb7;\\x1d\\xfc\\xf7H\\x9f\\xc9`;`}\\xcfb5P\\xfd\\xb5\\xd8\\x8f!u'\n        b'\\xec\\x01\\xe9\\x85%\\x96lhR\\xc90\\xfb\\x1d\\xb6\\x9d\\xcd\\x8c\\x14\\x90\\x91\\xde'\n        b'\\xf1\\xdd]\\xd7d*\\xce@\\x97Z\\xf1Yq ')\n\n    nl_key = collector_object._GetNLKey(\n        registry, b'\\x01\\xd6]\\xf4C\\xaa\\n\\x86\\xd9B\\xd1\\x174\\xcef|')\n    self.assertEqual(nl_key, expected_nl_key)\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    test_output_writer = TestOutputWriter()\n    collector_object = cached_credentials.CachedCredentialsKeyCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertTrue(result)\n\n    test_output_writer.Close()\n\n    # TODO:\n    # self.assertEqual(len(collector_object.cached_entries), 1)\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    test_output_writer = TestOutputWriter()\n    collector_object = cached_credentials.CachedCredentialsKeyCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertFalse(result)\n\n    test_output_writer.Close()\n\n    # TODO:\n    # self.assertEqual(len(collector_object.cached_entries), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/data_format.py",
    "content": "\"\"\"Tests for binary data format and file.\"\"\"\n\nimport io\nimport unittest\n\nfrom dtfabric import errors as dtfabric_errors\nfrom dtfabric.runtime import data_maps as dtfabric_data_maps\nfrom dtfabric.runtime import fabric as dtfabric_fabric\n\nfrom winregrc import data_format\nfrom winregrc import errors\n\nfrom tests import test_lib\n\n\nclass ErrorBytesIO(io.BytesIO):\n  \"\"\"Bytes IO that errors.\"\"\"\n\n  # The following methods are part of the file-like object interface.\n  # pylint: disable=invalid-name\n\n  def read(self, size=None):  # pylint: disable=redundant-returns-doc,unused-argument\n    \"\"\"Reads bytes.\n\n    Args:\n      size (Optional[int]): number of bytes to read, where None represents\n          all remaining bytes.\n\n    Returns:\n      bytes: bytes read.\n\n    Raises:\n      OSError: for testing.\n    \"\"\"\n    raise OSError('Unable to read for testing purposes.')\n\n\nclass ErrorDataTypeMap(dtfabric_data_maps.DataTypeMap):\n  \"\"\"Data type map that errors.\"\"\"\n\n  # pylint: disable=redundant-returns-doc\n\n  def FoldByteStream(self, mapped_value, **unused_kwargs):\n    \"\"\"Folds the data type into a byte stream.\n\n    Args:\n      mapped_value (object): mapped value.\n\n    Returns:\n      bytes: byte stream.\n\n    Raises:\n      FoldingError: if the data type definition cannot be folded into\n          the byte stream.\n    \"\"\"\n    raise dtfabric_errors.FoldingError(\n        'Unable to fold to byte stream for testing purposes.')\n\n  def MapByteStream(self, byte_stream, **unused_kwargs):\n    \"\"\"Maps the data type on a byte stream.\n\n    Args:\n      byte_stream (bytes): byte stream.\n\n    Returns:\n      object: mapped value.\n\n    Raises:\n      dtfabric.MappingError: if the data type definition cannot be mapped on\n          the byte stream.\n    \"\"\"\n    raise dtfabric_errors.MappingError(\n        'Unable to map byte stream for testing purposes.')\n\n\nclass BinaryDataFormatTest(test_lib.BaseTestCase):\n  \"\"\"Binary data format tests.\"\"\"\n\n  # pylint: disable=protected-access\n\n  _DATA_TYPE_FABRIC_DEFINITION = b\"\"\"\\\nname: uint32\ntype: integer\nattributes:\n  format: unsigned\n  size: 4\n  units: bytes\n---\nname: point3d\ntype: structure\nattributes:\n  byte_order: little-endian\nmembers:\n- name: x\n  data_type: uint32\n- name: y\n  data_type: uint32\n- name: z\n  data_type: uint32\n---\nname: shape3d\ntype: structure\nattributes:\n  byte_order: little-endian\nmembers:\n- name: number_of_points\n  data_type: uint32\n- name: points\n  type: sequence\n  element_data_type: point3d\n  number_of_elements: shape3d.number_of_points\n\"\"\"\n\n  _DATA_TYPE_FABRIC = dtfabric_fabric.DataTypeFabric(\n      yaml_definition=_DATA_TYPE_FABRIC_DEFINITION)\n\n  def testDebugPrintData(self):\n    \"\"\"Tests the _DebugPrintData function.\"\"\"\n    output_writer = test_lib.TestOutputWriter()\n    test_format = data_format.BinaryDataFormat(\n        output_writer=output_writer)\n\n    data = b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06'\n    test_format._DebugPrintData('Description', data)\n\n    expected_output = [\n        'Description:\\n',\n        ('0x00000000  00 01 02 03 04 05 06                              '\n         '.......\\n\\n')]\n    self.assertEqual(output_writer.output, expected_output)\n\n  def testDebugPrintDecimalValue(self):\n    \"\"\"Tests the _DebugPrintDecimalValue function.\"\"\"\n    output_writer = test_lib.TestOutputWriter()\n    test_format = data_format.BinaryDataFormat(\n        output_writer=output_writer)\n\n    test_format._DebugPrintDecimalValue('Description', 1)\n\n    expected_output = ['Description\\t\\t\\t\\t\\t\\t\\t\\t: 1\\n']\n    self.assertEqual(output_writer.output, expected_output)\n\n  # TODO add tests for _DebugPrintFiletimeValue\n\n  def testDebugPrintValue(self):\n    \"\"\"Tests the _DebugPrintValue function.\"\"\"\n    output_writer = test_lib.TestOutputWriter()\n    test_format = data_format.BinaryDataFormat(\n        output_writer=output_writer)\n\n    test_format._DebugPrintValue('Description', 'Value')\n\n    expected_output = ['Description\\t\\t\\t\\t\\t\\t\\t\\t: Value\\n']\n    self.assertEqual(output_writer.output, expected_output)\n\n  def testDebugPrintText(self):\n    \"\"\"Tests the _DebugPrintText function.\"\"\"\n    output_writer = test_lib.TestOutputWriter()\n    test_format = data_format.BinaryDataFormat(\n        output_writer=output_writer)\n\n    test_format._DebugPrintText('Text')\n\n    expected_output = ['Text']\n    self.assertEqual(output_writer.output, expected_output)\n\n  # TODO: add tests for _GetDataTypeMap\n  # TODO: add tests for _ReadDefinitionFile\n\n  def testReadStructureFromByteStream(self):\n    \"\"\"Tests the _ReadStructureFromByteStream function.\"\"\"\n    output_writer = test_lib.TestOutputWriter()\n    test_format = data_format.BinaryDataFormat(\n        debug=True, output_writer=output_writer)\n\n    data_type_map = self._DATA_TYPE_FABRIC.CreateDataTypeMap('point3d')\n\n    test_format._ReadStructureFromByteStream(\n        b'\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x00\\x00', 0,\n        data_type_map, 'point3d')\n\n    # Test with missing byte stream.\n    with self.assertRaises(ValueError):\n      test_format._ReadStructureFromByteStream(\n          None, 0, data_type_map, 'point3d')\n\n    # Test with missing data map type.\n    with self.assertRaises(ValueError):\n      test_format._ReadStructureFromByteStream(\n          b'\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x00\\x00', 0, None,\n          'point3d')\n\n    # Test with data type map that raises an dtfabric.MappingError.\n    data_type_map = ErrorDataTypeMap(None)\n\n    with self.assertRaises(errors.ParseError):\n      test_format._ReadStructureFromByteStream(\n          b'\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x00\\x00', 0,\n          data_type_map, 'point3d')\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/environment_variables.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the environment variables collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import environment_variables\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass EnvironmentVariablesCollectorTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the environment variables collector.\"\"\"\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\System'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('Environment')\n    registry_file.AddKeyByPath(\n        '\\\\CurrentControlSet\\\\Control\\\\Session Manager', registry_key)\n\n    value_data = '%SystemRoot%\\\\TEMP'.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'TEMP', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    collector_object = environment_variables.EnvironmentVariablesCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 1)\n\n    environment_variable = test_results[0]\n    self.assertIsNotNone(environment_variable)\n    self.assertEqual(environment_variable.name, '%TEMP%')\n    self.assertEqual(environment_variable.value, '%SystemRoot%\\\\TEMP')\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    collector_object = environment_variables.EnvironmentVariablesCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/eventlog_providers.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Windows Event Log providers collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import regf as dfwinreg_regf\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import eventlog_providers\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass EventLogProvidersCollectorTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows Event Log providers collector.\"\"\"\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    software_test_path = self._GetTestFilePath(['SOFTWARE'])\n    self._SkipIfPathNotExists(software_test_path)\n\n    system_test_path = self._GetTestFilePath(['SYSTEM'])\n    self._SkipIfPathNotExists(system_test_path)\n\n    registry = dfwinreg_registry.WinRegistry()\n\n    with open(software_test_path, 'rb') as software_file_object:\n      with open(system_test_path, 'rb') as system_file_object:\n        registry_file = dfwinreg_regf.REGFWinRegistryFile(\n            ascii_codepage='cp1252')\n        registry_file.Open(software_file_object)\n\n        key_path_prefix = registry.GetRegistryFileMapping(registry_file)\n        registry_file.SetKeyPathPrefix(key_path_prefix)\n        registry.MapFile(key_path_prefix, registry_file)\n\n        registry_file = dfwinreg_regf.REGFWinRegistryFile(\n            ascii_codepage='cp1252')\n        registry_file.Open(system_file_object)\n\n        key_path_prefix = registry.GetRegistryFileMapping(registry_file)\n        registry_file.SetKeyPathPrefix(key_path_prefix)\n        registry.MapFile(key_path_prefix, registry_file)\n\n        collector_object = eventlog_providers.EventLogProvidersCollector()\n\n        test_results = list(collector_object.Collect(registry))\n\n    self.assertEqual(len(test_results), 974)\n\n    eventlog_provider = test_results[0]\n    self.assertIsNone(eventlog_provider.identifier)\n    self.assertIsNone(eventlog_provider.name)\n    self.assertEqual(eventlog_provider.log_sources, ['.NET Runtime'])\n    self.assertEqual(eventlog_provider.log_types, ['Application'])\n    self.assertEqual(eventlog_provider.category_message_files, set())\n    self.assertEqual(\n        eventlog_provider.event_message_files,\n        set(['C:\\\\Windows\\\\System32\\\\mscoree.dll']))\n    self.assertEqual(eventlog_provider.parameter_message_files, set())\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    collector_object = eventlog_providers.EventLogProvidersCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/filters.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Windows Registry key and value filters.\"\"\"\n\nimport unittest\n\nfrom winregrc import filters\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass WindowsRegistryKeyPathFilterTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows Registry key path filter.\"\"\"\n\n  def testInitialize(self):\n    \"\"\"Tests the initialize function.\"\"\"\n    test_filter = filters.WindowsRegistryKeyPathFilter('test')\n    self.assertIsNotNone(test_filter)\n\n  # TODO: add test for key_paths.\n  # TODO: add test for Match.\n\n\nclass WindowsRegistryKeyPathPrefixFilterTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows Registry key path prefix filter.\"\"\"\n\n  def testInitialize(self):\n    \"\"\"Tests the initialize function.\"\"\"\n    test_filter = filters.WindowsRegistryKeyPathPrefixFilter('test')\n    self.assertIsNotNone(test_filter)\n\n  # TODO: add test for Match.\n\n\nclass WindowsRegistryKeyPathSuffixFilterTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows Registry key path suffix filter.\"\"\"\n\n  def testInitialize(self):\n    \"\"\"Tests the initialize function.\"\"\"\n    test_filter = filters.WindowsRegistryKeyPathSuffixFilter('test')\n    self.assertIsNotNone(test_filter)\n\n  # TODO: add test for Match.\n\n\nclass WindowsRegistryKeyWithValuesFilterTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows Registry key with values filter.\"\"\"\n\n  def testInitialize(self):\n    \"\"\"Tests the initialize function.\"\"\"\n    test_filter = filters.WindowsRegistryKeyWithValuesFilter(['test'])\n    self.assertIsNotNone(test_filter)\n\n  # TODO: add test for Match.\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/hexdump.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the hexadecimal representation functions.\"\"\"\n\nimport unittest\n\nfrom winregrc import hexdump\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass HexdumpTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the hexadecimal representation functions.\"\"\"\n\n  def testHexdump(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    hexdump.Hexdump(b'')\n\n    hexdump.Hexdump(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06')\n\n    hexdump.Hexdump(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n\n    hexdump.Hexdump(\n        b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f')\n\n    hexdump.Hexdump(\n        b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f'\n        b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f'\n        b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f')\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/interface.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Windows Registry key and value collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\n\nfrom winregrc import interface\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass WindowsRegistryKeyCollectorTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows Registry key and value collector.\"\"\"\n\n  # pylint: disable=protected-access\n\n  def testGetStringValueFromKey(self):\n    \"\"\"Tests the _GetStringValueFromKey function.\"\"\"\n    collector = interface.WindowsRegistryKeyCollector()\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('TestKey')\n\n    value_data = 'ValueData'.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'TestValue', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    value = collector._GetStringValueFromKey(\n        registry_key, 'TestValue', default_value='DefaultValue')\n    self.assertEqual(value, 'ValueData')\n\n    value = collector._GetStringValueFromKey(\n        None, 'TestValue', default_value='DefaultValue')\n    self.assertEqual(value, 'DefaultValue')\n\n    value = collector._GetStringValueFromKey(\n        registry_key, 'Bogus', default_value='DefaultValue')\n    self.assertEqual(value, 'DefaultValue')\n\n    collector = interface.WindowsRegistryKeyCollector()\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('TestKey')\n\n    value_data = b'\\x03\\x00\\x00\\x00'\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'TestValue', data=value_data,\n        data_type=dfwinreg_definitions.REG_DWORD)\n    registry_key.AddValue(registry_value)\n\n    value = collector._GetStringValueFromKey(\n        registry_key, 'TestValue', default_value='DefaultValue')\n    self.assertEqual(value, 'DefaultValue')\n\n  def testGetValueDataFromKey(self):\n    \"\"\"Tests the _GetValueDataFromKey function.\"\"\"\n    collector = interface.WindowsRegistryKeyCollector()\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('TestKey')\n\n    value_data = 'ValueData'.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'TestValue', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    value = collector._GetValueDataFromKey(registry_key, 'TestValue')\n    self.assertEqual(value, value_data)\n\n  def testGetValueFromKey(self):\n    \"\"\"Tests the _GetValueFromKey function.\"\"\"\n    collector = interface.WindowsRegistryKeyCollector()\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('TestKey')\n\n    value_data = 'ValueData'.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'TestValue', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    value = collector._GetValueFromKey(\n        registry_key, 'TestValue', default_value='DefaultValue')\n    self.assertEqual(value, 'ValueData')\n\n    value = collector._GetValueFromKey(\n        None, 'TestValue', default_value='DefaultValue')\n    self.assertEqual(value, 'DefaultValue')\n\n    value = collector._GetValueFromKey(\n        registry_key, 'Bogus', default_value='DefaultValue')\n    self.assertEqual(value, 'DefaultValue')\n\n    collector = interface.WindowsRegistryKeyCollector()\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('TestKey')\n\n    value_data = b'\\x03\\x00\\x00\\x00'\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'TestValue', data=value_data,\n        data_type=dfwinreg_definitions.REG_DWORD)\n    registry_key.AddValue(registry_value)\n\n    value = collector._GetValueFromKey(\n        registry_key, 'TestValue', default_value='DefaultValue')\n    self.assertEqual(value, 3)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/knownfolders.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Windows known folders collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import knownfolders\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass KnownFoldersCollectorTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows known folders collector.\"\"\"\n\n  _DISPLAY_NAME = 'Downloads'\n  _IDENTIFIER = '374de290-123f-4565-9164-39c4925e467b'\n  _LOCALIZED_DISPLAY_NAME = '@%SystemRoot%\\\\system32\\\\shell32.dll,-21798'\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\Software'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('FolderDescriptions')\n    registry_file.AddKeyByPath(\n        '\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer', registry_key)\n\n    subkey = dfwinreg_fake.FakeWinRegistryKey(self._IDENTIFIER)\n    registry_key.AddSubkey(self._IDENTIFIER, subkey)\n\n    value_data = self._DISPLAY_NAME.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'Name', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    subkey.AddValue(registry_value)\n\n    value_data = self._LOCALIZED_DISPLAY_NAME.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'LocalizedName', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    subkey.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    collector_object = knownfolders.KnownFoldersCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 1)\n\n    known_folder = test_results[0]\n    self.assertIsNotNone(known_folder)\n    self.assertEqual(known_folder.display_name, self._DISPLAY_NAME)\n    self.assertEqual(known_folder.identifier, self._IDENTIFIER)\n    self.assertEqual(\n        known_folder.localized_display_name, self._LOCALIZED_DISPLAY_NAME)\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    collector_object = knownfolders.KnownFoldersCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/mounted_devices.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Windows mounted devices collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import mounted_devices\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass MountedDevicesCollectorTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows mounted devices collector.\"\"\"\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\System'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('MountedDevices')\n    registry_file.AddKeyByPath('\\\\', registry_key)\n\n    value_data = b'\\x78\\x56\\x34\\x12\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00'\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        '\\\\DosDevices\\\\C:', data=value_data,\n        data_type=dfwinreg_definitions.REG_BINARY)\n    registry_key.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    collector_object = mounted_devices.MountedDevicesCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 1)\n\n    mounted_device = test_results[0]\n    self.assertIsNotNone(mounted_device)\n    self.assertEqual(mounted_device.identifier, '\\\\DosDevices\\\\C:')\n    self.assertEqual(mounted_device.disk_identity, 0x12345678)\n    self.assertEqual(mounted_device.partition_offset, 0x1000)\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    collector_object = mounted_devices.MountedDevicesCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/mru.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Most Recently Used (MRU) collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import mru\n\nfrom tests import test_lib\n\n\nclass MostRecentlyUsedCollectorTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the Most Recently Used (MRU) collector.\"\"\"\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_CURRENT_USER'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('RecentDocs')\n    registry_file.AddKeyByPath(\n        '\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer',\n        registry_key)\n\n    value_data = b'a\\x00\\x00\\x00'\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'MRUList', data=value_data, data_type=dfwinreg_definitions.REG_BINARY)\n    registry_key.AddValue(registry_value)\n\n    value_data = 'MyFile.txt\\x00'.encode('utf_16_le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'a', data=value_data, data_type=dfwinreg_definitions.REG_BINARY)\n    registry_key.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = mru.MostRecentlyUsedCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertTrue(result)\n\n    test_output_writer.Close()\n\n    self.assertEqual(len(collector_object.mru_entries), 1)\n\n    mru_entry = collector_object.mru_entries[0]\n    self.assertIsNotNone(mru_entry)\n    self.assertEqual(mru_entry.string, 'MyFile.txt')\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = mru.MostRecentlyUsedCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertFalse(result)\n\n    test_output_writer.Close()\n\n    self.assertEqual(len(collector_object.mru_entries), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/msie_zone_info.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Microsoft Internet Explorer (MSIE) zone collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import regf as dfwinreg_regf\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import msie_zone_info\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass MSIEZoneInformationCollectorTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Microsoft Internet Explorer (MSIE) zone collector.\"\"\"\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    test_path = self._GetTestFilePath(['SOFTWARE'])\n    self._SkipIfPathNotExists(test_path)\n\n    registry = dfwinreg_registry.WinRegistry()\n\n    with open(test_path, 'rb') as file_object:\n      registry_file = dfwinreg_regf.REGFWinRegistryFile(ascii_codepage='cp1252')\n      registry_file.Open(file_object)\n\n      key_path_prefix = registry.GetRegistryFileMapping(registry_file)\n      registry_file.SetKeyPathPrefix(key_path_prefix)\n      registry.MapFile(key_path_prefix, registry_file)\n\n      collector_object = msie_zone_info.MSIEZoneInformationCollector()\n\n      test_results = list(collector_object.Collect(registry))\n\n    self.assertEqual(len(test_results), 1724)\n\n    zone_information = test_results[0]\n    self.assertEqual(zone_information.zone, '0')\n    self.assertEqual(zone_information.zone_name, 'Computer')\n    self.assertEqual(zone_information.control, '1809')\n    self.assertEqual(zone_information.control_value, 3)\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    collector_object = msie_zone_info.MSIEZoneInformationCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/output_writer.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the output writer.\"\"\"\n\nimport unittest\n\nfrom winregrc import output_writers\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass StdoutOutputWriterTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the stdout output writer.\"\"\"\n\n  # pylint: disable=protected-access\n\n  def testFormatDataInHexadecimal(self):\n    \"\"\"Tests the _FormatDataInHexadecimal function.\"\"\"\n    test_output_writer = output_writers.StdoutOutputWriter()\n\n    data = b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06'\n    expected_formatted_data = (\n        '0x00000000  00 01 02 03 04 05 06                              '\n        '.......\\n'\n        '\\n')\n    formatted_data = test_output_writer._FormatDataInHexadecimal(data)\n    self.assertEqual(formatted_data, expected_formatted_data)\n\n    data = b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09'\n    expected_formatted_data = (\n        '0x00000000  00 01 02 03 04 05 06 07  08 09                    '\n        '..........\\n'\n        '\\n')\n    formatted_data = test_output_writer._FormatDataInHexadecimal(data)\n    self.assertEqual(formatted_data, expected_formatted_data)\n\n    data = b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f'\n    expected_formatted_data = (\n        '0x00000000  00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  '\n        '................\\n'\n        '\\n')\n    formatted_data = test_output_writer._FormatDataInHexadecimal(data)\n    self.assertEqual(formatted_data, expected_formatted_data)\n\n    data = (\n        b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f'\n        b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f'\n        b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f')\n    expected_formatted_data = (\n        '0x00000000  00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  '\n        '................\\n'\n        '...\\n'\n        '0x00000020  00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  '\n        '................\\n'\n        '\\n')\n    formatted_data = test_output_writer._FormatDataInHexadecimal(data)\n    self.assertEqual(formatted_data, expected_formatted_data)\n\n  def testOpenClose(self):\n    \"\"\"Tests the Open and Close functions.\"\"\"\n    test_output_writer = output_writers.StdoutOutputWriter()\n\n    result = test_output_writer.Open()\n    self.assertTrue(result)\n\n    test_output_writer.Close()\n\n  def testWriteDebugData(self):\n    \"\"\"Tests the WriteDebugData function.\"\"\"\n    test_output_writer = output_writers.StdoutOutputWriter()\n\n    test_output_writer.WriteDebugData('Description', b'DATA')\n\n  def testWriteValue(self):\n    \"\"\"Tests the WriteValue function.\"\"\"\n    test_output_writer = output_writers.StdoutOutputWriter()\n\n    test_output_writer.WriteValue('Description', 'Value')\n\n  def testWriteText(self):\n    \"\"\"Tests the WriteText function.\"\"\"\n    test_output_writer = output_writers.StdoutOutputWriter()\n\n    test_output_writer.WriteText('Test')\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/profiles.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the user profiles collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import profiles\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass UserProfilesCollectorTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows user profiles collector.\"\"\"\n\n  _SID = 'S-1-5-18'\n  _PROFILE_PATH = '%systemroot%\\\\system32\\\\config\\\\systemprofile'\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\Software'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('ProfileList')\n    registry_file.AddKeyByPath(\n        '\\\\Microsoft\\\\Windows NT\\\\CurrentVersion', registry_key)\n\n    subkey = dfwinreg_fake.FakeWinRegistryKey(self._SID)\n    registry_key.AddSubkey(self._SID, subkey)\n\n    value_data = self._PROFILE_PATH.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'ProfileImagePath', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    subkey.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    collector_object = profiles.UserProfilesCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 1)\n\n    user_profile = test_results[0]\n    self.assertIsNotNone(user_profile)\n    self.assertEqual(user_profile.security_identifier, self._SID)\n    self.assertEqual(user_profile.profile_path, self._PROFILE_PATH)\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    collector_object = profiles.UserProfilesCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/programscache.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Programs Cache information collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import regf as dfwinreg_regf\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import errors\nfrom winregrc import output_writers\nfrom winregrc import programscache\n\nfrom tests import test_lib\n\n\nclass TestOutputWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Output writer for testing.\n\n  Attributes:\n    text (list[str]): text.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes an output writer object.\"\"\"\n    super().__init__()\n    self.text = []\n\n  def WriteText(self, text):\n    \"\"\"Writes text to stdout.\n\n    Args:\n      text (str): text to write.\n    \"\"\"\n    self.text.append(text)\n\n\nclass ProgramsCacheDataParserTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the Programs Cache data parser.\"\"\"\n\n  def testParse(self):\n    \"\"\"Tests the Parse function.\"\"\"\n    data_parser = programscache.ProgramsCacheDataParser()\n\n    with self.assertRaises(errors.ParseError):\n      data_parser.Parse(b'')\n\n\nclass ProgramsCacheCollectorTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the Programs Cache information collector.\"\"\"\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    test_path = self._GetTestFilePath(['NTUSER.DAT'])\n    self._SkipIfPathNotExists(test_path)\n\n    registry = dfwinreg_registry.WinRegistry()\n\n    with open(test_path, 'rb') as file_object:\n      registry_file = dfwinreg_regf.REGFWinRegistryFile(ascii_codepage='cp1252')\n      registry_file.Open(file_object)\n\n      key_path_prefix = registry.GetRegistryFileMapping(registry_file)\n      registry_file.SetKeyPathPrefix(key_path_prefix)\n      registry.MapFile(key_path_prefix, registry_file)\n\n      test_output_writer = test_lib.TestOutputWriter()\n      collector_object = programscache.ProgramsCacheCollector(\n          output_writer=test_output_writer)\n\n      result = collector_object.Collect(registry)\n\n    self.assertTrue(result)\n\n    test_output_writer.Close()\n\n    # TODO: test program cache values.\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = programscache.ProgramsCacheCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertFalse(result)\n\n    test_output_writer.Close()\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/sam.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Security Account Manager (SAM) collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import errors\nfrom winregrc import sam\n\nfrom tests import test_lib\n\n\n_F_VALUE_DATA = bytes(bytearray([\n    0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd2, 0x12, 0xa1,\n    0xfc, 0x88, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x46, 0x8f, 0x64, 0xcc, 0xfd, 0x88, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0xf4, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x88, 0x52, 0x35, 0x00]))\n\n_V_VALUE_DATA = bytes(bytearray([\n    0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,\n    0xbc, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0xd8, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x44, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,\n    0x5c, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,\n    0x64, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x68, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x7c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x80, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x01, 0x00, 0x14, 0x80, 0x9c, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00,\n    0x14, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0x00,\n    0x02, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x14, 0x00, 0x44, 0x00, 0x05, 0x01,\n    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,\n    0x02, 0xc0, 0x14, 0x00, 0xff, 0xff, 0x1f, 0x00, 0x01, 0x01, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x05, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x58, 0x00,\n    0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x5b, 0x03, 0x02, 0x00,\n    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x18, 0x00, 0xff, 0x07, 0x0f, 0x00, 0x01, 0x02, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00,\n    0x00, 0x00, 0x24, 0x00, 0x44, 0x00, 0x02, 0x00, 0x01, 0x05, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0x9b, 0x7d, 0xee, 0x68,\n    0xf4, 0xd1, 0xe6, 0x5e, 0xe5, 0xbd, 0xa3, 0x09, 0xf4, 0x01, 0x00, 0x00,\n    0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00,\n    0x20, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,\n    0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x41, 0x00, 0x64, 0x00,\n    0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00,\n    0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x18, 0x00,\n    0x42, 0x00, 0x75, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x74, 0x00, 0x2d, 0x00,\n    0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00,\n    0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x66, 0x00,\n    0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x61, 0x00, 0x64, 0x00, 0x6d, 0x00,\n    0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00,\n    0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x74, 0x00,\n    0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00,\n    0x70, 0x00, 0x75, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2f, 0x00,\n    0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00,\n    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x00,\n    0x01, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00,\n    0x03, 0x00, 0x01, 0x00, 0xd8, 0x31, 0x5b, 0x1f, 0x33, 0x69, 0x27, 0x07,\n    0x1f, 0xda, 0xf2, 0x03, 0xec, 0x2c, 0xf6, 0x84, 0x03, 0x00, 0x01, 0x00,\n    0x03, 0x00, 0x01, 0x00]))\n\n\nclass SecurityAccountManagerDataParserTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the Security Account Manager (SAM) data parser.\"\"\"\n\n  def testParseFValue(self):\n    \"\"\"Tests the ParseFValue function.\"\"\"\n    user_account = sam.UserAccount()\n\n    data_parser = sam.SecurityAccountManagerDataParser()\n\n    data_parser.ParseFValue(_F_VALUE_DATA, user_account)\n\n    self.assertEqual(user_account.last_login_time, 129347632925692440)\n    self.assertEqual(user_account.last_password_set_time, 129347637947436870)\n    self.assertEqual(user_account.account_expiration_time, 0)\n    self.assertEqual(user_account.last_password_failure_time, 0)\n    self.assertEqual(user_account.rid, 500)\n    self.assertEqual(user_account.primary_gid, 513)\n    self.assertEqual(user_account.user_account_control_flags, 0x211)\n    self.assertEqual(user_account.codepage, 0)\n    self.assertEqual(user_account.number_of_password_failures, 0)\n    self.assertEqual(user_account.number_of_logons, 6)\n\n    with self.assertRaises(errors.ParseError):\n      data_parser.ParseFValue(b'', user_account)\n\n    # TODO: add bogus data tests.\n\n  def testParseVValue(self):\n    \"\"\"Tests the ParseVValue function.\"\"\"\n    user_account = sam.UserAccount()\n\n    data_parser = sam.SecurityAccountManagerDataParser()\n\n    data_parser.ParseVValue(_V_VALUE_DATA, user_account)\n\n    self.assertEqual(user_account.username, 'Administrator')\n\n    # TODO: tests other values set by ParseVValue.\n\n    with self.assertRaises(errors.ParseError):\n      data_parser.ParseVValue(b'', user_account)\n\n    # TODO: add bogus data tests.\n\n  # TODO: add more tests.\n\n\nclass SecurityAccountManagerCollectorTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the Security Account Manager (SAM) collector.\"\"\"\n\n  _RID = '000001F4'\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\SAM'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('Users')\n    registry_file.AddKeyByPath('\\\\SAM\\\\Domains\\\\Account', registry_key)\n\n    subkey = dfwinreg_fake.FakeWinRegistryKey(self._RID)\n    registry_key.AddSubkey(self._RID, subkey)\n\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'F', data=_F_VALUE_DATA, data_type=dfwinreg_definitions.REG_BINARY)\n    subkey.AddValue(registry_value)\n\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'V', data=_V_VALUE_DATA, data_type=dfwinreg_definitions.REG_BINARY)\n    subkey.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = sam.SecurityAccountManagerCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertTrue(result)\n\n    test_output_writer.Close()\n\n    self.assertEqual(len(collector_object.user_accounts), 1)\n\n    user_account = collector_object.user_accounts[0]\n    self.assertIsNotNone(user_account)\n    self.assertEqual(user_account.username, 'Administrator')\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = sam.SecurityAccountManagerCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertFalse(result)\n\n    test_output_writer.Close()\n\n    self.assertEqual(len(collector_object.user_accounts), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/services.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the services collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import services\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass WindowsServicesCollectorTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the services collector.\"\"\"\n\n  _DESCRIPTION = '@%SystemRoot%\\\\System32\\\\wwansvc.dll,-258'\n  _DISPLAY_NAME = '@%SystemRoot%\\\\System32\\\\wwansvc.dll,-257'\n  _IMAGE_PATH = '%SystemRoot%\\\\system32\\\\svchost.exe -k LocalServiceNoNetwork'\n  _OBJECT_NAME = 'NT Authority\\\\LocalService'\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\System'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('Services')\n    registry_file.AddKeyByPath('\\\\CurrentControlSet', registry_key)\n\n    subkey = dfwinreg_fake.FakeWinRegistryKey('WwanSvc')\n    registry_key.AddSubkey('WwanSvc', subkey)\n\n    value_data = self._DESCRIPTION.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'Description', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    subkey.AddValue(registry_value)\n\n    value_data = self._DISPLAY_NAME.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'DisplayName', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    subkey.AddValue(registry_value)\n\n    value_data = self._IMAGE_PATH.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'ImagePath', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    subkey.AddValue(registry_value)\n\n    value_data = self._OBJECT_NAME.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'ObjectName', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    subkey.AddValue(registry_value)\n\n    value_data = b'\\x03\\x00\\x00\\x00'\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'Start', data=value_data, data_type=dfwinreg_definitions.REG_DWORD)\n    subkey.AddValue(registry_value)\n\n    value_data = b'\\x20\\x00\\x00\\x00'\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'Type', data=value_data, data_type=dfwinreg_definitions.REG_DWORD)\n    subkey.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    collector_object = services.WindowsServicesCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 1)\n\n    windows_service = test_results[0]\n    self.assertIsNotNone(windows_service)\n    self.assertEqual(windows_service.description, self._DESCRIPTION)\n    self.assertEqual(windows_service.display_name, self._DISPLAY_NAME)\n    self.assertEqual(windows_service.image_path, self._IMAGE_PATH)\n    self.assertEqual(windows_service.name, 'WwanSvc')\n    self.assertEqual(windows_service.object_name, self._OBJECT_NAME)\n    self.assertEqual(windows_service.service_type, 32)\n    self.assertEqual(windows_service.start_value, 3)\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    collector_object = services.WindowsServicesCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 0)\n\n  # TODO: add tests for Compare method\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/shellfolders.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Windows shell folders collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import shellfolders\n\nfrom tests import test_lib as shared_test_lib\n\n\nclass ShellFoldersCollectorTest(shared_test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows shell folders collector.\"\"\"\n\n  _GUID1 = '{2227a280-3aea-1069-a2de-08002b30309d}'\n  _GUID2 = '{e7de9b1a-7533-4556-9484-b26fb486475e}'\n  _LOCALIZED_STRING1 = '@%SystemRoot%\\\\system32\\\\prnfldr.dll,-8036'\n  _NAME1 = 'Printers'\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\Software'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('CLSID')\n    registry_file.AddKeyByPath('\\\\Classes', registry_key)\n\n    subkey = dfwinreg_fake.FakeWinRegistryKey(self._GUID1)\n    registry_key.AddSubkey(self._GUID1, subkey)\n\n    shell_folder_key = dfwinreg_fake.FakeWinRegistryKey('ShellFolder')\n    subkey.AddSubkey('ShellFolder', shell_folder_key)\n\n    value_data = self._NAME1.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        '', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    subkey.AddValue(registry_value)\n\n    value_data = self._LOCALIZED_STRING1.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'LocalizedString', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    subkey.AddValue(registry_value)\n\n    subkey = dfwinreg_fake.FakeWinRegistryKey(self._GUID2)\n    registry_key.AddSubkey(self._GUID2, subkey)\n\n    shell_folder_key = dfwinreg_fake.FakeWinRegistryKey('ShellFolder')\n    subkey.AddSubkey('ShellFolder', shell_folder_key)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    collector_object = shellfolders.ShellFoldersCollector()\n\n    test_results = sorted(\n        collector_object.Collect(registry),\n        key=lambda folder: folder.identifier)\n    self.assertEqual(len(test_results), 2)\n\n    shell_folder = test_results[0]\n    self.assertIsNotNone(shell_folder)\n    self.assertEqual(shell_folder.identifier, self._GUID1)\n    self.assertEqual(shell_folder.name, self._NAME1)\n    self.assertEqual(shell_folder.localized_string, self._LOCALIZED_STRING1)\n\n    shell_folder = test_results[1]\n    self.assertIsNotNone(shell_folder)\n    self.assertEqual(shell_folder.identifier, self._GUID2)\n    self.assertIsNone(shell_folder.name)\n    self.assertIsNone(shell_folder.localized_string)\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    collector_object = shellfolders.ShellFoldersCollector()\n\n    test_results = list(collector_object.Collect(registry))\n    self.assertEqual(len(test_results), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/sysinfo.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the system information collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import sysinfo\n\nfrom tests import test_lib\n\n\nclass SystemInfoCollectorTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the system information collector.\"\"\"\n\n  # pylint: disable=protected-access\n\n  _CSD_VERSION = 'Service Pack 1'\n  _CURRENT_BUILD_NUMBER = '7601'\n  _CURRENT_TYPE = 'Multiprocessor Free'\n  _CURRENT_VERSION = '6.1'\n  _INSTALLATION_DATE = 1289406535\n  _PATH_NAME = 'C:\\\\Windows'\n  _PRODUCT_IDENTIFIER = '00426-067-1817155-86250'\n  _PRODUCT_NAME = 'Windows 7 Ultimate'\n  _REGISTERED_ORGANIZATION = ''\n  _REGISTERED_OWNER = 'Windows User'\n  _SYSTEM_ROOT = 'C:\\\\Windows'\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\Software'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('CurrentVersion')\n    registry_file.AddKeyByPath('\\\\Microsoft\\\\Windows NT', registry_key)\n\n    value_data = self._CSD_VERSION.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'CSDVersion', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    value_data = self._CURRENT_BUILD_NUMBER.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'CurrentBuildNumber', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    value_data = self._CURRENT_TYPE.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'CurrentType', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    value_data = self._CURRENT_VERSION.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'CurrentVersion', data=value_data,\n        data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    value_data = b'\\x47\\xc8\\xda\\x4c'\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'InstallDate', data=value_data,\n        data_type=dfwinreg_definitions.REG_DWORD)\n    registry_key.AddValue(registry_value)\n\n    value_data = self._PRODUCT_IDENTIFIER.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'ProductId', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    value_data = self._PRODUCT_NAME.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'ProductName', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    # TODO: add more values.\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testParseInstallDate(self):\n    \"\"\"Tests the _ParseInstallDate function.\"\"\"\n    collector_object = sysinfo.SystemInfoCollector()\n\n    date_time = collector_object._ParseInstallDate(None)\n    self.assertIsNone(date_time)\n\n    value_data = b'\\x47\\xc8\\xda\\x4c'\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'InstallDate', data=value_data,\n        data_type=dfwinreg_definitions.REG_DWORD)\n\n    date_time = collector_object._ParseInstallDate(registry_value)\n    self.assertIsNotNone(date_time)\n\n    value_data = b'\\x00\\x00\\x00\\x00'\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'InstallDate', data=value_data,\n        data_type=dfwinreg_definitions.REG_DWORD)\n\n    date_time = collector_object._ParseInstallDate(registry_value)\n    self.assertIsNotNone(date_time)\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = sysinfo.SystemInfoCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertTrue(result)\n\n    test_output_writer.Close()\n\n    self.assertIsNotNone(collector_object.system_information)\n\n    self.assertEqual(\n        collector_object.system_information.csd_version, self._CSD_VERSION)\n    self.assertEqual(\n        collector_object.system_information.current_build_number,\n        self._CURRENT_BUILD_NUMBER)\n    self.assertEqual(\n        collector_object.system_information.current_type, self._CURRENT_TYPE)\n    self.assertEqual(\n        collector_object.system_information.current_version,\n        self._CURRENT_VERSION)\n    self.assertIsNotNone(collector_object.system_information.installation_date)\n    self.assertEqual(\n        collector_object.system_information.product_identifier,\n        self._PRODUCT_IDENTIFIER)\n    self.assertEqual(\n        collector_object.system_information.product_name, self._PRODUCT_NAME)\n\n    # TODO: add more values.\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = sysinfo.SystemInfoCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertFalse(result)\n\n    test_output_writer.Close()\n\n    self.assertIsNone(collector_object.system_information)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/task_cache.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Task Cache information collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import task_cache\n\nfrom tests import test_lib\n\n\n_DYNAMIC_INFO_DATA = bytes(bytearray([\n    0x03, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x7d, 0x12, 0x3f, 0x04, 0xca, 0x01,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00]))\n\n_DYNAMIC_INFO2_DATA = bytes(bytearray([\n    0x03, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x7d, 0x12, 0x3f, 0x04, 0xca, 0x01,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x7d, 0x12, 0x3f, 0x04, 0xca, 0x01]))\n\n\nclass TaskCacheDataParserTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the Task Cache data parser.\"\"\"\n\n  def testParseDynamicInfo(self):\n    \"\"\"Tests the ParseDynamicInfo function.\"\"\"\n    data_parser = task_cache.TaskCacheDataParser()\n\n    cached_task = task_cache.CachedTask()\n    data_parser.ParseDynamicInfo(_DYNAMIC_INFO_DATA, cached_task)\n\n    # TODO: compare date time value.\n    self.assertIsNotNone(cached_task.last_registered_time)\n    # TODO: compare date time value.\n    self.assertIsNotNone(cached_task.launch_time)\n\n    cached_task = task_cache.CachedTask()\n    data_parser.ParseDynamicInfo(_DYNAMIC_INFO2_DATA, cached_task)\n\n    # TODO: compare date time value.\n    self.assertIsNotNone(cached_task.last_registered_time)\n    # TODO: compare date time value.\n    self.assertIsNotNone(cached_task.launch_time)\n\n\nclass TaskCacheCollectorTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the Task Cache information collector.\"\"\"\n\n  _GUID1 = '{8905ECD8-016F-4DC2-90E6-A5F1FA6A841A}'\n  _GUID2 = '{F93C7104-998A-4A38-B935-775A3138B3C3}'\n  _GUID3 = '{FE7B674F-2430-40A1-9162-AFC3727E3DC3}'\n\n  _NAME1 = 'AD RMS Rights Policy Template Management (Automated)'\n  _NAME2 = 'Notifications'\n  _NAME3 = 'AutoWake'\n\n  _PATH = (\n      '\\\\Microsoft\\\\Windows\\\\Active Directory Rights Management Services '\n      'Client\\\\AD RMS Rights Policy Template Management (Automated)')\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\Software'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(self._GUID1)\n    registry_file.AddKeyByPath(\n        '\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\TaskCache\\\\Tasks',\n        registry_key)\n\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'DynamicInfo', data=_DYNAMIC_INFO_DATA,\n        data_type=dfwinreg_definitions.REG_BINARY)\n    registry_key.AddValue(registry_value)\n\n    value_data = self._PATH.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'Path', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(self._NAME1)\n    registry_file.AddKeyByPath((\n        '\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\TaskCache\\\\Tree\\\\'\n        'Microsoft\\\\Windows\\\\Active Directory Rights Management Services '\n        'Client'), registry_key)\n\n    value_data = '{8905ECD8-016F-4DC2-90E6-A5F1FA6A841A}\\x00'.encode(\n        'utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'Id', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(self._GUID2)\n    registry_file.AddKeyByPath(\n        '\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\TaskCache\\\\Tasks',\n        registry_key)\n\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'DynamicInfo', data=_DYNAMIC_INFO2_DATA,\n        data_type=dfwinreg_definitions.REG_BINARY)\n    registry_key.AddValue(registry_value)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(self._NAME2)\n    registry_file.AddKeyByPath((\n        '\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\TaskCache\\\\Tree\\\\'\n        'Microsoft\\\\Windows\\\\Location'), registry_key)\n\n    value_data = '{F93C7104-998A-4A38-B935-775A3138B3C3}\\x00'.encode(\n        'utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'Id', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(self._GUID3)\n    registry_file.AddKeyByPath(\n        '\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\TaskCache\\\\Tasks',\n        registry_key)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(self._NAME3)\n    registry_file.AddKeyByPath((\n        '\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\TaskCache\\\\Tree\\\\'\n        'Microsoft\\\\Windows\\\\SideShow'), registry_key)\n\n    value_data = '{FE7B674F-2430-40A1-9162-AFC3727E3DC3}\\x00'.encode(\n        'utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'Id', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    registry_key.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def _CreateTestRegistryEmpty(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\Software'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey('Tasks')\n    registry_file.AddKeyByPath(\n        '\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\TaskCache',\n        registry_key)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = task_cache.TaskCacheCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertTrue(result)\n\n    test_output_writer.Close()\n\n    self.assertEqual(len(collector_object.cached_tasks), 2)\n\n    cached_tasks = sorted(\n        collector_object.cached_tasks, key=lambda task: task.identifier)\n\n    cached_task = cached_tasks[0]\n\n    self.assertIsNotNone(cached_task)\n    self.assertEqual(cached_task.identifier, self._GUID1)\n    # TODO: fix test\n    # self.assertEqual(cached_task.name, self._NAME1)\n\n    cached_task = cached_tasks[1]\n\n    self.assertIsNotNone(cached_task)\n    self.assertEqual(cached_task.identifier, self._GUID2)\n    # TODO: fix test\n    # self.assertEqual(cached_task.name, self._NAME2)\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = task_cache.TaskCacheCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertFalse(result)\n\n    test_output_writer.Close()\n\n    self.assertEqual(len(collector_object.cached_tasks), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/test_lib.py",
    "content": "\"\"\"Shared test case.\"\"\"\n\nimport os\nimport unittest\n\nfrom winregrc import output_writers\n\n\nclass BaseTestCase(unittest.TestCase):\n  \"\"\"The base test case.\"\"\"\n\n  _TEST_DATA_PATH = os.path.join(os.getcwd(), 'test_data')\n\n  # Show full diff results, part of TestCase so does not follow our naming\n  # conventions.\n  maxDiff = None\n\n  def _GetTestFilePath(self, path_segments):\n    \"\"\"Retrieves the path of a test file in the test data directory.\n\n    Args:\n      path_segments (list[str]): path segments inside the test data directory.\n\n    Returns:\n      str: path of the test file.\n    \"\"\"\n    # Note that we need to pass the individual path segments to os.path.join\n    # and not a list.\n    return os.path.join(self._TEST_DATA_PATH, *path_segments)\n\n  def _SkipIfPathNotExists(self, path):\n    \"\"\"Skips the test if the path does not exist.\n\n    Args:\n      path (str): path of a test file.\n\n    Raises:\n      SkipTest: if the path does not exist and the test should be skipped.\n    \"\"\"\n    if not os.path.exists(path):\n      filename = os.path.basename(path)\n      raise unittest.SkipTest(f'missing test file: {filename:s}')\n\n\nclass TestOutputWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Test output writer.\n\n  Attributes:\n    output (list[str]): output written.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes a test output writer.\"\"\"\"\"\n    super().__init__()\n    self.output = []\n\n  def Close(self):\n    \"\"\"Closes the output writer object.\"\"\"\n    return\n\n  def Open(self):\n    \"\"\"Opens the output writer object.\"\"\"\n    return\n\n  def WriteText(self, text):\n    \"\"\"Writes text to the output.\n\n    Args:\n      text (str): text to write.\n    \"\"\"\n    self.output.append(text)\n"
  },
  {
    "path": "tests/type_libraries.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the type libraries collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import type_libraries\n\nfrom tests import test_lib\n\n\nclass TypeLibraryTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the type library.\"\"\"\n\n  _DESCRIPTION = 'Microsoft Office List 14.0'\n  _FILENAME = 'C:\\\\PROGRA~1\\\\MICROS~2\\\\Office14\\\\STSLIST.DLL'\n  _IDENTIFIER = '{edcd5812-6a06-43c3-afac-46ef5d14e22c}'\n  _VERSION = '3.0'\n\n  def testInitialize(self):\n    \"\"\"Tests the initialize function.\"\"\"\n    type_library = type_libraries.TypeLibrary(\n        self._IDENTIFIER, self._VERSION, self._DESCRIPTION, self._FILENAME)\n    self.assertIsNotNone(type_library)\n\n\nclass TypeLibraryCollectorTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the type libraries collector.\"\"\"\n\n  _DESCRIPTION1 = 'Microsoft Office List 14.0'\n  _FILENAME1 = 'C:\\\\PROGRA~1\\\\MICROS~2\\\\Office14\\\\STSLIST.DLL'\n  _IDENTIFIER1 = '{edcd5812-6a06-43c3-afac-46ef5d14e22c}'\n  _VERSION1 = '3.0'\n\n  _DESCRIPTION2 = 'IAS SDO Helper 1.0 Type Library'\n  _FILENAME2 = '%SystemRoot%\\\\system32\\\\sdohlp.dll\\\\1'\n  _IDENTIFIER2 = '{e9970f91-b6aa-11d9-b032-000d56c25c27}'\n  _VERSION2 = '1.0'\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_LOCAL_MACHINE\\\\Software'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(self._IDENTIFIER1)\n    registry_file.AddKeyByPath('\\\\Classes\\\\TypeLib', registry_key)\n\n    subkey = dfwinreg_fake.FakeWinRegistryKey(self._VERSION1)\n    registry_key.AddSubkey(self._VERSION1, subkey)\n\n    value_data = self._DESCRIPTION1.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        '', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    subkey.AddValue(registry_value)\n\n    language_key = dfwinreg_fake.FakeWinRegistryKey('409')\n    subkey.AddSubkey('409', language_key)\n\n    platform_key = dfwinreg_fake.FakeWinRegistryKey('Win32')\n    language_key.AddSubkey('Win32', platform_key)\n\n    value_data = self._FILENAME1.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        '', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    platform_key.AddValue(registry_value)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(self._IDENTIFIER2)\n    registry_file.AddKeyByPath('\\\\Classes\\\\TypeLib', registry_key)\n\n    subkey = dfwinreg_fake.FakeWinRegistryKey(self._VERSION2)\n    registry_key.AddSubkey(self._VERSION2, subkey)\n\n    value_data = self._DESCRIPTION1.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        '', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    subkey.AddValue(registry_value)\n\n    language_key = dfwinreg_fake.FakeWinRegistryKey('0')\n    subkey.AddSubkey('0', language_key)\n\n    platform_key = dfwinreg_fake.FakeWinRegistryKey('x64')\n    language_key.AddSubkey('x64', platform_key)\n\n    value_data = self._FILENAME1.encode('utf-16-le')\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        '', data=value_data, data_type=dfwinreg_definitions.REG_SZ)\n    platform_key.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = type_libraries.TypeLibrariesCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertTrue(result)\n\n    self.assertEqual(len(collector_object.type_libraries), 2)\n\n    type_library = collector_object.type_libraries[0]\n\n    self.assertIsNotNone(type_library)\n    self.assertEqual(type_library.description, self._DESCRIPTION1)\n    self.assertEqual(type_library.identifier, self._IDENTIFIER1)\n    self.assertEqual(type_library.typelib_filename, self._FILENAME1)\n    self.assertEqual(type_library.version, self._VERSION1)\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = type_libraries.TypeLibrariesCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertFalse(result)\n\n    self.assertEqual(len(collector_object.type_libraries), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tests/userassist.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Tests for the Windows User Assist collector.\"\"\"\n\nimport unittest\n\nfrom dfwinreg import definitions as dfwinreg_definitions\nfrom dfwinreg import fake as dfwinreg_fake\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import userassist\n\nfrom tests import test_lib\n\n\n_ENTRY_DATA_V3 = bytes(bytearray([\n    0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0xe3, 0x6e, 0x4b,\n    0x17, 0x15, 0xca, 0x01]))\n\n_ENTRY_DATA_V5 = bytes(bytearray([\n    0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,\n    0x20, 0x30, 0x05, 0x00, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf,\n    0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf,\n    0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf,\n    0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0xff, 0xff, 0xff, 0xff,\n    0x04, 0xa8, 0x92, 0xd2, 0xab, 0x80, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00]))\n\n\nclass UserAssistDataParserTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the User Assist data parser.\"\"\"\n\n  def testParseEntry(self):\n    \"\"\"Tests the ParseEntry function.\"\"\"\n    data_parser = userassist.UserAssistDataParser()\n\n    data_parser.ParseEntry(3, _ENTRY_DATA_V3)\n\n    data_parser.ParseEntry(5, _ENTRY_DATA_V5)\n\n\nclass UserAssistCollectorTest(test_lib.BaseTestCase):\n  \"\"\"Tests for the Windows User Assist collector.\"\"\"\n\n  _GUID = '{5E6AB780-7743-11CF-A12B-00AA004AE837}'\n\n  _UEME_CTLSESSION_VALUE_DATA = bytes(bytearray([\n      0xb0, 0xa8, 0x50, 0x0e, 0x01, 0x00, 0x00, 0x00]))\n\n  _ENTRY_VALUE_DATA = bytes(bytearray([\n      0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x54, 0x4b, 0xf6, 0xd3,\n      0x15, 0x15, 0xca, 0x01]))\n\n  def _CreateTestRegistry(self):\n    \"\"\"Creates Registry keys and values for testing.\n\n    Returns:\n      dfwinreg.WinRegistry: Windows Registry for testing.\n    \"\"\"\n    key_path_prefix = 'HKEY_CURRENT_USER'\n\n    registry_file = dfwinreg_fake.FakeWinRegistryFile(\n        key_path_prefix=key_path_prefix)\n\n    registry_key = dfwinreg_fake.FakeWinRegistryKey(self._GUID)\n    registry_file.AddKeyByPath(\n        '\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\UserAssist',\n        registry_key)\n\n    value_data = b'\\x03\\x00\\x00\\x00'\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'Version', data=value_data, data_type=dfwinreg_definitions.REG_DWORD)\n    registry_key.AddValue(registry_value)\n\n    subkey = dfwinreg_fake.FakeWinRegistryKey('Count')\n    registry_key.AddSubkey('Count', subkey)\n\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'HRZR_PGYFRFFVBA', data=self._UEME_CTLSESSION_VALUE_DATA,\n        data_type=dfwinreg_definitions.REG_BINARY)\n    subkey.AddValue(registry_value)\n\n    registry_value = dfwinreg_fake.FakeWinRegistryValue(\n        'HRZR_EHACVQY:%pfvqy2%\\\\Jvaqbjf Zrffratre.yax',\n        data=self._ENTRY_VALUE_DATA, data_type=dfwinreg_definitions.REG_BINARY)\n    subkey.AddValue(registry_value)\n\n    registry_file.Open(None)\n\n    registry = dfwinreg_registry.WinRegistry()\n    registry.MapFile(key_path_prefix, registry_file)\n    return registry\n\n  def testCollect(self):\n    \"\"\"Tests the Collect function.\"\"\"\n    registry = self._CreateTestRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = userassist.UserAssistCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertTrue(result)\n\n    test_output_writer.Close()\n\n    self.assertEqual(len(collector_object.user_assist_entries), 1)\n\n    # TODO: test user assist entry values.\n\n  def testCollectEmpty(self):\n    \"\"\"Tests the Collect function on an empty Registry.\"\"\"\n    registry = dfwinreg_registry.WinRegistry()\n\n    test_output_writer = test_lib.TestOutputWriter()\n    collector_object = userassist.UserAssistCollector(\n        output_writer=test_output_writer)\n\n    result = collector_object.Collect(registry)\n    self.assertFalse(result)\n\n    test_output_writer.Close()\n\n    self.assertEqual(len(collector_object.user_assist_entries), 0)\n\n\nif __name__ == '__main__':\n  unittest.main()\n"
  },
  {
    "path": "tox.ini",
    "content": "[tox]\nenvlist = py3{10,11,12,13,14},coverage,docs,lint,wheel\n\n[testenv]\nallowlist_externals = ./run_tests.py\npip_pre = True\npassenv =\n  CFLAGS\n  CPPFLAGS\n  LDFLAGS\nsetenv =\n  PYTHONPATH = {toxinidir}\ndeps =\n  coverage: coverage\n  wheel:\n    build\n    setuptools >= 65\n    wheel\ncommands =\n  py3{10,11,12,13,14}: ./run_tests.py\n  coverage: coverage erase\n  coverage: coverage run --source=winregrc --omit=\"*_test*,*__init__*,*test_lib*\" run_tests.py\n  coverage: coverage xml\n  wheel: python -m build --no-isolation --wheel\n\n[testenv:docs]\nusedevelop = True\ndeps =\n  -rdocs/requirements.txt\ncommands =\n  sphinx-build -b html -d build/doctrees docs dist/docs\n  sphinx-build -b linkcheck docs dist/docs\n\n[testenv:lint]\nskipsdist = True\npip_pre = True\npassenv =\n  CFLAGS\n  CPPFLAGS\n  LDFLAGS\nsetenv =\n  PYTHONPATH = {toxinidir}\ndeps =\n  pylint >= 3.3.0, < 3.4.0\n  setuptools >= 65\n  yamllint >= 1.26.0\ncommands =\n  pylint --version\n  yamllint -v\n  pylint --rcfile=.pylintrc tests winregrc\n  yamllint -c .yamllint.yaml winregrc\n"
  },
  {
    "path": "utils/__init__.py",
    "content": "\"\"\"Data formats.\"\"\"\n\n__version__ = '20170423'\n"
  },
  {
    "path": "utils/check_dependencies.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to check for the availability and version of dependencies.\"\"\"\n\nimport sys\n\n# Change PYTHONPATH to include dependencies.\nsys.path.insert(0, '.')\n\nimport utils.dependencies  # pylint: disable=wrong-import-position\n\n\nif __name__ == '__main__':\n  dependency_helper = utils.dependencies.DependencyHelper()\n\n  if not dependency_helper.CheckDependencies():\n    sys.exit(1)\n"
  },
  {
    "path": "utils/dependencies.py",
    "content": "\"\"\"Helper to check for availability and version of dependencies.\"\"\"\n\nimport configparser\nimport os\nimport re\n\n\nclass DependencyDefinition:\n  \"\"\"Dependency definition.\n\n  Attributes:\n    dpkg_name (str): name of the dpkg package that provides the dependency.\n    is_optional (bool): True if the dependency is optional.\n    l2tbinaries_name (str): name of the l2tbinaries package that provides\n        the dependency.\n    maximum_version (str): maximum supported version, a greater or equal\n        version is not supported.\n    minimum_version (str): minimum supported version, a lesser version is\n        not supported.\n    name (str): name of (the Python module that provides) the dependency.\n    pypi_name (str): name of the PyPI package that provides the dependency.\n    python2_only (bool): True if the dependency is only supported by Python 2.\n    python3_only (bool): True if the dependency is only supported by Python 3.\n    rpm_name (str): name of the rpm package that provides the dependency.\n    skip_check (bool): True if the dependency should be skipped by the\n        CheckDependencies or CheckTestDependencies methods of DependencyHelper.\n    skip_requires (bool): True if the dependency should be excluded from\n        pyproject.toml dependencies.\n    version_property (str): name of the version attribute or function.\n  \"\"\"\n\n  def __init__(self, name):\n    \"\"\"Initializes a dependency configuration.\n\n    Args:\n      name (str): name of the dependency.\n    \"\"\"\n    super().__init__()\n    self.dpkg_name = None\n    self.is_optional = False\n    self.l2tbinaries_name = None\n    self.maximum_version = None\n    self.minimum_version = None\n    self.name = name\n    self.pypi_name = None\n    self.python2_only = False\n    self.python3_only = False\n    self.rpm_name = None\n    self.skip_check = None\n    self.skip_requires = None\n    self.version_property = None\n\n\nclass DependencyDefinitionReader:\n  \"\"\"Dependency definition reader.\"\"\"\n\n  _VALUE_NAMES = frozenset([\n      'dpkg_name',\n      'is_optional',\n      'l2tbinaries_name',\n      'maximum_version',\n      'minimum_version',\n      'pypi_name',\n      'python2_only',\n      'python3_only',\n      'rpm_name',\n      'skip_check',\n      'skip_requires',\n      'version_property'])\n\n  def _GetConfigValue(self, config_parser, section_name, value_name):\n    \"\"\"Retrieves a value from the config parser.\n\n    Args:\n      config_parser (ConfigParser): configuration parser.\n      section_name (str): name of the section that contains the value.\n      value_name (str): name of the value.\n\n    Returns:\n      object: configuration value or None if the value does not exists.\n    \"\"\"\n    try:\n      return config_parser.get(section_name, value_name)\n    except configparser.NoOptionError:\n      return None\n\n  def Read(self, file_object):\n    \"\"\"Reads dependency definitions.\n\n    Args:\n      file_object (file): file-like object to read from.\n\n    Yields:\n      DependencyDefinition: dependency definition.\n    \"\"\"\n    config_parser = configparser.ConfigParser(interpolation=None)\n    config_parser.read_file(file_object)\n\n    for section_name in config_parser.sections():\n      dependency_definition = DependencyDefinition(section_name)\n      for value_name in self._VALUE_NAMES:\n        value = self._GetConfigValue(config_parser, section_name, value_name)\n        setattr(dependency_definition, value_name, value)\n\n      yield dependency_definition\n\n\nclass DependencyHelper:\n  \"\"\"Dependency helper.\n\n  Attributes:\n    dependencies (dict[str, DependencyDefinition]): dependencies.\n  \"\"\"\n\n  _VERSION_NUMBERS_REGEX = re.compile(r'[0-9.]+')\n  _VERSION_SPLIT_REGEX = re.compile(r'\\.|\\-')\n\n  def __init__(\n      self, dependencies_file='dependencies.ini',\n      test_dependencies_file='test_dependencies.ini'):\n    \"\"\"Initializes a dependency helper.\n\n    Args:\n      dependencies_file (Optional[str]): path to the dependencies configuration\n          file.\n      test_dependencies_file (Optional[str]): path to the test dependencies\n          configuration file.\n    \"\"\"\n    super().__init__()\n    self._test_dependencies = {}\n    self.dependencies = {}\n\n    dependency_reader = DependencyDefinitionReader()\n\n    with open(dependencies_file, 'r', encoding='utf-8') as file_object:\n      for dependency in dependency_reader.Read(file_object):\n        self.dependencies[dependency.name] = dependency\n\n    if os.path.exists(test_dependencies_file):\n      with open(test_dependencies_file, 'r', encoding='utf-8') as file_object:\n        for dependency in dependency_reader.Read(file_object):\n          self._test_dependencies[dependency.name] = dependency\n\n  def _CheckPythonModule(self, dependency):\n    \"\"\"Checks the availability of a Python module.\n\n    Args:\n      dependency (DependencyDefinition): dependency definition.\n\n    Returns:\n      tuple: containing:\n\n        bool: True if the Python module is available and conforms to\n            the minimum required version, False otherwise.\n        str: status message.\n    \"\"\"\n    module_object = self._ImportPythonModule(dependency.name)\n    if not module_object:\n      return False, f'missing: {dependency.name:s}'\n\n    if not dependency.version_property:\n      return True, dependency.name\n\n    return self._CheckPythonModuleVersion(\n        dependency.name, module_object, dependency.version_property,\n        dependency.minimum_version, dependency.maximum_version)\n\n  def _CheckPythonModuleVersion(\n      self, module_name, module_object, version_property, minimum_version,\n      maximum_version):\n    \"\"\"Checks the version of a Python module.\n\n    Args:\n      module_object (module): Python module.\n      module_name (str): name of the Python module.\n      version_property (str): version attribute or function.\n      minimum_version (str): minimum version.\n      maximum_version (str): maximum version.\n\n    Returns:\n      tuple: containing:\n\n        bool: True if the Python module is available and conforms to\n            the minimum required version, False otherwise.\n        str: status message.\n    \"\"\"\n    module_version = None\n    if not version_property.endswith('()'):\n      module_version = getattr(module_object, version_property, None)\n    else:\n      version_method = getattr(\n          module_object, version_property[:-2], None)\n      if version_method:\n        module_version = version_method()\n\n    if not module_version:\n      return False, (\n          f'unable to determine version information for: {module_name:s}')\n\n    # Make sure the module version is a string.\n    module_version = f'{module_version!s}'\n\n    # Split the version string and convert every digit into an integer.\n    # A string compare of both version strings will yield an incorrect result.\n\n    # Strip any semantic suffixes such as a1, b1, pre, post, rc, dev.\n    module_version = self._VERSION_NUMBERS_REGEX.findall(module_version)[0]\n\n    if module_version[-1] == '.':\n      module_version = module_version[:-1]\n\n    try:\n      module_version_map = list(\n          map(int, self._VERSION_SPLIT_REGEX.split(module_version)))\n    except ValueError:\n      return False, (\n          f'unable to parse module version: {module_name:s} {module_version:s}')\n\n    if minimum_version:\n      try:\n        minimum_version_map = list(\n            map(int, self._VERSION_SPLIT_REGEX.split(minimum_version)))\n      except ValueError:\n        return False, (\n            f'unable to parse minimum version: {module_name:s} '\n            f'{minimum_version:s}')\n\n      if module_version_map < minimum_version_map:\n        return False, (\n            f'{module_name:s} version: {module_version!s} is too old, '\n            f'{minimum_version!s} or later required')\n\n    if maximum_version:\n      try:\n        maximum_version_map = list(\n            map(int, self._VERSION_SPLIT_REGEX.split(maximum_version)))\n      except ValueError:\n        return False, (\n            f'unable to parse maximum version: {module_name:s} '\n            f'{maximum_version:s}')\n\n      if module_version_map > maximum_version_map:\n        return False, (\n            f'{module_name:s} version: {module_version!s} is too recent, '\n            f'{maximum_version!s} or earlier required')\n\n    return True, f'{module_name:s} version: {module_version!s}'\n\n  def _ImportPythonModule(self, module_name):\n    \"\"\"Imports a Python module.\n\n    Args:\n      module_name (str): name of the module.\n\n    Returns:\n      module: Python module or None if the module cannot be imported.\n    \"\"\"\n    try:\n      module_object = list(map(__import__, [module_name]))[0]\n    except ImportError:\n      return None\n\n    # If the module name contains dots get the upper most module object.\n    if '.' in module_name:\n      for submodule_name in module_name.split('.')[1:]:\n        module_object = getattr(module_object, submodule_name, None)\n\n    return module_object\n\n  def _PrintCheckDependencyStatus(\n      self, dependency, result, status_message, verbose_output=True):\n    \"\"\"Prints the check dependency status.\n\n    Args:\n      dependency (DependencyDefinition): dependency definition.\n      result (bool): True if the Python module is available and conforms to\n            the minimum required version, False otherwise.\n      status_message (str): status message.\n      verbose_output (Optional[bool]): True if output should be verbose.\n    \"\"\"\n    if not result or dependency.is_optional:\n      if dependency.is_optional:\n        status_indicator = '[OPTIONAL]'\n      else:\n        status_indicator = '[FAILURE]'\n\n      print(f'{status_indicator:s}\\t{status_message:s}')\n\n    elif verbose_output:\n      print(f'[OK]\\t\\t{status_message:s}')\n\n  def CheckDependencies(self, verbose_output=True):\n    \"\"\"Checks the availability of the dependencies.\n\n    Args:\n      verbose_output (Optional[bool]): True if output should be verbose.\n\n    Returns:\n      bool: True if the dependencies are available, False otherwise.\n    \"\"\"\n    print('Checking availability and versions of dependencies.')\n    check_result = True\n\n    for _, dependency in sorted(self.dependencies.items()):\n      if dependency.skip_check:\n        continue\n\n      result, status_message = self._CheckPythonModule(dependency)\n\n      if not result and not dependency.is_optional:\n        check_result = False\n\n      self._PrintCheckDependencyStatus(\n          dependency, result, status_message, verbose_output=verbose_output)\n\n    if check_result and not verbose_output:\n      print('[OK]')\n\n    print('')\n    return check_result\n\n  def CheckTestDependencies(self, verbose_output=True):\n    \"\"\"Checks the availability of the dependencies when running tests.\n\n    Args:\n      verbose_output (Optional[bool]): True if output should be verbose.\n\n    Returns:\n      bool: True if the dependencies are available, False otherwise.\n    \"\"\"\n    if not self.CheckDependencies(verbose_output=verbose_output):\n      return False\n\n    print('Checking availability and versions of test dependencies.')\n    check_result = True\n\n    for dependency in sorted(\n        self._test_dependencies.values(),\n        key=lambda dependency: dependency.name):\n      if dependency.skip_check:\n        continue\n\n      result, status_message = self._CheckPythonModule(dependency)\n\n      if not result and not dependency.is_optional:\n        check_result = False\n\n      self._PrintCheckDependencyStatus(\n          dependency, result, status_message, verbose_output=verbose_output)\n\n    if check_result and not verbose_output:\n      print('[OK]')\n\n    print('')\n    return check_result\n"
  },
  {
    "path": "utils/update_release.sh",
    "content": "#!/bin/bash\n#\n# Script that makes changes in preparation of a new release, such as updating\n# the version and documentation.\n\nEXIT_FAILURE=1;\nEXIT_SUCCESS=0;\n\nVERSION=$(date -u +\"%Y%m%d\")\n\n# Update the Python module version.\nsed \"s/__version__ = '[0-9]*'/__version__ = '${VERSION}'/\" -i winregrc/__init__.py\n\n# Update the version in the pyproject configuration.\nsed \"s/version = \\\"[0-9]*\\\"/version = \\\"${VERSION}\\\"/\" -i pyproject.toml\n\n# Ensure shebangs of Python scripts are consistent.\nfind . -name \\*.py -exec sed '1s?^#!.*$?#!/usr/bin/env python3?' -i {} \\;\n\n# Update the version in the dpkg configuration files.\nDPKG_DATE=$(date -R)\n\ncat > config/dpkg/changelog << EOT\nwinreg-kb (${VERSION}-1) unstable; urgency=low\n\n  * Auto-generated\n\n -- Joachim Metz <joachim.metz@gmail.com>  ${DPKG_DATE}\nEOT\n\n# Regenerate the API documentation.\ntox -edocs\n\nexit ${EXIT_SUCCESS};\n\n"
  },
  {
    "path": "winreg-kb.ini",
    "content": "[project]\nname: winreg-kb\nstatus: experimental\nname_description: Windows Registry knowledge base (winreg-kb)\nmaintainer: Joachim Metz <joachim.metz@gmail.com>\nhomepage_url: https://github.com/libyal/winreg-kb\ngit_url: https://github.com/libyal/winreg-kb.git\ndescription_short: Windows Registry resources (winregrc)\ndescription_long: winregrc is a Python module part of winreg-kb to allow reuse of\n    Windows Registry resources.\n"
  },
  {
    "path": "winregrc/__init__.py",
    "content": "\"\"\"Windows Registry resources (winregrc).\"\"\"\n\n__version__ = '20260413'\n"
  },
  {
    "path": "winregrc/appcompatcache.py",
    "content": "\"\"\"Application Compatibility Cache collector.\"\"\"\n\nimport logging\n\nfrom dtfabric.runtime import data_maps as dtfabric_data_maps\n\nfrom winregrc import data_format\nfrom winregrc import errors\nfrom winregrc import interface\n\n\nclass AppCompatCacheHeader:\n  \"\"\"Application Compatibility Cache header.\n\n  Attributes:\n    number_of_cached_entries (int): number of cached entries.\n    header_size (int): header size.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes an Application Compatibility Cache header.\"\"\"\n    super().__init__()\n    self.number_of_cached_entries = 0\n    self.header_size = 0\n\n\nclass AppCompatCacheCachedEntry:\n  \"\"\"Application Compatibility Cache cached entry.\n\n  Attributes:\n    cached_entry_size (int): size of the cached entry.\n    data (bytes): data of the cached entry.\n    file_size (int): size of file corresponding to the cached entry.\n    insertion_flags (int): insertion flags of the cached entry.\n    last_modification_time (int): last modification timestamp of the file\n        corresponding to the cached entry.\n    last_update_time (int): last update timestamp the cached entry.\n    shim_flags (int): shim flags of the cached entry.\n    path (str): path of the cached entry.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes an Application Compatibility Cache cached entry.\"\"\"\n    super().__init__()\n    self.cached_entry_size = 0\n    self.data = None\n    self.file_size = None\n    self.insertion_flags = None\n    self.last_modification_time = None\n    self.last_update_time = None\n    self.shim_flags = None\n    self.path = None\n\n\nclass AppCompatCacheDataParser(data_format.BinaryDataFormat):\n  \"\"\"Application Compatibility Cache data parser.\"\"\"\n\n  _DEFINITION_FILE = 'appcompatcache.yaml'\n\n  _FORMAT_TYPE_2000 = 1\n  _FORMAT_TYPE_XP = 2\n  _FORMAT_TYPE_2003 = 3\n  _FORMAT_TYPE_VISTA = 4\n  _FORMAT_TYPE_7 = 5\n  _FORMAT_TYPE_8 = 6\n  _FORMAT_TYPE_10 = 7\n\n  _HEADER_SIGNATURES = {\n      # AppCompatCache format signature used in Windows XP.\n      0xdeadbeef: _FORMAT_TYPE_XP,\n      # AppCompatCache format signature used in Windows 2003, Vista and 2008.\n      0xbadc0ffe: _FORMAT_TYPE_2003,\n      # AppCompatCache format signature used in Windows 7 and 2008 R2.\n      0xbadc0fee: _FORMAT_TYPE_7,\n      # AppCompatCache format used in Windows 8.0 and 8.1.\n      0x00000080: _FORMAT_TYPE_8,\n      # AppCompatCache format used in Windows 10\n      0x00000030: _FORMAT_TYPE_10,\n      0x00000034: _FORMAT_TYPE_10}\n\n  _HEADER_DATA_TYPE_MAP_NAMES = {\n      _FORMAT_TYPE_XP: 'appcompatcache_header_xp_32bit',\n      _FORMAT_TYPE_2003: 'appcompatcache_header_2003',\n      _FORMAT_TYPE_VISTA: 'appcompatcache_header_vista',\n      _FORMAT_TYPE_7: 'appcompatcache_header_7',\n      _FORMAT_TYPE_8: 'appcompatcache_header_8',\n      _FORMAT_TYPE_10: 'appcompatcache_header_10'}\n\n  _SUPPORTED_FORMAT_TYPES = frozenset(_HEADER_DATA_TYPE_MAP_NAMES.keys())\n\n  # AppCompatCache format used in Windows 8.0.\n  _CACHED_ENTRY_SIGNATURE_8_0 = b'00ts'\n\n  # AppCompatCache format used in Windows 8.1.\n  _CACHED_ENTRY_SIGNATURE_8_1 = b'10ts'\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes an Application Compatibility Cache data parser.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be written.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__(\n        debug=debug, output_writer=output_writer)\n    self._cached_entry_data_type_map = None\n\n  def _DebugPrintCachedEntryXP(self, cached_entry):\n    \"\"\"Prints Windows XP AppCompatCache cached entry value debug information.\n\n    Args:\n      cached_entry (appcompatcache_cached_entry_xp_32bit): Windows XP\n          AppCompatCache cached entry.\n    \"\"\"\n    # TODO: have dtFabric handle string conversion.\n    string_size = 0\n    for string_index in range(0, 528, 2):\n      if (cached_entry.path[string_index] == 0 and\n          cached_entry.path[string_index + 1] == 0):\n        break\n      string_size += 2\n\n    path = bytearray(cached_entry.path[0:string_size]).decode('utf-16-le')\n    self._DebugPrintValue('Path', path)\n\n    self._DebugPrintDecimalValue('File size', cached_entry.file_size)\n\n    self._DebugPrintFiletimeValue(\n        'Last update time', cached_entry.last_update_time)\n\n  def _DebugPrintCachedEntry2003(self, cached_entry):\n    \"\"\"Prints Windows 2003 AppCompatCache cached entry value debug information.\n\n    Args:\n      cached_entry_common (appcompatcache_cached_entry_2003_32bit|\n                           appcompatcache_cached_entry_2003_64bit|\n                           appcompatcache_cached_entry_vista_32bit|\n                           appcompatcache_cached_entry_vista_64bit|\n                           appcompatcache_cached_entry_7_32bit|\n                           appcompatcache_cached_entry_7_64bit): Windows 2003,\n          Vista or 7 AppCompatCache cached entry.\n    \"\"\"\n    self._DebugPrintDecimalValue('Path size', cached_entry.path_size)\n\n    self._DebugPrintDecimalValue(\n        'Maximum path size', cached_entry.maximum_path_size)\n\n    self._DebugPrintValue('Path offset', f'0x{cached_entry.path_offset:08x}')\n\n    if hasattr(cached_entry, 'file_size'):\n      self._DebugPrintDecimalValue('File size', cached_entry.file_size)\n\n    if hasattr(cached_entry, 'insertion_flags'):\n      self._DebugPrintValue(\n          'Insertion flags', f'0x{cached_entry.insertion_flags:08x}')\n\n    if hasattr(cached_entry, 'shim_flags'):\n      self._DebugPrintValue('Shim flags', f'0x{cached_entry.shim_flags:08x}')\n\n    if hasattr(cached_entry, 'data_offset'):\n      self._DebugPrintValue('Data offset', f'0x{cached_entry.data_offset:08x}')\n\n    if hasattr(cached_entry, 'data_size'):\n      self._DebugPrintDecimalValue('Data size', cached_entry.data_size)\n\n  # pylint: disable=missing-type-doc\n  def _DebugPrintCachedEntry8(self, cached_entry_header, cached_entry_body):\n    \"\"\"Prints Windows 8 AppCompatCache cached entry value debug information.\n\n    Args:\n      cached_entry_header (appcompatcache_cached_entry_header_8): Windows 8 or\n          10 AppCompatCache cached entry header.\n      cached_entry_body (appcompatcache_cached_entry_header_8_0|\n          appcompatcache_cached_entry_header_8_1|\n          appcompatcache_cached_entry_header_10): Windows 8.0, 8.1 or 10\n          AppCompatCache cached entry body.\n    \"\"\"\n    self._DebugPrintValue(\n        'Signature', cached_entry_header.signature.decode('ascii'))\n\n    self._DebugPrintValue('Unknown1', f'0x{cached_entry_header.unknown1:08x}')\n\n    self._DebugPrintDecimalValue(\n        'Cached entry data size', cached_entry_header.cached_entry_data_size)\n\n    self._DebugPrintDecimalValue('Path size', cached_entry_body.path_size)\n\n    self._DebugPrintValue('Path', cached_entry_body.path.rstrip('\\x00'))\n\n    if hasattr(cached_entry_body, 'insertion_flags'):\n      self._DebugPrintValue(\n          'Insertion flags', f'0x{cached_entry_body.insertion_flags:08x}')\n\n    if hasattr(cached_entry_body, 'shim_flags'):\n      self._DebugPrintValue(\n          'Shim flags', f'0x{cached_entry_body.shim_flags:08x}')\n\n    if hasattr(cached_entry_body, 'unknown1'):\n      self._DebugPrintValue('Unknown1', f'0x{cached_entry_body.unknown1:04x}')\n\n    self._DebugPrintFiletimeValue(\n        'Last modification time', cached_entry_body.last_modification_time)\n\n    self._DebugPrintDecimalValue('Data size', cached_entry_body.data_size)\n\n  # pylint: disable=missing-type-doc\n  def _DebugPrintHeader(self, format_type, header):\n    \"\"\"Prints AppCompatCache header value debug information.\n\n    Args:\n      format_type (int): AppCompatCache format type.\n      header (appcompatcache_header_xp_32bit|appcompatcache_header_vista|\n          appcompatcache_header_7|appcompatcache_header_8|\n          appcompatcache_header_10): AppCompatCache header.\n    \"\"\"\n    if format_type == self._FORMAT_TYPE_10:\n      self._DebugPrintDecimalValue('Header size', header.signature)\n    else:\n      self._DebugPrintValue('Signature', f'0x{header.signature:08x}')\n\n    if format_type in (\n        self._FORMAT_TYPE_XP, self._FORMAT_TYPE_2003, self._FORMAT_TYPE_VISTA,\n        self._FORMAT_TYPE_7, self._FORMAT_TYPE_10):\n      self._DebugPrintDecimalValue(\n          'Number of cached entries', header.number_of_cached_entries)\n\n    if format_type == self._FORMAT_TYPE_XP:\n      if self._debug:\n        self._DebugPrintValue(\n            'Number of LRU entries', f'0x{header.number_of_lru_entries:08x}')\n\n        self._DebugPrintValue('Unknown1', f'0x{header.unknown1:08x}')\n\n    elif format_type == self._FORMAT_TYPE_8:\n      self._DebugPrintValue('Unknown1', f'0x{header.unknown1:08x}')\n\n    if format_type != self._FORMAT_TYPE_XP:\n      self._DebugPrintText('\\n')\n\n  def _GetCachedEntryDataTypeMap(\n      self, format_type, value_data, cached_entry_offset):\n    \"\"\"Determines the cached entry data type map.\n\n    Args:\n      format_type (int): format type.\n      value_data (bytes): value data.\n      cached_entry_offset (int): offset of the first cached entry data\n          relative to the start of the value data.\n\n    Returns:\n      dtfabric.DataTypeMap: data type map which contains a data type definition,\n          such as a structure, that can be mapped onto binary data or None\n          if the data type map is not defined.\n\n    Raises:\n      ParseError: if the cached entry data type map cannot be determined.\n    \"\"\"\n    if format_type not in self._SUPPORTED_FORMAT_TYPES:\n      raise errors.ParseError(f'Unsupported format type: {format_type:d}')\n\n    data_type_map_name = ''\n\n    if format_type == self._FORMAT_TYPE_XP:\n      data_type_map_name = 'appcompatcache_cached_entry_xp_32bit'\n\n    elif format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10):\n      data_type_map_name = 'appcompatcache_cached_entry_header_8'\n\n    else:\n      cached_entry = self._ParseCommon2003CachedEntry(\n          value_data, cached_entry_offset)\n\n      # Assume the entry is 64-bit if the 32-bit path offset is 0 and\n      # the 64-bit path offset is set.\n      if (cached_entry.path_offset_32bit == 0 and\n          cached_entry.path_offset_64bit != 0):\n        number_of_bits = '64'\n      else:\n        number_of_bits = '32'\n\n      if format_type == self._FORMAT_TYPE_2003:\n        data_type_map_name = (\n            f'appcompatcache_cached_entry_2003_{number_of_bits:s}bit')\n      elif format_type == self._FORMAT_TYPE_VISTA:\n        data_type_map_name = (\n            f'appcompatcache_cached_entry_vista_{number_of_bits:s}bit')\n      elif format_type == self._FORMAT_TYPE_7:\n        data_type_map_name = (\n            f'appcompatcache_cached_entry_7_{number_of_bits:s}bit')\n\n    return self._GetDataTypeMap(data_type_map_name)\n\n  def _ParseCommon2003CachedEntry(self, value_data, cached_entry_offset):\n    \"\"\"Parses the cached entry structure common for Windows 2003, Vista and 7.\n\n    Args:\n      value_data (bytes): value data.\n      cached_entry_offset (int): offset of the first cached entry data\n          relative to the start of the value data.\n\n    Returns:\n      appcompatcache_cached_entry_2003_common: cached entry structure common\n          for Windows 2003, Windows Vista and Windows 7.\n\n    Raises:\n      ParseError: if the value data could not be parsed.\n    \"\"\"\n    cached_entry_data = value_data[cached_entry_offset:]\n\n    data_type_map = self._GetDataTypeMap(\n        'appcompatcache_cached_entry_2003_common')\n\n    try:\n      cached_entry = self._ReadStructureFromByteStream(\n          cached_entry_data, cached_entry_offset, data_type_map,\n          'cached entry')\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse cached entry value with error: {exception!s}')\n\n    if cached_entry.path_size > cached_entry.maximum_path_size:\n      raise errors.ParseError('Path size value out of bounds.')\n\n    path_end_of_string_size = (\n        cached_entry.maximum_path_size - cached_entry.path_size)\n    if cached_entry.path_size == 0 or path_end_of_string_size != 2:\n      raise errors.ParseError('Unsupported path size values.')\n\n    return cached_entry\n\n  def CheckSignature(self, value_data):\n    \"\"\"Parses and validates the signature.\n\n    Args:\n      value_data (bytes): value data.\n\n    Returns:\n      int: format type or None if format could not be determined.\n\n    Raises:\n      ParseError: if the value data could not be parsed.\n    \"\"\"\n    data_type_map = self._GetDataTypeMap('uint32le')\n\n    try:\n      signature = self._ReadStructureFromByteStream(\n          value_data, 0, data_type_map, 'signature')\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse signature value with error: {exception!s}')\n\n    format_type = self._HEADER_SIGNATURES.get(signature)\n\n    if format_type == self._FORMAT_TYPE_2003:\n      # TODO: determine which format version is used (2003 or Vista).\n      return self._FORMAT_TYPE_2003\n\n    if format_type == self._FORMAT_TYPE_8:\n      cached_entry_signature = value_data[signature:signature + 4]\n      if cached_entry_signature in (\n          self._CACHED_ENTRY_SIGNATURE_8_0, self._CACHED_ENTRY_SIGNATURE_8_1):\n        return self._FORMAT_TYPE_8\n\n    elif format_type == self._FORMAT_TYPE_10:\n      # Windows 10 uses the same cache entry signature as Windows 8.1\n      cached_entry_signature = value_data[signature:signature + 4]\n      if cached_entry_signature == self._CACHED_ENTRY_SIGNATURE_8_1:\n        return self._FORMAT_TYPE_10\n\n    return format_type\n\n  def ParseCachedEntry(\n      self, format_type, value_data, cached_entry_index, cached_entry_offset):\n    \"\"\"Parses a cached entry.\n\n    Args:\n      format_type (int): format type.\n      value_data (bytes): value data.\n      cached_entry_index (int): cached entry index.\n      cached_entry_offset (int): offset of the first cached entry data\n          relative to the start of the value data.\n\n    Returns:\n      AppCompatCacheCachedEntry: cached entry.\n\n    Raises:\n      ParseError: if the value data could not be parsed.\n    \"\"\"\n    if not self._cached_entry_data_type_map:\n      self._cached_entry_data_type_map = self._GetCachedEntryDataTypeMap(\n          format_type, value_data, cached_entry_offset)\n\n    if not self._cached_entry_data_type_map:\n      raise errors.ParseError('Unable to determine cached entry data type.')\n\n    cached_entry_size = self._cached_entry_data_type_map.GetSizeHint()\n    cached_entry_end_offset = cached_entry_offset + cached_entry_size\n    cached_entry_data = value_data[cached_entry_offset:cached_entry_end_offset]\n\n    if self._debug:\n      if format_type not in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10):\n        description = f'Cached entry: {cached_entry_index:d} data'\n        self._DebugPrintData(description, cached_entry_data)\n\n    try:\n      cached_entry = self._ReadStructureFromByteStream(\n          cached_entry_data, cached_entry_offset,\n          self._cached_entry_data_type_map, 'cached entry')\n    except (ValueError, errors.ParseError) as exception:\n      if self._debug:\n        if format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10):\n          description = f'Cached entry: {cached_entry_index:d} header data'\n          self._DebugPrintData(description, cached_entry_data)\n\n      raise errors.ParseError(\n          f'Unable to parse cached entry value with error: {exception!s}')\n\n    if format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10):\n      if cached_entry.signature not in (\n          self._CACHED_ENTRY_SIGNATURE_8_0, self._CACHED_ENTRY_SIGNATURE_8_1):\n        if self._debug:\n          description = f'Cached entry: {cached_entry_index:d} header data'\n          self._DebugPrintData(description, cached_entry_data)\n\n        raise errors.ParseError('Unsupported cache entry signature')\n\n    cached_entry_object = AppCompatCacheCachedEntry()\n\n    data_offset = 0\n    data_size = 0\n\n    if format_type == self._FORMAT_TYPE_XP:\n      if self._debug:\n        self._DebugPrintCachedEntryXP(cached_entry)\n\n      # TODO: have dtFabric handle string conversion.\n      string_size = 0\n      for string_index in range(0, 528, 2):\n        if (cached_entry.path[string_index] == 0 and\n            cached_entry.path[string_index + 1] == 0):\n          break\n        string_size += 2\n\n      last_modification_time = cached_entry.last_modification_time\n      path = bytearray(cached_entry.path[0:string_size]).decode('utf-16-le')\n\n      cached_entry_object.last_update_time = cached_entry.last_update_time\n\n    elif format_type in (\n        self._FORMAT_TYPE_2003, self._FORMAT_TYPE_VISTA, self._FORMAT_TYPE_7):\n      if self._debug:\n        self._DebugPrintCachedEntry2003(cached_entry)\n\n      last_modification_time = cached_entry.last_modification_time\n\n      if format_type in (self._FORMAT_TYPE_VISTA, self._FORMAT_TYPE_7):\n        cached_entry_object.insertion_flags = cached_entry.insertion_flags\n        cached_entry_object.shim_flags = cached_entry.shim_flags\n\n      path_size = cached_entry.path_size\n      maximum_path_size = cached_entry.maximum_path_size\n      path_offset = cached_entry.path_offset\n\n      if path_offset > 0 and path_size > 0:\n        path_size += path_offset\n        maximum_path_size += path_offset\n\n        if self._debug:\n          self._DebugPrintData(\n              'Path data', value_data[path_offset:maximum_path_size])\n\n        path = value_data[path_offset:path_size].decode('utf-16-le')\n\n        if self._debug:\n          self._DebugPrintValue('Path', path)\n\n      if format_type == self._FORMAT_TYPE_7:\n        data_offset = cached_entry.data_offset\n        data_size = cached_entry.data_size\n\n    elif format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10):\n      cached_entry_data_size = cached_entry.cached_entry_data_size\n      cached_entry_size = 12 + cached_entry_data_size\n      cached_entry_end_offset = cached_entry_offset + cached_entry_size\n\n      cached_entry_data = value_data[\n          cached_entry_offset:cached_entry_end_offset]\n\n      if self._debug:\n        description = f'Cached entry: {cached_entry_index:d} data'\n        self._DebugPrintData(description, cached_entry_data)\n\n      if format_type == self._FORMAT_TYPE_10:\n        data_type_map_name = 'appcompatcache_cached_entry_body_10'\n      elif cached_entry.signature == self._CACHED_ENTRY_SIGNATURE_8_0:\n        data_type_map_name = 'appcompatcache_cached_entry_body_8_0'\n      elif cached_entry.signature == self._CACHED_ENTRY_SIGNATURE_8_1:\n        data_type_map_name = 'appcompatcache_cached_entry_body_8_1'\n      else:\n        data_type_map_name = None\n\n      data_type_map = self._GetDataTypeMap(data_type_map_name)\n      context = dtfabric_data_maps.DataTypeMapContext()\n\n      try:\n        cached_entry_body = self._ReadStructureFromByteStream(\n            cached_entry_data[12:], cached_entry_offset + 12,\n            data_type_map, 'cached entry body', context=context)\n      except (ValueError, errors.ParseError) as exception:\n        raise errors.ParseError(\n            f'Unable to parse cached entry body with error: {exception!s}')\n\n      if self._debug:\n        self._DebugPrintCachedEntry8(cached_entry, cached_entry_body)\n\n      last_modification_time = cached_entry_body.last_modification_time\n      path = cached_entry_body.path\n\n      if format_type == self._FORMAT_TYPE_8:\n        cached_entry_object.insertion_flags = cached_entry_body.insertion_flags\n        cached_entry_object.shim_flags = cached_entry_body.shim_flags\n\n      data_offset = cached_entry_offset + context.byte_size\n      data_size = cached_entry_body.data_size\n\n    if self._debug:\n      self._DebugPrintText('\\n')\n\n    cached_entry_object.cached_entry_size = cached_entry_size\n    cached_entry_object.file_size = getattr(cached_entry, 'file_size', None)\n    cached_entry_object.last_modification_time = last_modification_time\n    cached_entry_object.path = path\n\n    if data_size > 0:\n      cached_entry_object.data = value_data[data_offset:data_offset + data_size]\n\n      if self._debug:\n        self._DebugPrintData('Data', cached_entry_object.data)\n\n    return cached_entry_object\n\n  def ParseHeader(self, format_type, value_data):\n    \"\"\"Parses the header.\n\n    Args:\n      format_type (int): format type.\n      value_data (bytes): value data.\n\n    Returns:\n      AppCompatCacheHeader: header.\n\n    Raises:\n      ParseError: if the value data could not be parsed.\n    \"\"\"\n    data_type_map_name = self._HEADER_DATA_TYPE_MAP_NAMES.get(format_type)\n    if not data_type_map_name:\n      raise errors.ParseError(f'Unsupported format type: {format_type:d}')\n\n    data_type_map = self._GetDataTypeMap(data_type_map_name)\n    context = dtfabric_data_maps.DataTypeMapContext()\n\n    try:\n      header = self._ReadStructureFromByteStream(\n          value_data, 0, data_type_map, 'header', context=context)\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse header value with error: {exception!s}')\n\n    header_data_size = context.byte_size\n    if format_type == self._FORMAT_TYPE_10:\n      header_data_size = header.signature\n\n    cache_header = AppCompatCacheHeader()\n    cache_header.header_size = header_data_size\n    cache_header.number_of_cached_entries = getattr(\n        header, 'number_of_cached_entries', None)\n\n    if self._debug:\n      self._DebugPrintHeader(format_type, header)\n\n    if format_type == self._FORMAT_TYPE_XP:\n      if self._debug:\n        self._DebugPrintText('LRU entries:')\n\n      data_offset = 16\n      number_of_lru_entries = header.number_of_lru_entries\n      if 0 <= number_of_lru_entries <= 96:\n        data_type_map = self._GetDataTypeMap('uint32le')\n\n        for lru_entry_index in range(number_of_lru_entries):\n          try:\n            lru_entry = self._ReadStructureFromByteStream(\n                value_data[data_offset:data_offset + 4], data_offset,\n                data_type_map, 'LRU entry')\n          except (ValueError, errors.ParseError) as exception:\n            raise errors.ParseError(\n                f'Unable to parse LRU entry value with error: {exception!s}')\n\n          data_offset += 4\n\n          if self._debug:\n            offset_value = 400 + (lru_entry * 552)\n            description = f'LRU entry: {lru_entry_index:d}'\n            value_string = f'{lru_entry:d} (offset: 0x{offset_value:08x})'\n            self._DebugPrintValue(description, value_string)\n\n        if self._debug:\n          self._DebugPrintText('\\n')\n\n      if self._debug:\n        self._DebugPrintData('Unknown data', value_data[data_offset:400])\n\n    self._cached_entry_data_type_map = None\n\n    return cache_header\n\n\nclass AppCompatCacheCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Application Compatibility Cache collector.\n\n  Attributes:\n    cached_entries (list[AppCompatCacheCachedEntry]): cached entries.\n  \"\"\"\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a Application Compatibility Cache collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__(debug=debug)\n    self._parser = AppCompatCacheDataParser(\n        debug=self._debug, output_writer=output_writer)\n    self._output_writer = output_writer\n    self.cached_entries = []\n\n  def _CollectAppCompatCacheFromKey(self, app_compat_cache_key):\n    \"\"\"Collects Application Compatibility Cache from a Windows Registry key.\n\n    Args:\n      app_compat_cache_key (dfwinreg.WinRegistryKey): Application Compatibility\n          Cache Windows Registry key.\n\n    Returns:\n      bool: True if the Application Compatibility Cache key was found,\n          False if not.\n    \"\"\"\n    value = app_compat_cache_key.GetValueByName('AppCompatCache')\n    if not value:\n      logging.warning(\n          f'Missing AppCompatCache value in key: {app_compat_cache_key.path:s}')\n      return True\n\n    value_data = value.data\n    value_data_size = len(value.data)\n\n    # TODO: add non debug output\n    if self._debug:\n      self._output_writer.WriteDebugData('Value data:\\n', value_data)\n\n    format_type = self._parser.CheckSignature(value_data)\n    if not format_type:\n      logging.warning('Unsupported signature.')\n      return True\n\n    cache_header = self._parser.ParseHeader(format_type, value_data)\n\n    # On Windows Vista and 2008 when the cache is empty it will\n    # only consist of the header.\n    if value_data_size <= cache_header.header_size:\n      return True\n\n    cached_entry_offset = cache_header.header_size\n    cached_entry_index = 0\n\n    while cached_entry_offset < value_data_size:\n      cached_entry = self._parser.ParseCachedEntry(\n          format_type, value_data, cached_entry_index, cached_entry_offset)\n\n      self.cached_entries.append(cached_entry)\n\n      cached_entry_offset += cached_entry.cached_entry_size\n      cached_entry_index += 1\n\n      if (cache_header.number_of_cached_entries != 0 and\n          cached_entry_index >= cache_header.number_of_cached_entries):\n        break\n\n    return True\n\n  def Collect(self, registry, all_control_sets=False):\n    \"\"\"Collects the Application Compatibility Cache.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n      all_control_sets (Optional[bool]): True if the services should be\n          collected from all control sets instead of only the current control\n          set.\n\n    Returns:\n      bool: True if the Application Compatibility Cache key was found,\n          False if not.\n    \"\"\"\n    result = False\n\n    if all_control_sets:\n      system_key = registry.GetKeyByPath('HKEY_LOCAL_MACHINE\\\\System\\\\')\n      if not system_key:\n        return result\n\n      for control_set_key in system_key.GetSubkeys():\n        if control_set_key.name.startswith('ControlSet'):\n          # Windows XP\n          app_compat_cache_key = control_set_key.GetSubkeyByPath(\n              'Control\\\\Session Manager\\\\AppCompatibility')\n          if app_compat_cache_key:\n            if self._CollectAppCompatCacheFromKey(app_compat_cache_key):\n              result = True\n\n          # Windows 2003 and later\n          app_compat_cache_key = control_set_key.GetSubkeyByPath(\n              'Control\\\\Session Manager\\\\AppCompatCache')\n          if app_compat_cache_key:\n            if self._CollectAppCompatCacheFromKey(app_compat_cache_key):\n              result = True\n    else:\n      # Windows XP\n      key_path = (\n          'HKEY_LOCAL_MACHINE\\\\System\\\\CurrentControlSet\\\\Control\\\\'\n          'Session Manager\\\\AppCompatibility')\n\n      try:\n        app_compat_cache_key = registry.GetKeyByPath(key_path)\n      except RuntimeError:\n        app_compat_cache_key = None\n\n      if app_compat_cache_key:\n        if self._CollectAppCompatCacheFromKey(app_compat_cache_key):\n          result = True\n\n      # Windows 2003 and later\n      key_path = (\n          'HKEY_LOCAL_MACHINE\\\\System\\\\CurrentControlSet\\\\Control\\\\'\n          'Session Manager\\\\AppCompatCache')\n\n      try:\n        app_compat_cache_key = registry.GetKeyByPath(key_path)\n      except RuntimeError:\n        app_compat_cache_key = None\n\n      if app_compat_cache_key:\n        if self._CollectAppCompatCacheFromKey(app_compat_cache_key):\n          result = True\n\n    return result\n"
  },
  {
    "path": "winregrc/appcompatcache.yaml",
    "content": "# dtFabric format specification.\n---\nname: appcompatcache\ntype: format\ndescription: Application Compatibility Cache format\n---\nname: byte\ntype: integer\nattributes:\n  format: unsigned\n  size: 1\n  units: bytes\n---\nname: uint16\ntype: integer\nattributes:\n  format: unsigned\n  size: 2\n  units: bytes\n---\nname: uint32\ntype: integer\nattributes:\n  format: unsigned\n  size: 4\n  units: bytes\n---\nname: uint64\ntype: integer\nattributes:\n  format: unsigned\n  size: 8\n  units: bytes\n---\nname: uint16le\ntype: integer\nattributes:\n  byte_order: little-endian\n  format: unsigned\n  size: 2\n  units: bytes\n---\nname: uint32le\ntype: integer\nattributes:\n  byte_order: little-endian\n  format: unsigned\n  size: 4\n  units: bytes\n---\nname: uint64le\ntype: integer\nattributes:\n  byte_order: little-endian\n  format: unsigned\n  size: 8\n  units: bytes\n---\nname: wchar16\ntype: character\nattributes:\n  size: 2\n  units: bytes\n---\nname: appcompatcache_header_xp_32bit\ntype: structure\ndescription: Windows XP 32-bit AppCompatCache header.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: signature\n  data_type: uint32\n- name: number_of_cached_entries\n  data_type: uint32\n- name: number_of_lru_entries\n  data_type: uint32\n- name: unknown1\n  data_type: uint32\n- name: lru_entries\n  type: sequence\n  element_data_type: uint32\n  number_of_elements: 96\n---\nname: appcompatcache_cached_entry_xp_32bit\ntype: structure\ndescription: Windows XP 32-bit AppCompatCache cached entry.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: path\n  type: sequence\n  element_data_type: byte\n  number_of_elements: 528\n- name: last_modification_time\n  data_type: uint64\n- name: file_size\n  data_type: uint64\n- name: last_update_time\n  data_type: uint64\n---\nname: appcompatcache_header_2003\ntype: structure\ndescription: Windows 2003 AppCompatCache header.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: signature\n  data_type: uint32\n- name: number_of_cached_entries\n  data_type: uint32\n---\nname: appcompatcache_cached_entry_2003_common\ntype: structure\ndescription: Windows 2003, Vista, 7 common AppCompatCache cached entry.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: path_size\n  data_type: uint16\n- name: maximum_path_size\n  data_type: uint16\n- name: path_offset_32bit\n  data_type: uint32\n- name: path_offset_64bit\n  data_type: uint64\n---\nname: appcompatcache_cached_entry_2003_32bit\ntype: structure\ndescription: Windows 2003 32-bit AppCompatCache cached entry.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: path_size\n  data_type: uint16\n- name: maximum_path_size\n  data_type: uint16\n- name: path_offset\n  data_type: uint32\n- name: last_modification_time\n  data_type: uint64\n- name: file_size\n  data_type: uint64\n---\nname: appcompatcache_cached_entry_2003_64bit\ntype: structure\ndescription: Windows 2003 64-bit AppCompatCache cached entry.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: path_size\n  data_type: uint16\n- name: maximum_path_size\n  data_type: uint16\n- name: unknown1\n  data_type: uint32\n- name: path_offset\n  data_type: uint64\n- name: last_modification_time\n  data_type: uint64\n- name: file_size\n  data_type: uint64\n---\nname: appcompatcache_header_vista\ntype: structure\ndescription: Windows Vista and 2008 AppCompatCache header.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: signature\n  data_type: uint32\n- name: number_of_cached_entries\n  data_type: uint32\n---\nname: appcompatcache_cached_entry_vista_32bit\ntype: structure\ndescription: Windows Vista and 2008 32-bit AppCompatCache cached entry.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: path_size\n  data_type: uint16\n- name: maximum_path_size\n  data_type: uint16\n- name: path_offset\n  data_type: uint32\n- name: last_modification_time\n  data_type: uint64\n- name: insertion_flags\n  data_type: uint32\n- name: shim_flags\n  data_type: uint32\n---\nname: appcompatcache_cached_entry_vista_64bit\ntype: structure\ndescription: Windows Vista and 2008 64-bit AppCompatCache cached entry.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: path_size\n  data_type: uint16\n- name: maximum_path_size\n  data_type: uint16\n- name: unknown1\n  data_type: uint32\n- name: path_offset\n  data_type: uint64\n- name: last_modification_time\n  data_type: uint64\n- name: insertion_flags\n  data_type: uint32\n- name: shim_flags\n  data_type: uint32\n---\nname: appcompatcache_header_7\ntype: structure\ndescription: Windows 7 AppCompatCache header.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: signature\n  data_type: uint32\n- name: number_of_cached_entries\n  data_type: uint32\n- name: unknown1\n  type: sequence\n  element_data_type: byte\n  number_of_elements: 120\n---\nname: appcompatcache_cached_entry_7_32bit\ntype: structure\ndescription: Windows 7 and 2008 R2 32-bit AppCompatCache cached entry.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: path_size\n  data_type: uint16\n- name: maximum_path_size\n  data_type: uint16\n- name: path_offset\n  data_type: uint32\n- name: last_modification_time\n  data_type: uint64\n- name: insertion_flags\n  data_type: uint32\n- name: shim_flags\n  data_type: uint32\n- name: data_size\n  data_type: uint32\n- name: data_offset\n  data_type: uint32\n---\nname: appcompatcache_cached_entry_7_64bit\ntype: structure\ndescription: Windows 7 and 2008 R2 64-bit AppCompatCache cached entry.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: path_size\n  data_type: uint16\n- name: maximum_path_size\n  data_type: uint16\n- name: unknown1\n  data_type: uint32\n- name: path_offset\n  data_type: uint64\n- name: last_modification_time\n  data_type: uint64\n- name: insertion_flags\n  data_type: uint32\n- name: shim_flags\n  data_type: uint32\n- name: data_size\n  data_type: uint64\n- name: data_offset\n  data_type: uint64\n---\nname: appcompatcache_header_8\ntype: structure\ndescription: Windows 8 AppCompatCache header.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: signature\n  data_type: uint32\n- name: unknown1\n  data_type: uint32\n- name: unknown2\n  type: sequence\n  element_data_type: byte\n  number_of_elements: 120\n---\nname: appcompatcache_cached_entry_header_8\ntype: structure\ndescription: Windows 8 and 10 AppCompatCache header.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: signature\n  type: stream\n  element_data_type: byte\n  number_of_elements: 4\n- name: unknown1\n  data_type: uint32\n- name: cached_entry_data_size\n  data_type: uint32\n---\nname: appcompatcache_cached_entry_body_8_0\ntype: structure\ndescription: Windows 8.0 AppCompatCache body.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: path_size\n  data_type: uint16\n- name: path\n  type: string\n  encoding: utf-16-le\n  element_data_type: wchar16\n  elements_data_size: appcompatcache_cached_entry_body_8_0.path_size\n- name: insertion_flags\n  data_type: uint32\n- name: shim_flags\n  data_type: uint32\n- name: last_modification_time\n  data_type: uint64\n- name: data_size\n  data_type: uint32\n---\nname: appcompatcache_cached_entry_body_8_1\ntype: structure\ndescription: Windows 8.1 AppCompatCache body.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: path_size\n  data_type: uint16\n- name: path\n  type: string\n  encoding: utf-16-le\n  element_data_type: wchar16\n  elements_data_size: appcompatcache_cached_entry_body_8_1.path_size\n- name: insertion_flags\n  data_type: uint32\n- name: shim_flags\n  data_type: uint32\n- name: unknown1\n  data_type: uint16\n- name: last_modification_time\n  data_type: uint64\n- name: data_size\n  data_type: uint32\n---\nname: appcompatcache_cached_entry_body_10\ntype: structure\ndescription: Windows 10 AppCompatCache body.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: path_size\n  data_type: uint16\n- name: path\n  type: string\n  encoding: utf-16-le\n  element_data_type: wchar16\n  elements_data_size: appcompatcache_cached_entry_body_10.path_size\n- name: last_modification_time\n  data_type: uint64\n- name: data_size\n  data_type: uint32\n---\nname: appcompatcache_header_10\ntype: structure\ndescription: Windows 10 AppCompatCache header.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: signature\n  data_type: uint32\n- name: unknown1\n  data_type: uint32\n- name: unknown2\n  type: sequence\n  element_data_type: byte\n  number_of_elements: 28\n- name: number_of_cached_entries\n  data_type: uint32\n- name: unknown3\n  type: sequence\n  element_data_type: byte\n  number_of_elements: 8\n"
  },
  {
    "path": "winregrc/application_identifiers.py",
    "content": "\"\"\"Windows application identifiers (AppID) collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass ApplicationIdentifier:\n  \"\"\"Application identifier.\n\n  Attributes:\n    description (str): description.\n    guid (str): identifier.\n  \"\"\"\n\n  def __init__(self, guid, description):\n    \"\"\"Initializes an application identifier.\n\n    Args:\n      guid (str): identifier.\n      description (str): description.\n    \"\"\"\n    super().__init__()\n    self.description = description\n    self.guid = guid\n\n\nclass ApplicationIdentifiersCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows application identifiers collector.\"\"\"\n\n  _APPLICATION_IDENTIFIERS_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Classes\\\\AppID')\n\n  def _CollectApplicationIdentifiers(self, application_identifiers_key):\n    \"\"\"Collects Windows application identifiers (AppID).\n\n    Args:\n      application_identifiers_key (dfwinreg.WinRegistryKey): application\n          identifiers Windows Registry key.\n\n    Yields:\n      ApplicationIdentifier: an application identifier.\n    \"\"\"\n    for subkey in application_identifiers_key.GetSubkeys():\n      name = subkey.name.lower()\n\n      # Ignore subkeys that are not formatted as {%GUID%}\n      if len(name) == 38 and name[0] == '{' and name[37] == '}':\n        description = self._GetValueFromKey(subkey, '')\n\n        yield ApplicationIdentifier(name, description)\n\n  def Collect(self, registry):\n    \"\"\"Collects Windows application identifiers (AppID).\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Yields:\n      ApplicationIdentifier: an application identifier.\n    \"\"\"\n    application_identifiers_key = registry.GetKeyByPath(\n        self._APPLICATION_IDENTIFIERS_KEY_PATH)\n    if application_identifiers_key:\n      yield from self._CollectApplicationIdentifiers(\n          application_identifiers_key)\n"
  },
  {
    "path": "winregrc/cached_credentials.py",
    "content": "\"\"\"Domain cached credentials collector.\"\"\"\n\nimport codecs\nimport struct\n\nimport pyfcrypto\nimport pyhmac\n\nfrom winregrc import hexdump\nfrom winregrc import interface\n\n\nclass CachedCredentialsKeyCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Domain cached credentials key collector.\"\"\"\n\n  _CREDENTIALS_CACHE_KEY_PATH = 'HKEY_LOCAL_MACHINE\\\\Security\\\\Cache'\n\n  _NL_KEY_MATERIAL_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Security\\\\Policy\\\\Secrets\\\\NL$KM\\\\CurrVal')\n\n  _LSA_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\System\\\\CurrentControlSet\\\\Control\\\\Lsa')\n\n  _POLICY_ENCRYPTION_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Security\\\\Policy\\\\PolSecretEncryptionKey')\n\n  _ODD_PARITY_TABLE = [\n      1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, 16, 16, 19, 19, 21,\n      21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, 32, 32, 35, 35, 37, 37, 38,\n      38, 41, 41, 42, 42, 44, 44, 47, 47, 49, 49, 50, 50, 52, 52, 55, 55, 56,\n      56, 59, 59, 61, 61, 62, 62, 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74,\n      74, 76, 76, 79, 79, 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93,\n      93, 94, 94, 97, 97, 98, 98, 100, 100, 103, 103, 104, 104, 107, 107, 109,\n      109, 110, 110, 112, 112, 115, 115, 117, 117, 118, 118, 121, 121, 122, 122,\n      124, 124, 127, 127, 128, 128, 131, 131, 133, 133, 134, 134, 137, 137, 138,\n      138, 140, 140, 143, 143, 145, 145, 146, 146, 148, 148, 151, 151, 152, 152,\n      155, 155, 157, 157, 158, 158, 161, 161, 162, 162, 164, 164, 167, 167, 168,\n      168, 171, 171, 173, 173, 174, 174, 176, 176, 179, 179, 181, 181, 182, 182,\n      185, 185, 186, 186, 188, 188, 191, 191, 193, 193, 194, 194, 196, 196, 199,\n      199, 200, 200, 203, 203, 205, 205, 206, 206, 208, 208, 211, 211, 213, 213,\n      214, 214, 217, 217, 218, 218, 220, 220, 223, 223, 224, 224, 227, 227, 229,\n      229, 230, 230, 233, 233, 234, 234, 236, 236, 239, 239, 241, 241, 242, 242,\n      244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, 254]\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a system key collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__(debug=debug)\n    self._output_writer = output_writer\n\n  def _DecryptARC4(self, key, data):\n    \"\"\"Decrypts ARC4 encrypted data.\n\n    Args:\n      key (str): key used to decrypt the data.\n      data (bytes): data to decrypt.\n\n    Returns:\n      bytes: decrypted data.\n    \"\"\"\n    rc4_context = pyfcrypto.rc4_context()\n    rc4_context.set_key(key)\n\n    return pyfcrypto.crypt_rc4(rc4_context, data)\n\n  def _DecryptTripleDES(self, key, data):\n    \"\"\"Decrypts Triple DES-ECB encrypted data.\n\n    Args:\n      key (str): key used to decrypt the data.\n      data (bytes): data to decrypt.\n\n    Returns:\n      bytes: decrypted data.\n    \"\"\"\n    des3_context = pyfcrypto.des3_context()\n    des3_context.set_key(key)\n\n    return pyfcrypto.crypt_des3(\n        des3_context, pyfcrypto.crypt_modes.DECRYPT, data)\n\n  def _GetBootKey(self, registry):\n    \"\"\"Retrieves the boot key.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      bytes: boot key or None if not found.\n    \"\"\"\n    try:\n      lsa_key = registry.GetKeyByPath(self._LSA_KEY_PATH)\n    except RuntimeError:\n      lsa_key = None\n\n    if not lsa_key:\n      return None\n\n    lsa_jd_key = lsa_key.GetSubkeyByName('JD')\n    lsa_skew1_key = lsa_key.GetSubkeyByName('Skew1')\n    lsa_gbg_key = lsa_key.GetSubkeyByName('GBG')\n    lsa_data_key = lsa_key.GetSubkeyByName('Data')\n\n    if None in (lsa_jd_key, lsa_skew1_key, lsa_gbg_key, lsa_data_key):\n      return None\n\n    lsa_jd_class_name = lsa_jd_key.class_name\n    lsa_skew1_class_name = lsa_skew1_key.class_name\n    lsa_gbg_class_name = lsa_gbg_key.class_name\n    lsa_data_class_name = lsa_data_key.class_name\n\n    if None in (\n        lsa_jd_class_name, lsa_skew1_class_name, lsa_gbg_class_name,\n        lsa_data_class_name):\n      return None\n\n    class_name_string = ''.join([\n        lsa_jd_class_name, lsa_skew1_class_name, lsa_gbg_class_name,\n        lsa_data_class_name])\n\n    scrambled_key = codecs.decode(class_name_string, 'hex')\n    key = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n\n    for index, scrambled_index in enumerate([\n        8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7]):\n      key[index] = scrambled_key[scrambled_index]\n\n    return bytes(key)\n\n  def _GetLSAKey(self, registry, boot_key):\n    \"\"\"Retrieves the LSA key.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n      boot_key (bytes): boot key.\n\n    Returns:\n      bytes: LSA key or None if not found.\n    \"\"\"\n    policy_encryption_key = registry.GetKeyByPath(\n        self._POLICY_ENCRYPTION_KEY_PATH)\n    if not policy_encryption_key:\n      return None\n\n    policy_encryption_value = policy_encryption_key.GetValueByName('')\n    if not policy_encryption_value:\n      return None\n\n    value_data = policy_encryption_value.data\n\n    digest_context = pyhmac.md5_context()\n    digest_context.update(boot_key)\n\n    iteration = 0\n    while iteration < 1000:\n      digest_context.update(value_data[60:76])\n      iteration += 1\n\n    rc4_key = digest_context.finalize()\n    decrypted_data = self._DecryptARC4(rc4_key, value_data[12:60])\n    return decrypted_data[16:32]\n\n  def _GetNLKey(self, registry, lsa_key):\n    \"\"\"Retrieves the NL key.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n      lsa_key (bytes): LSA key.\n\n    Returns:\n      bytes: NL key or None if not found.\n    \"\"\"\n    nl_key_material_key = registry.GetKeyByPath(\n        self._NL_KEY_MATERIAL_KEY_PATH)\n    if not nl_key_material_key:\n      return None\n\n    nl_key_material_value = nl_key_material_key.GetValueByName('')\n    if not nl_key_material_value:\n      return None\n\n    key_size = len(lsa_key)\n    value_data = nl_key_material_value.data\n    value_data_size = len(value_data)\n\n    decrypted_value_data = []\n    key_offset = 0\n    for value_data_offset in range(12, value_data_size, 8):\n      key_end_offset = key_offset + 7\n      value_data_end_offset = value_data_offset + 8\n\n      des_key = self._UnpackLSAKey(lsa_key[key_offset:key_end_offset])\n      decrypted_data = self._DecryptTripleDES(\n          des_key, value_data[value_data_offset:value_data_end_offset])\n      decrypted_value_data.append(decrypted_data)\n\n      key_offset = key_end_offset\n\n      available_key_size = key_size - key_offset\n      if available_key_size < 7:\n        key_offset = available_key_size\n\n    decrypted_value_data = b''.join(decrypted_value_data)\n    print(hexdump.Hexdump(decrypted_value_data))\n\n    (data_size, ) = struct.unpack('<L', decrypted_value_data[:4])\n    data_size += 8\n\n    return decrypted_value_data[8:data_size]\n\n  def _UnpackLSAKey(self, lsa_key):\n    \"\"\"Unpacks 7 bytes of the LSA key as a 8-byte Triple DES decryption key.\n\n    Args:\n      lsa_key (bytes): LSA key.\n\n    Returns:\n      bytes: Triple DES decryption key.\n    \"\"\"\n    lsa_key = bytearray(lsa_key)\n    des_key = [\n        lsa_key[0] >> 1,\n        (lsa_key[0] & 0x01) << 6 | lsa_key[1] >> 2,\n        (lsa_key[1] & 0x03) << 5 | lsa_key[2] >> 3,\n        (lsa_key[2] & 0x07) << 4 | lsa_key[3] >> 4,\n        (lsa_key[3] & 0x0f) << 3 | lsa_key[4] >> 5,\n        (lsa_key[4] & 0x1f) << 2 | lsa_key[5] >> 6,\n        (lsa_key[5] & 0x3f) << 1 | lsa_key[6] >> 7,\n        lsa_key[6] & 0x7f]\n\n    des_key = bytearray([\n        self._ODD_PARITY_TABLE[value << 1] for value in des_key])\n\n    return bytes(des_key)\n\n  def Collect(self, registry):  # pylint: disable=arguments-differ\n    \"\"\"Collects system information.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      bool: True if the system key was found, False if not.\n    \"\"\"\n    credentials_cache_key = registry.GetKeyByPath(\n        self._CREDENTIALS_CACHE_KEY_PATH)\n    if not credentials_cache_key:\n      return False\n\n    boot_key = self._GetBootKey(registry)\n    if not boot_key:\n      return False\n\n    lsa_key = self._GetLSAKey(registry, boot_key)\n    if not lsa_key:\n      return False\n\n    nl_key = self._GetNLKey(registry, lsa_key)\n    if not nl_key:\n      return False\n\n    for value in credentials_cache_key.GetValues():\n      if value.name == 'NL$Control':\n        continue\n\n      rc4_key = pyhmac.md5_calculate_hmac(nl_key, value.data[64:80])\n      decrypted_data = self._DecryptARC4(rc4_key, value.data[96:])\n\n      print(value.name)\n      print(hexdump.Hexdump(value.data))\n      print(hexdump.Hexdump(decrypted_data))\n\n    return True\n"
  },
  {
    "path": "winregrc/catalog.py",
    "content": "\"\"\"Catalog collector.\"\"\"\n\nimport re\n\n\nclass CatalogKeyDescriptor:\n  \"\"\"Catalog key descriptor.\n\n  Attributes:\n    grouped_key_paths (list[str]): paths of Windows Registry keys with similar\n        values.\n    key_path (str): path of Windows Registry key.\n    value_descriptors (tuple[str,str]): pairs of value name and data type.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes a catalog key descriptor.\"\"\"\n    super().__init__()\n    self.grouped_key_paths = []\n    self.key_path = None\n    self.value_descriptors = []\n\n\nclass CatalogCollector:\n  \"\"\"Catalog collector.\"\"\"\n\n  def __init__(self, group_keys=False):\n    \"\"\"Initializes a catalog collector.\n\n    Args:\n      group_keys (bool): group keys with similar values.\n    \"\"\"\n    super().__init__()\n    self._group_keys = group_keys\n\n  def _CollectCatalogKeyDescriptors(self, registry_key):\n    \"\"\"Collects the catalog key descriptors from a Windows Registry key.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n\n    Yields:\n      CatalogKeyDescriptor: catalog key descriptor.\n    \"\"\"\n    key_descriptor = CatalogKeyDescriptor()\n    key_descriptor.key_path = registry_key.path\n\n    for registry_value in registry_key.GetValues():\n      value_descriptor = (\n          registry_value.name or '(default)', registry_value.data_type_string)\n      key_descriptor.value_descriptors.append(value_descriptor)\n\n    yield key_descriptor\n\n    for sub_key in registry_key.GetSubkeys():\n      yield from self._CollectCatalogKeyDescriptors(sub_key)\n\n  def Collect(self, root_key):\n    \"\"\"Collects the catalog descriptors from a Windows Registry file.\n\n    Args:\n      root_key (dfwinreg.WinRegistryKey): root Windows Registry key.\n\n    Yields:\n      CatalogKeyDescriptor: catalog key descriptor.\n    \"\"\"\n    if not self._group_keys:\n      yield from self._CollectCatalogKeyDescriptors(root_key)\n\n    else:\n      def AlphanumericCompare(key):\n        return (int(text) if text.isdigit() else text.lower()\n                for text in re.split('([0-9]+)', key[0]))\n\n      key_descriptors_per_value_hash = {}\n\n      for key_descriptor in self._CollectCatalogKeyDescriptors(root_key):\n        values_hash = hash('\\n'.join([\n            '\\t'.join([value_name, data_type_string])\n            for value_name, data_type_string in sorted(\n                key_descriptor.value_descriptors, key=AlphanumericCompare)]))\n\n        matching_key_descriptor = key_descriptors_per_value_hash.get(\n            values_hash, None)\n        if matching_key_descriptor:\n          matching_key_descriptor.grouped_key_paths.append(\n              key_descriptor.key_path)\n        else:\n          key_descriptors_per_value_hash[values_hash] = key_descriptor\n\n      yield from key_descriptors_per_value_hash.values()\n"
  },
  {
    "path": "winregrc/controlpanel_items.py",
    "content": "\"\"\"Windows control panel items collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass ControlPanelItem:\n  \"\"\"Control panel item.\n\n  Attributes:\n    alternate_module_names (list[str]): alternate module names.\n    identifier (str): identifier.\n    module_name (str): module name.\n  \"\"\"\n\n  def __init__(self, identifier, module_name):\n    \"\"\"Initializes a control panel item.\n\n    Args:\n      identifier (str): identifier.\n      module_name (str): module name.\n    \"\"\"\n    super().__init__()\n    self.alternate_module_names = []\n    self.identifier = identifier\n    self.module_name = module_name\n\n\nclass ControlPanelItemsCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows control panel items collector.\"\"\"\n\n  _CONTROL_PANEL_NAMESPACE_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n      'Explorer\\\\ControlPanel\\\\NameSpace')\n\n  def _CollectControlPanelItems(self, control_panel_namespace_key):\n    \"\"\"Collects Windows control panel items.\n\n    Args:\n      control_panel_namespace_key (dfwinreg.WinRegistryKey): control panel\n          namespace Windows Registry key.\n\n    Yields:\n      ControlPanelItem: a control panel item.\n    \"\"\"\n    for subkey in control_panel_namespace_key.GetSubkeys():\n      if subkey.name[0] == '{' and subkey.name[-1] == '}':\n        identifier = subkey.name.lower()\n        module_name = self._GetValueFromKey(subkey, '')\n        yield ControlPanelItem(identifier, module_name)\n\n  def Collect(self, registry):\n    \"\"\"Collects Windows control panel items.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Yields:\n      ControlPanelItem: a control panel item.\n    \"\"\"\n    control_panel_namespace_key = registry.GetKeyByPath(\n        self._CONTROL_PANEL_NAMESPACE_KEY_PATH)\n    if control_panel_namespace_key:\n      yield from self._CollectControlPanelItems(control_panel_namespace_key)\n"
  },
  {
    "path": "winregrc/data/observed_shellfolders.yaml",
    "content": "# winreg-kb shellfolder definitions observed.\n---\nidentifier: \"{00020d75-0000-0000-c000-000000000046}\"\nname: \"Inbox\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{00020d76-0000-0000-c000-000000000046}\"\nname: \"Inbox\"\nwindows_versions: [\"Windows NT4\"]\n---\nidentifier: \"{00c6d95f-329c-409a-81d7-c46c66ea7f33}\"\nname: \"Default Location\"\nwindows_versions: [\"Windows 7\"]\n---\nidentifier: \"{0142e4d0-fb7a-11dc-ba4a-000ffe7ab428}\"\nname: \"Biometric Devices (Biometrics)\"\nwindows_versions: [\"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{025a5937-a6be-4686-a844-36fe4bec8b6d}\"\nname: \"Power Options\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{031e4825-7b94-4dc3-b131-e946b44c8dd5}\"\nname: \"Users Libraries\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{04731b67-d933-450a-90e6-4acd2e9408fe}\"\nclass_name: CLSID_SearchFolder\nname: \"Search Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9}\"\nname: \"Taskbar (Notification Area Icons)\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{0875dcb6-c686-4243-9432-adccf0b9f2d7}\"\nname: \"Microsoft !OneNote Namespace Extension for Windows Desktop Search\"\nwindows_versions: [\"Windows 7\"]\n---\nidentifier: \"{0afaced1-e828-11d1-9187-b532f1e9575d}\"\nname: \"Folder Shortcut\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{0bd8e793-d371-11d1-b0b5-0060972919d7}\"\nname: \"!SolidWorks Enterprise PDM\"\nwindows_versions: [\"Windows 7\"]\n---\nidentifier: \"{0c39a5cf-1a7a-40c8-ba74-8900e6df5fcd}\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{0cd7a5c0-9f37-11ce-ae65-08002b2e1262}\"\nname: \"Cabinet File\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{0df44eaa-ff21-4412-828e-260a8728e7f1}\"\nname: \"Taskbar and Start Menu\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{11016101-e366-4d22-bc06-4ada335c892b}\"\nname: \"Internet Explorer History and Feeds Shell Data Source for Windows Search\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{1206f5f1-0569-412c-8fec-3204630dfb70}\"\nname: \"Credential Manager\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{13e7f612-f261-4391-bea2-39df4f3fa311}\"\nname: \"Windows Desktop Search\"\nwindows_versions: [\"Windows XP 32-bit\"]\n---\nidentifier: \"{15eae92e-f17a-4431-9f28-805e482dafd4}\"\nname: \"Install New Programs (Get Programs)\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{1723d66a-7a12-443e-88c7-05e1bfe79983}\"\nname: \"Previous Versions Delegate Folder\"\nwindows_versions: [\"Windows Vista\"]\n---\nidentifier: \"{17cd9488-1228-4b2f-88ce-4298e93e0966}\"\nname: \"Default Programs (Set User Defaults)\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{1a9ba3a0-143a-11cf-8350-444553540000}\"\nname: \"Shell Favorite Folder\"\nwindows_versions: [\"Windows 2000\"]\n---\nidentifier: \"{1d2680c9-0e2a-469d-b787-065558bc7d43}\"\nname: \"Fusion Cache\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\"]\n---\nidentifier: \"{1f3427c8-5c10-4210-aa03-2ee45287d668}\"\nname: \"User Pinned\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{1f43a58c-ea28-43e6-9ec4-34574a16ebb7}\"\nname: \"Windows Desktop Search MAPI Namespace Extension Class\"\nwindows_versions: [\"Windows XP 32-bit\"]\n---\nidentifier: \"{1f4de370-d627-11d1-ba4f-00a0c91eedba}\"\nname: \"Search Results - Computers (Computer Search Results Folder, Network Computers)\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\"]\n---\nidentifier: \"{1fa9085f-25a2-489b-85d4-86326eedcd87}\"\nname: \"Manage Wireless Networks\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{208d2c60-3aea-1069-a2d7-08002b30309d}\"\nname: \"My Network Places (Network)\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{20d04fe0-3aea-1069-a2d8-08002b30309d}\"\nname: \"My Computer (Computer)\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{21ec2020-3aea-1069-a2dd-08002b30309d}\"\nname: \"Control Panel\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{2227a280-3aea-1069-a2de-08002b30309d}\"\nname: \"Printers and Faxes (Printers)\"\nwindows_versions: [\"Windows NT4\", \"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\n# Found in !RecentPlaces.lnk\nidentifier: \"{22877a6d-37a1-461a-91b0-dbda5aaebc99}\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{241d7c96-f8bf-4f85-b01f-e2b043341a4b}\"\nname: \"Workspaces Center (Remote Application and Desktop Connections)\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{2559a1f0-21d7-11d4-bdaf-00c04f60b9f0}\"\nname: \"Search\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{2559a1f1-21d7-11d4-bdaf-00c04f60b9f0}\"\nname: \"Help and Support\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{2559a1f2-21d7-11d4-bdaf-00c04f60b9f0}\"\nname: \"Windows Security\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{2559a1f3-21d7-11d4-bdaf-00c04f60b9f0}\"\nname: \"Run...\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{2559a1f4-21d7-11d4-bdaf-00c04f60b9f0}\"\nname: \"Internet\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\"]\n---\nidentifier: \"{2559a1f5-21d7-11d4-bdaf-00c04f60b9f0}\"\nname: \"E-mail\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{2559a1f6-21d7-11d4-bdaf-00c04f60b9f0}\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\"]\n---\nidentifier: \"{2559a1f7-21d7-11d4-bdaf-00c04f60b9f0}\"\nname: \"Set Program Access and Defaults\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{267cf8a9-f4e3-41e6-95b1-af881be130ff}\"\nname: \"Location Folder\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{26ee0668-a00a-44d7-9371-beb064c98683}\"\nname: \"Control Panel\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{2728520d-1ec8-4c68-a551-316b684c4ea7}\"\nname: \"Network Setup Wizard\"\nwindows_versions: [\"Windows XP 32-bit\"]\n---\nidentifier: \"{28803f59-3a75-4058-995f-4ee5503b023c}\"\nname: \"Bluetooth Devices\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{289978ac-a101-4341-a817-21eba7fd046d}\"\nname: \"Sync Center Conflict Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{289af617-1cc3-42a6-926c-e6a863f0e3ba}\"\nname: \"DLNA Media Servers Data Source\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{2965e715-eb66-4719-b53f-1672673bbefa}\"\nname: \"Results Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{2e9e59c0-b437-4981-a647-9c34b9b90891}\"\nname: \"Sync Setup Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{2f6ce85c-f9ee-43ca-90c7-8a9bd53a2467}\"\nname: \"File History Data Source\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{3080f90d-d7ad-11d9-bd98-0000947b0257}\"\nname: \"Show Desktop\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{3080f90e-d7ad-11d9-bd98-0000947b0257}\"\nname: \"Window Switcher\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{323ca680-c24d-4099-b94d-446dd2d7249e}\"\nname: \"Common Places\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{328b0346-7eaf-4bbe-a479-7cb88a095f5b}\"\nname: \"Layout Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{335a31dd-f04b-4d76-a925-d6b47cf360df}\"\nname: \"Backup and Restore Center\"\nwindows_versions: [\"Windows Vista\"]\n---\nidentifier: \"{35786d3c-b075-49b9-88dd-029876e11c01}\"\nname: \"Portable Devices\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{36eef7db-88ad-4e81-ad49-0e313f0c35f8}\"\nname: \"Windows Update\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{38a98528-6cbf-4ca9-8dc0-b1e1d10f7b1b}\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{3c5c43a3-9ce9-4a9b-9699-2ac0cf6cc4bf}\"\nname: \"Configure Wireless Network\"\nwindows_versions: [\"Windows XP 32-bit\"]\n---\nidentifier: \"{3f6bc534-dfa1-4ab4-ae54-ef25a74e0107}\"\nname: \"System Restore\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{4026492f-2f69-46b8-b9bf-5654fc07e423}\"\nname: \"Windows Firewall\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{418c8b64-5463-461d-88e0-75e2afa3c6fa}\"\nname: \"Explorer Browser Results Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{4234d49b-0245-4df3-b780-3893943456e1}\"\nname: \"Applications\"\nwindows_versions: [\"Windows 8.0\"]\n---\n# Found in Sample Music.lnk and Sample Pictures.lnk\nidentifier: \"{4336a54d-038b-4685-ab02-99bb52d3fb8b}\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{437ff9c0-a07f-4fa0-af80-84b6c6440a16}\"\nname: \"Command Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{450d8fba-ad25-11d0-98a8-0800361b1103}\"\nname: \"My Documents\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{48e7caab-b918-4e58-a94d-505519c795dc}\"\nname: \"Start Menu Folder\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{5399e694-6ce5-4d6c-8fce-1d8870fdcba0}\"\nname: \"Control Panel command object for Start menu and desktop\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\n# Found in File Explorer.lnk\nidentifier: \"{52205fd8-5dfb-447d-801a-d0b52f2e83e1}\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{58e3c745-d971-4081-9034-86e34b30836a}\"\nname: \"Speech Recognition Options\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{59031a47-3f72-44a7-89c5-5595fe6b30ee}\"\nname: \"Shared Documents Folder (Users Files)\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{5ea4f148-308c-46d7-98a9-49041b1dd468}\"\nname: \"Mobility Center Control Panel\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{60632754-c523-4b62-b45c-4172da012619}\"\nname: \"User Accounts\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{63da6ec0-2e98-11cf-8d82-444553540000}\"\nname: \"Microsoft FTP Folder\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{640167b4-59b0-47a6-b335-a6b3c0695aea}\"\nname: \"Portable Media Devices\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\"]\n---\nidentifier: \"{645ff040-5081-101b-9f08-00aa002f954e}\"\nname: \"Recycle Bin\"\nwindows_versions: [\"Windows NT4\", \"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{64693913-1c21-4f30-a98f-4e52906d3b56}\"\nclass_name: CLSID_AppInstanceFolder\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{67718415-c450-4f3c-bf8a-b487642dc39b}\"\nname: \"Windows Features\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{6785bfac-9d2d-4be5-b7e2-59937e8fb80a}\"\nname: \"Other Users Folder\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{679f85cb-0220-4080-b29b-5540cc05aab6}\"\nname: Quick access\nwindows_versions: [10]\n---\nidentifier: \"{67ca7650-96e6-4fdd-bb43-a8e774f73a57}\"\nname: \"Home Group Control Panel (Home Group)\"\nwindows_versions: [\"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{692f0339-cbaa-47e6-b5b5-3b84db604e87}\"\nname: \"Extensions Manager Folder\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\"]\n---\nidentifier: \"{6dfd7c5c-2451-11d3-a299-00c04f8ef6af}\"\nname: \"Folder Options\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\"]\n---\nidentifier: \"{7007acc7-3202-11d1-aad2-00805fc1270e}\"\nname: \"Network Connections (Network and Dial-up Connections)\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\"]\n---\nidentifier: \"{708e1662-b832-42a8-bbe1-0a77121e3908}\"\nname: \"Tree property value folder\"\nwindows_versions: [\"Windows Vista\"]\n---\nidentifier: \"{71d99464-3b6b-475c-b241-e15883207529}\"\nname: \"Sync Results Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{72b36e70-8700-42d6-a7f7-c9ab3323ee51}\"\nname: \"Search Connector Folder\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{78f3955e-3b90-4184-bd14-5397c15f1efc}\"\nname: \"Performance Information and Tools\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{7a9d77bd-5403-11d2-8785-2e0420524153}\"\nname: \"User Accounts (Users and Passwords)\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{7b81be6a-ce2b-4676-a29e-eb907a5126c5}\"\nname: \"Programs and Features\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{7bd29e00-76c1-11cf-9dd0-00a0c9034933}\"\nname: \"Temporary Internet Files\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{7bd29e01-76c1-11cf-9dd0-00a0c9034933}\"\nname: \"Temporary Internet Files\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{7be9d83c-a729-4d97-b5a7-1b7313c39e0a}\"\nname: \"Programs Folder\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{8060b2e3-c9d7-4a5d-8c6b-ce8eba111328}\"\nname: \"Proximity CPL\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{8343457c-8703-410f-ba8b-8b026e431743}\"\nname: \"Feedback Tool\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{85bbd920-42a0-1069-a2e4-08002b30309d}\"\nname: \"Briefcase\"\nwindows_versions: [\"Windows NT4\", \"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{863aa9fd-42df-457b-8e4d-0de1b8015c60}\"\nname: \"Remote Printers\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{865e5e76-ad83-4dca-a109-50dc2113ce9a}\"\nname: \"Programs Folder and Fast Items\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{871c5380-42a0-1069-a2ea-08002b30309d}\"\nname: \"Internet Explorer (Homepage)\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{87630419-6216-4ff8-a1f0-143562d16d5c}\"\nname: \"Mobile Broadband Profile Settings Editor\"\nwindows_versions: [\"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{877ca5ac-cb41-4842-9c69-9136e42d47e2}\"\nname: \"File Backup Index\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{88c6c381-2e85-11d0-94de-444553540000}\"\nname: \"ActiveX Cache Folder\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{896664f7-12e1-490f-8782-c0835afd98fc}\"\nname: \"Libraries delegate folder that appears in Users Files Folder\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{89d83576-6bd1-4c86-9454-beb04e94c819}\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{8e908fc9-becc-40f6-915b-f4ca0e70d03d}\"\nname: \"Network and Sharing Center\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{8fd8b88d-30e1-4f25-ac2b-553d3d65f0ea}\"\nname: \"DXP\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{9113a02d-00a3-46b9-bc5f-9c04daddd5d7}\"\nname: \"Enhanced Storage Data Source\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{93412589-74d4-4e4e-ad0e-e0cb621440fd}\"\nname: \"Font Settings\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{9343812e-1c37-4a49-a12e-4b2d810d956b}\"\nname: \"Search Home\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{96437431-5a90-4658-a77c-25478734f03e}\"\nname: \"Server Manager\"\nwindows_versions: [\"Windows 2008\"]\n---\nidentifier: \"{96ae8d84-a250-4520-95a5-a47a7e3c548b}\"\nname: \"Parental Controls\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{98d99750-0b8a-4c59-9151-589053683d73}\"\nname: \"Windows Search Service Media Center Namespace Extension Handler\"\nwindows_versions: [\"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{98f275b4-4fff-11e0-89e2-7b86dfd72085}\"\nclass_name: CLSID_StartMenuLauncherProviderFolder\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{992cffa0-f557-101a-88ec-00dd010ccc48}\"\nname: \"Network Connections (Network and Dial-up Connections)\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{9a096bb5-9dc3-4d1c-8526-c3cbf991ea4e}\"\nname: \"Internet Explorer RSS Feeds Folder\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{9c60de1e-e5fc-40f4-a487-460851a8d915}\"\nname: \"AutoPlay\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{9c73f5e5-7ae7-4e32-a8e8-8d23b85255bf}\"\nname: \"Sync Center Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{9db7a13c-f208-4981-8353-73cc61ae2783}\"\nname: \"Previous Versions\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{9f433b7c-5f96-4ce1-ac28-aeaa1cc04d7c}\"\nname: \"Security Center\"\nwindows_versions: [\"Windows Vista\"]\n---\nidentifier: \"{9fe63afd-59cf-4419-9775-abcc3849f861}\"\nname: \"System Recovery (Recovery)\"\nwindows_versions: [\"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{a00ee528-ebd9-48b8-944a-8942113d46ac}\"\nclass_name: CLSID_StartMenuCommandingProviderFolder\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{a3c3d402-e56c-4033-95f7-4885e80b0111}\"\nname: \"Previous Versions Results Delegate Folder\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{a5a3563a-5755-4a6f-854e-afa3230b199f}\"\nname: \"Library Folder\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{a5e46e3a-8849-11d1-9d8c-00c04fc99d61}\"\nname: \"Microsoft Browser Architecture\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\"]\n---\nidentifier: \"{a6482830-08eb-41e2-84c1-73920c2badb9}\"\nname: \"Removable Storage Devices\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{a8a91a66-3a7d-4424-8d24-04e180695c7a}\"\nname: \"Device Center (Devices and Printers)\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{aee2420f-d50e-405c-8784-363c582bf45a}\"\nname: \"Device Pairing Folder\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{afdb1f70-2a4c-11d2-9039-00c04f8eeb3e}\"\nname: \"Offline Files Folder\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows 8.0\"]\n---\nidentifier: \"{b155bdf8-02f0-451e-9a26-ae317cfd7779}\"\nname: \"Nethood delegate folder (Delegate folder that appears in Computer)\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{b2952b16-0e07-4e5a-b993-58c52cb94cae}\"\nname: \"DB Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{b4fb3f98-c1ea-428d-a78a-d1f5659cba93}\"\nname: \"Other Users Folder\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{b98a2bea-7d42-4558-8bd1-832f41bac6fd}\"\nname: \"Backup And Restore (Backup and Restore Center)\"\nwindows_versions: [\"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{bb06c0e4-d293-4f75-8a90-cb05b6477eee}\"\nname: \"System\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{bb64f8a7-bee7-4e1a-ab8d-7d8273f7fdb6}\"\nname: \"Action Center Control Panel\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{bc476f4c-d9d7-4100-8d4e-e043f6dec409}\"\nname: \"Microsoft Browser Architecture\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows Vista\"]\n---\nidentifier: \"{bc48b32f-5910-47f5-8570-5074a8a5636a}\"\nname: \"Sync Results Delegate Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{bd7a2e7b-21cb-41b2-a086-b309680c6b7e}\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{bd84b380-8ca2-1069-ab1d-08000948f534}\"\nname: \"Microsoft Windows Font Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{bdeadf00-c265-11d0-bced-00a0c90ab50f}\"\nname: \"Web Folders\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\"]\n---\nidentifier: \"{be122a0e-4503-11da-8bde-f66bad1e3f3a}\"\nname: \"Windows Anytime Upgrade\"\nwindows_versions: [\"Windows Vista\"]\n---\nidentifier: \"{bf782cc9-5a52-4a17-806c-2a894ffeeac5}\"\nname: \"Language Settings\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{c291a080-b400-4e34-ae3f-3d2b9637d56c}\"\nname: \"UNCFATShellFolder Class\"\nwindows_versions: [\"Windows XP 32-bit\"]\n---\nidentifier: \"{c2b136e2-d50e-405c-8784-363c582bf43e}\"\nname: \"Device Center Initialization\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{c555438b-3c23-4769-a71f-b6d3d9b6053a}\"\nname: \"Display\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{c57a6066-66a3-4d91-9eb9-41532179f0a5}\"\nname: \"Application Suggested Locations\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{c58c4893-3be0-4b45-abb5-a63e4b8c8651}\"\nname: \"Troubleshooting\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{cb1b7f8c-c50a-4176-b604-9e24dee8d4d1}\"\nname: \"Welcome Center (Getting Started)\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\"]\n---\nidentifier: \"{d2035edf-75cb-4ef1-95a7-410d9ee17170}\"\nname: \"DLNA Content Directory Data Source\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{d20ea4e1-3957-11d2-a40b-0c5020524152}\"\nname: \"Fonts\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\"]\n---\nidentifier: \"{d20ea4e1-3957-11d2-a40b-0c5020524153}\"\nname: \"Administrative Tools\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{d34a6ca6-62c2-4c34-8a7c-14709c1ad938}\"\nname: \"Common Places FS Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{d426cfd0-87fc-4906-98d9-a23f5d515d61}\"\nname: \"Windows Search Service Outlook Express Protocol Handler\"\nwindows_versions: [\"Windows XP 32-bit\"]\n---\nidentifier: \"{d4480a50-ba28-11d1-8e75-00c04fa31a86}\"\nname: \"Add Network Place\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{d450a8a1-9568-45c7-9c0e-b4f9fb4537bd}\"\nname: \"Installed Updates\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{d555645e-d4f8-4c29-a827-d93c859c4f2a}\"\nname: \"Ease of Access (Ease of Access Center)\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{d5b1944e-db4e-482e-b3f1-db05827f0978}\"\nname: \"Softex OmniPass Encrypted Folder\"\nwindows_versions: [\"Windows XP 32-bit\"]\n---\nidentifier: \"{d6277990-4c6a-11cf-8d87-00aa0060f5bf}\"\nname: \"Scheduled Tasks\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\"]\n---\nidentifier: \"{d8559eb9-20c0-410e-beda-7ed416aecc2a}\"\nname: \"Windows Defender\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{d9ef8727-cac2-4e60-809e-86f80a666c91}\"\nname: \"Secure Startup (BitLocker Drive Encryption)\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{daf95313-e44d-46af-be1b-cbacea2c3065}\"\nclass_name: CLSID_StartMenuProviderFolder\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{dffacdc5-679f-4156-8947-c5c76bc0b67f}\"\nname: \"Delegate folder that appears in Users Files Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{e17d4fc0-5564-11d1-83f2-00a0c90dc849}\"\nname: \"Search Results Folder\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\"]\n---\nidentifier: \"{e211b736-43fd-11d1-9efb-0000f8757fcd}\"\nname: \"Scanners and Cameras\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\"]\n---\nidentifier: \"{e345f35f-9397-435c-8f95-4e922c26259e}\"\nclass_name: CLSID_StartMenuPathCompleteProviderFolder\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{e413d040-6788-4c22-957e-175d1c513a34}\"\nname: \"Sync Center Conflict Delegate Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{e773f1af-3a65-4866-857d-846fc9c4598a}\"\nname: \"Shell Storage Folder Viewer\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\"]\n---\nidentifier: \"{e7de9b1a-7533-4556-9484-b26fb486475e}\"\nname: \"Network Map\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\"]\n---\nidentifier: \"{e7e4bc40-e76a-11ce-a9bb-00aa004ae837}\"\nname: \"Shell DocObject Viewer\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{e88dcce0-b7b3-11d1-a9f0-00aa0060fa31}\"\nname: \"Compressed Folder\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{e95a4861-d57a-4be1-ad0f-35267e261739}\"\nname: \"Windows SideShow\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{e9950154-c418-419e-a90a-20c5287ae24b}\"\nname: \"Sensors (Location and Other Sensors)\"\nwindows_versions: [\"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{ed228fdf-9ea8-4870-83b1-96b02cfe0d52}\"\nname: \"My Games (Games Explorer)\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{ed50fc29-b964-48a9-afb3-15ebb9b97f36}\"\nname: \"PrintHood delegate folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{ed7ba470-8e54-465e-825c-99712043e01c}\"\nname: \"All Tasks\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{ed834ed6-4b5a-4bfe-8f11-a626dcb6a921}\"\nname: \"Personalization Control Panel\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{edc978d6-4d53-4b2f-a265-5805674be568}\"\nname: \"Stream Backed Folder\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{f02c1a0d-be21-4350-88b0-7367fc96ef3c}\"\nname: \"Computers and Devices\"\nwindows_versions: [\"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{f1390a9a-a3f4-4e5d-9c5f-98f3bd8d935c}\"\nname: \"Sync Setup Delegate Folder\"\nwindows_versions: [\"Windows Vista\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{f3f5824c-ad58-4728-af59-a1ebe3392799}\"\nname: \"Sticky Notes Namespace Extension for Windows Desktop Search\"\nwindows_versions: [\"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{f5175861-2688-11d0-9c5e-00aa00a45957}\"\nname: \"Subscription Folder\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{f6b6e965-e9b2-444b-9286-10c9152edbc5}\"\nname: \"History Vault\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{f8c2ab3b-17bc-41da-9758-339d7dbf2d88}\"\nname: \"Previous Versions Results Folder\"\nwindows_versions: [\"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n---\nidentifier: \"{f90c627b-7280-45db-bc26-cce7bdd620a4}\"\nname: \"All Tasks\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{f942c606-0914-47ab-be56-1321b8035096}\"\nname: \"Storage Spaces\"\nwindows_versions: [\"Windows 8.0\"]\n---\nidentifier: \"{fb0c9c8a-6c50-11d1-9f1d-0000f8757fcd}\"\nname: \"Scanners & Cameras\"\nwindows_versions: [\"Windows XP 32-bit\", \"Windows 2003\"]\n---\nidentifier: \"{fbf23b42-e3f0-101b-8488-00aa003e56f8}\"\nname: \"Internet Explorer\"\nwindows_versions: [\"Windows NT4\", \"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\"]\n---\nidentifier: \"{fe1290f0-cfbd-11cf-a330-00aa00c16e65}\"\nname: \"Directory\"\nwindows_versions: [\"Windows 2000\"]\n---\nidentifier: \"{ff393560-c2a7-11cf-bff4-444553540000}\"\nname: \"History\"\nwindows_versions: [\"Windows 2000\", \"Windows XP 32-bit\", \"Windows 2003\", \"Windows Vista\", \"Windows 2008\", \"Windows 7\", \"Windows 8.0\"]\n"
  },
  {
    "path": "winregrc/data_format.py",
    "content": "\"\"\"Binary data format.\"\"\"\n\nimport os\n\nfrom dfdatetime import filetime as dfdatetime_filetime\n\nfrom dtfabric import errors as dtfabric_errors\nfrom dtfabric.runtime import fabric as dtfabric_fabric\n\nfrom winregrc import errors\n\n\nclass BinaryDataFormat:\n  \"\"\"Binary data format.\"\"\"\n\n  # The dtFabric definition file, which must be overwritten by a subclass.\n  _DEFINITION_FILE = None\n\n  # Preserve the absolute path value of __file__ in case it is changed\n  # at run-time.\n  _DEFINITION_FILES_PATH = os.path.dirname(__file__)\n\n  _HEXDUMP_CHARACTER_MAP = [\n      '.' if byte < 0x20 or byte > 0x7e else chr(byte) for byte in range(256)]\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a binary data format.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be written.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__()\n    self._data_type_maps = {}\n    self._debug = debug\n    self._fabric = self._ReadDefinitionFile(self._DEFINITION_FILE)\n    self._output_writer = output_writer\n\n  def _DebugPrintData(self, description, data):\n    \"\"\"Prints data for debugging.\n\n    Args:\n      description (str): description.\n      data (bytes): data.\n    \"\"\"\n    if self._output_writer:\n      self._output_writer.WriteText(f'{description:s}:\\n')\n\n      value_string = self._FormatDataInHexadecimal(data)\n      self._output_writer.WriteText(value_string)\n\n  def _DebugPrintDecimalValue(self, description, value):\n    \"\"\"Prints a decimal value for debugging.\n\n    Args:\n      description (str): description.\n      value (int): value.\n    \"\"\"\n    self._DebugPrintValue(description, f'{value:d}')\n\n  def _DebugPrintFiletimeValue(self, description, value):\n    \"\"\"Prints a FILETIME timestamp value for debugging.\n\n    Args:\n      description (str): description.\n      value (object): value.\n    \"\"\"\n    if value == 0:\n      date_time_string = 'Not set (0)'\n    elif value == 0x7fffffffffffffff:\n      date_time_string = 'Never (0x7fffffffffffffff)'\n    else:\n      date_time = dfdatetime_filetime.Filetime(timestamp=value)\n      date_time_string = date_time.CopyToDateTimeString()\n      if date_time_string:\n        date_time_string = f'{date_time_string:s} UTC'\n      else:\n        date_time_string = f'0x{value:08x}'\n\n    self._DebugPrintValue(description, date_time_string)\n\n  def _DebugPrintStructureObject(self, structure_object, debug_info):\n    \"\"\"Prints structure object debug information.\n\n    Args:\n      structure_object (object): structure object.\n      debug_info (list[tuple[str, str, int]]): debug information.\n    \"\"\"\n    text = self._FormatStructureObject(structure_object, debug_info)\n    self._output_writer.WriteText(text)\n\n  def _DebugPrintText(self, text):\n    \"\"\"Prints text for debugging.\n\n    Args:\n      text (str): text.\n    \"\"\"\n    if self._output_writer:\n      self._output_writer.DebugPrintText(text)\n\n  def _DebugPrintValue(self, description, value):\n    \"\"\"Prints a value for debugging.\n\n    Args:\n      description (str): description.\n      value (object): value.\n    \"\"\"\n    if self._output_writer:\n      text = self._FormatValue(description, value)\n      self._output_writer.WriteText(text)\n\n  def _FormatDataInHexadecimal(self, data):\n    \"\"\"Formats data in a hexadecimal representation.\n\n    Args:\n      data (bytes): data.\n\n    Returns:\n      str: hexadecimal representation of the data.\n    \"\"\"\n    in_group = False\n    previous_hexadecimal_string = None\n\n    lines = []\n    data_size = len(data)\n    for block_index in range(0, data_size, 16):\n      data_string = data[block_index:block_index + 16]\n\n      hexadecimal_byte_values = []\n      printable_values = []\n      for byte_value in data_string:\n        if isinstance(byte_value, str):\n          byte_value = ord(byte_value)\n\n        hexadecimal_byte_values.append(f'{byte_value:02x}')\n\n        printable_value = self._HEXDUMP_CHARACTER_MAP[byte_value]\n        printable_values.append(printable_value)\n\n      remaining_size = 16 - len(data_string)\n      if remaining_size == 0:\n        whitespace = ''\n      elif remaining_size >= 8:\n        whitespace = ' ' * ((3 * remaining_size) - 1)\n      else:\n        whitespace = ' ' * (3 * remaining_size)\n\n      hexadecimal_string_part1 = ' '.join(hexadecimal_byte_values[0:8])\n      hexadecimal_string_part2 = ' '.join(hexadecimal_byte_values[8:16])\n      hexadecimal_string = (\n          f'{hexadecimal_string_part1:s}  {hexadecimal_string_part2:s}'\n          f'{whitespace:s}')\n\n      if (previous_hexadecimal_string is not None and\n          previous_hexadecimal_string == hexadecimal_string and\n          block_index + 16 < data_size):\n\n        if not in_group:\n          in_group = True\n\n          lines.append('...')\n\n      else:\n        printable_string = ''.join(printable_values)\n\n        lines.append(\n            f'0x{block_index:08x}  {hexadecimal_string:s}  '\n            f'{printable_string:s}')\n\n        in_group = False\n        previous_hexadecimal_string = hexadecimal_string\n\n    lines.extend(['', ''])\n    return '\\n'.join(lines)\n\n  def _FormatIntegerAsDecimal(self, integer):\n    \"\"\"Formats an integer as a decimal.\n\n    Args:\n      integer (int): integer.\n\n    Returns:\n      str: integer formatted as a decimal.\n    \"\"\"\n    return f'{integer:d}'\n\n  def _FormatIntegerAsFiletime(self, integer):\n    \"\"\"Formats an integer as a FILETIME date and time value.\n\n    Args:\n      integer (int): integer.\n\n    Returns:\n      str: integer formatted as a FILETIME date and time value.\n    \"\"\"\n    if integer == 0:\n      return 'Not set (0)'\n\n    if integer == 0x7fffffffffffffff:\n      return 'Never (0x7fffffffffffffff)'\n\n    date_time = dfdatetime_filetime.Filetime(timestamp=integer)\n    date_time_string = date_time.CopyToDateTimeString()\n    if not date_time_string:\n      return f'0x{integer:08x}'\n\n    return f'{date_time_string:s} UTC'\n\n  def _FormatIntegerAsHexadecimal2(self, integer):\n    \"\"\"Formats an integer as an 2-digit hexadecimal.\n\n    Args:\n      integer (int): integer.\n\n    Returns:\n      str: integer formatted as an 2-digit hexadecimal.\n    \"\"\"\n    return f'0x{integer:02x}'\n\n  def _FormatIntegerAsHexadecimal4(self, integer):\n    \"\"\"Formats an integer as an 4-digit hexadecimal.\n\n    Args:\n      integer (int): integer.\n\n    Returns:\n      str: integer formatted as an 4-digit hexadecimal.\n    \"\"\"\n    return f'0x{integer:04x}'\n\n  def _FormatIntegerAsHexadecimal8(self, integer):\n    \"\"\"Formats an integer as an 8-digit hexadecimal.\n\n    Args:\n      integer (int): integer.\n\n    Returns:\n      str: integer formatted as an 8-digit hexadecimal.\n    \"\"\"\n    return f'0x{integer:08x}'\n\n  def _FormatStructureObject(self, structure_object, debug_info):\n    \"\"\"Formats a structure object debug information.\n\n    Args:\n      structure_object (object): structure object.\n      debug_info (list[tuple[str, str, int]]): debug information.\n\n    Returns:\n      str: structure object debug information.\n    \"\"\"\n    lines = []\n\n    attribute_value = ''\n    for attribute_name, description, value_format_callback in debug_info:\n      attribute_value = getattr(structure_object, attribute_name, None)\n      if attribute_value is None:\n        continue\n\n      value_format_function = None\n      if value_format_callback:\n        value_format_function = getattr(self, value_format_callback, None)\n      if value_format_function:\n        attribute_value = value_format_function(attribute_value)\n\n      if isinstance(attribute_value, str) and '\\n' in attribute_value:\n        text = ''\n        if description is not None:\n          text = f'{description:s}:\\n'\n        text = ''.join([text, attribute_value])\n\n      else:\n        text = self._FormatValue(description, attribute_value)\n\n      lines.append(text)\n\n    if not attribute_value or attribute_value[:-2] != '\\n\\n':\n      lines.append('\\n')\n\n    return ''.join(lines)\n\n  def _FormatValue(self, description, value):\n    \"\"\"Formats a value for debugging.\n\n    Args:\n      description (str): description.\n      value (object): value.\n\n    Returns:\n      str: formatted value.\n    \"\"\"\n    alignment, _ = divmod(len(description), 8)\n    alignment_string = '\\t' * (8 - alignment + 1)\n    return f'{description:s}{alignment_string:s}: {value!s}\\n'\n\n  def _GetDataTypeMap(self, name):\n    \"\"\"Retrieves a data type map defined by the definition file.\n\n    The data type maps are cached for reuse.\n\n    Args:\n      name (str): name of the data type as defined by the definition file.\n\n    Returns:\n      dtfabric.DataTypeMap: data type map which contains a data type definition,\n          such as a structure, that can be mapped onto binary data.\n    \"\"\"\n    data_type_map = self._data_type_maps.get(name)\n    if not data_type_map:\n      data_type_map = self._fabric.CreateDataTypeMap(name)\n      self._data_type_maps[name] = data_type_map\n\n    return data_type_map\n\n  def _ReadDefinitionFile(self, filename):\n    \"\"\"Reads a dtFabric definition file.\n\n    Args:\n      filename (str): name of the dtFabric definition file.\n\n    Returns:\n      dtfabric.DataTypeFabric: data type fabric which contains the data format\n          data type maps of the data type definition, such as a structure, that\n          can be mapped onto binary data or None if no filename is provided.\n    \"\"\"\n    if not filename:\n      return None\n\n    path = os.path.join(self._DEFINITION_FILES_PATH, filename)\n    with open(path, 'rb') as file_object:\n      definition = file_object.read()\n\n    return dtfabric_fabric.DataTypeFabric(yaml_definition=definition)\n\n  def _ReadStructureFromByteStream(\n      self, byte_stream, file_offset, data_type_map, description, context=None):\n    \"\"\"Reads a structure from a byte stream.\n\n    Args:\n      byte_stream (bytes): byte stream.\n      file_offset (int): offset of the structure data relative to the start\n          of the file-like object.\n      data_type_map (dtfabric.DataTypeMap): data type map of the structure.\n      description (str): description of the structure.\n      context (Optional[dtfabric.DataTypeMapContext]): data type map context.\n\n    Returns:\n      object: structure values object.\n\n    Raises:\n      ParseError: if the structure cannot be read.\n      ValueError: if file-like object or data type map is missing.\n    \"\"\"\n    if not byte_stream:\n      raise ValueError('Missing byte stream.')\n\n    if not data_type_map:\n      raise ValueError('Missing data type map.')\n\n    try:\n      return data_type_map.MapByteStream(byte_stream, context=context)\n    except (dtfabric_errors.ByteStreamTooSmallError,\n            dtfabric_errors.MappingError) as exception:\n      raise errors.ParseError((\n          f'Unable to map {description:s} data at offset: 0x{file_offset:08x} '\n          f'with error: {exception!s}'))\n"
  },
  {
    "path": "winregrc/delegatefolders.py",
    "content": "\"\"\"Windows delegate folders collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass DelegateFolder:\n  \"\"\"Delegate folder.\n\n  Attributes:\n    identifier (str): identifier.\n    name (str): name.\n    namespace (str): namespace.\n  \"\"\"\n\n  def __init__(self, identifier, name, namespace):\n    \"\"\"Initializes a delegate folder.\n\n    Args:\n      identifier (str): identifier.\n      name (str): name.\n      namespace (str): namespace.\n    \"\"\"\n    super().__init__()\n    self.identifier = identifier\n    self.name = name\n    self.namespace = namespace\n\n\nclass DelegateFoldersCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows delegate folders collector.\"\"\"\n\n  _EXPLORER_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n      'Explorer')\n\n  def _CollectDelegateFolders(self, delegate_folders_key, namespace):\n    \"\"\"Collects Windows delegate folders.\n\n    Args:\n      delegate_folders_key (dfwinreg.WinRegistryKey): delegate folders Windows\n          Registry key.\n      namespace (str): namespace.\n\n    Yields:\n      DelegateFolder: a delegate folder.\n    \"\"\"\n    for subkey in delegate_folders_key.GetSubkeys():\n      name = self._GetValueFromKey(subkey, '')\n      yield DelegateFolder(subkey.name, name, namespace)\n\n  def Collect(self, registry):\n    \"\"\"Collects Windows delegate folders.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Yields:\n      DelegateFolder: a delegate folder.\n    \"\"\"\n    explorer_key = registry.GetKeyByPath(self._EXPLORER_KEY_PATH)\n    if explorer_key:\n      for subkey in explorer_key.GetSubkeys():\n        delegate_folders_key = subkey.GetSubkeyByPath(\n            'NameSpace\\\\DelegateFolders')\n        if delegate_folders_key:\n          yield from self._CollectDelegateFolders(\n              delegate_folders_key, subkey.name)\n"
  },
  {
    "path": "winregrc/environment_variables.py",
    "content": "\"\"\"Environment variables collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass EnvironmentVariable:\n  \"\"\"Environment variable.\n\n  Attributes:\n    name (str): name.\n    value (str): value.\n  \"\"\"\n\n  def __init__(self, name, value):\n    \"\"\"Initializes an environment variable.\n\n    Args:\n      name (str): name.\n      value (str): value.\n    \"\"\"\n    super().__init__()\n    self.name = name\n    self.value = value\n\n\nclass EnvironmentVariablesCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Environment variables collector.\"\"\"\n\n  _ENVIRONMENT_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\System\\\\CurrentControlSet\\\\Control\\\\'\n      'Session Manager\\\\Environment')\n\n  _PROFILELIST_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\'\n      'ProfileList')\n\n  _WINDOWS_CURRENTVERSION_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion')\n\n  _WINDOWS_NT_CURRENTVERSION_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows NT\\\\CurrentVersion')\n\n  _PROFILELIST_KEY_VALUE_MAPPINGS = {\n      'AllUsersProfile': '%AllUsersProfile%',\n      'ProgramData': '%ProgramData%',\n      'Public': '%Public%'}\n\n  _WINDOWS_KEY_VALUE_MAPPINGS = {\n      'CommonFilesDir': '%CommonProgramFiles%',\n      'CommonFilesDir (x86)': '%CommonProgramFiles(x86)%',\n      'CommonW6432Dir': '%CommonProgramW6432%',\n      'ProgramFilesDir': '%ProgramFiles%',\n      'ProgramFilesDir (x86)': '%ProgramFiles(x86)%',\n      'ProgramW6432Dir': '%ProgramW6432%'}\n\n  _WINDOWS_NT_KEY_VALUE_MAPPINGS = {\n      'SystemRoot': '%SystemRoot%'}\n\n  def _CollectEnvironmentVariablesFromEnvironmentKey(self, registry_key):\n    \"\"\"Collects environment variables.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): environment Windows Registry\n          key.\n\n    Yields:\n      EnvironmentVariable: an environment variable.\n    \"\"\"\n    for registry_value in registry_key.GetValues():\n      value_string = registry_value.GetDataAsObject()\n      yield EnvironmentVariable(f'%{registry_value.name:s}%', value_string)\n\n  def _CollectEnvironmentVariablesWithMappings(self, registry_key, mappings):\n    \"\"\"Collects environment variables.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n\n    Yields:\n      EnvironmentVariable: an environment variable.\n    \"\"\"\n    for value_name, environment_variable_name in mappings.items():\n      registry_value = registry_key.GetValueByName(value_name)\n      if registry_value:\n        value_string = registry_value.GetDataAsObject()\n        yield EnvironmentVariable(environment_variable_name, value_string)\n\n  def Collect(self, registry):\n    \"\"\"Collects environment variables.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Yields:\n      EnvironmentVariable: an environment variable.\n    \"\"\"\n    registry_key = registry.GetKeyByPath(self._ENVIRONMENT_KEY_PATH)\n    if registry_key:\n      yield from self._CollectEnvironmentVariablesFromEnvironmentKey(\n          registry_key)\n\n    registry_key = registry.GetKeyByPath(self._PROFILELIST_KEY_PATH)\n    if registry_key:\n      yield from self._CollectEnvironmentVariablesWithMappings(\n          registry_key, self._PROFILELIST_KEY_VALUE_MAPPINGS)\n\n    registry_key = registry.GetKeyByPath(self._WINDOWS_CURRENTVERSION_KEY_PATH)\n    if registry_key:\n      yield from self._CollectEnvironmentVariablesWithMappings(\n          registry_key, self._WINDOWS_KEY_VALUE_MAPPINGS)\n\n    registry_key = registry.GetKeyByPath(\n        self._WINDOWS_NT_CURRENTVERSION_KEY_PATH)\n    if registry_key:\n      yield from self._CollectEnvironmentVariablesWithMappings(\n          registry_key, self._WINDOWS_NT_KEY_VALUE_MAPPINGS)\n"
  },
  {
    "path": "winregrc/errors.py",
    "content": "\"\"\"The error objects.\"\"\"\n\n\nclass Error(Exception):\n  \"\"\"The error interface.\"\"\"\n\n\nclass ParseError(Error):\n  \"\"\"Error that is raised when value data cannot be parsed.\"\"\"\n"
  },
  {
    "path": "winregrc/eventlog_providers.py",
    "content": "\"\"\"Windows Event Log providers collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass EventLogProvider:\n  \"\"\"Windows Event Log provider.\n\n  Attributes:\n    additional_identifier (str): additional identifier of the provider,\n        contains a GUID.\n    category_message_files (set[str]): paths of the category message files.\n    event_message_files (set[str]): paths of the event message files.\n    identifier (str): identifier of the provider, contains a GUID.\n    log_sources (list[str]): names of the corresponding Event Log sources.\n    log_types (list[str]): Windows Event Log types.\n    name (str): name of the provider.\n    parameter_message_files (set[str]): paths of the parameter message\n        files.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes a Windows Event Log provider.\"\"\"\n    super().__init__()\n    self.additional_identifier = None\n    self.category_message_files = set()\n    self.event_message_files = set()\n    self.identifier = None\n    self.log_sources = []\n    self.log_types = []\n    self.name = None\n    self.parameter_message_files = set()\n\n\nclass EventLogProvidersCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows Event Log providers collector.\"\"\"\n\n  _SERVICES_EVENTLOG_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\System\\\\CurrentControlSet\\\\Services\\\\EventLog')\n\n  _WINEVT_PUBLISHERS_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n      'WINEVT\\\\Publishers')\n\n  def _CollectEventLogProviders(\n      self, services_eventlog_key, winevt_publishers_key):\n    \"\"\"Collects Windows Event Log providers.\n\n    Args:\n      services_eventlog_key (dfwinreg.WinRegistryKey): a Services\\\\EventLog\n          Windows Registry.\n      winevt_publishers_key (dfwinreg.WinRegistryKey): a WINEVT\\\\Publishers\n          Windows Registry.\n\n    Yields:\n      EventLogProvider: an Event Log provider.\n    \"\"\"\n    event_log_providers_per_identifier = {}\n    event_log_providers_per_name = {}\n\n    for event_log_provider in self._CollectEventLogProvidersFromPublishersKeys(\n        winevt_publishers_key):\n      provider_identifier = event_log_provider.identifier\n\n      existing_event_log_provider = event_log_providers_per_identifier.get(\n          provider_identifier, None)\n      if existing_event_log_provider:\n        self._MergeEventLogProviders(\n            existing_event_log_provider, event_log_provider)\n\n      else:\n        event_log_providers_per_identifier[provider_identifier] = (\n            event_log_provider)\n\n        if event_log_provider.name:\n          event_log_providers_per_name[event_log_provider.name] = (\n              event_log_provider)\n\n    event_log_providers_per_log_source = {}\n\n    for event_log_provider in self._CollectEventLogProvidersFromServicesKey(\n        services_eventlog_key):\n      provider_identifier = event_log_provider.identifier\n\n      if provider_identifier:\n        existing_event_log_provider = event_log_providers_per_identifier.get(\n            provider_identifier, None)\n        if existing_event_log_provider:\n          self._MergeEventLogProviders(\n              existing_event_log_provider, event_log_provider)\n          continue\n\n      log_source = event_log_provider.log_sources[0]\n      existing_event_log_provider = event_log_providers_per_name.get(\n          log_source, None)\n      if existing_event_log_provider:\n        if (provider_identifier and\n            provider_identifier != existing_event_log_provider.identifier):\n          existing_event_log_provider.additional_identifier = (\n              provider_identifier)\n\n        self._MergeEventLogProviders(\n            existing_event_log_provider, event_log_provider)\n        continue\n\n      event_log_providers_per_log_source[log_source] = event_log_provider\n\n    event_log_providers = list(event_log_providers_per_identifier.values())\n    event_log_providers.extend(event_log_providers_per_log_source.values())\n\n    for event_log_provider in sorted(\n        event_log_providers, key=self._GetEventLogProviderSortedKey):\n      event_log_provider.category_message_files = self._NormalizeMessageFiles(\n          event_log_provider.category_message_files)\n      event_log_provider.event_message_files = self._NormalizeMessageFiles(\n          event_log_provider.event_message_files)\n      event_log_provider.parameter_message_files = self._NormalizeMessageFiles(\n          event_log_provider.parameter_message_files)\n\n      yield event_log_provider\n\n  def _CollectEventLogProvidersFromPublishersKeys(self, winevt_publishers_key):\n    \"\"\"Collects Windows Event Log providers from a WINEVT publishers key.\n\n    Args:\n      winevt_publishers_key (dfwinreg.WinRegistryKey): WINEVT publishers key.\n\n    Yield:\n      EventLogProvider: Event Log provider.\n    \"\"\"\n    if winevt_publishers_key:\n      for guid_key in winevt_publishers_key.GetSubkeys():\n        event_log_provider = EventLogProvider()\n        event_log_provider.identifier = guid_key.name.lower()\n        event_log_provider.name = self._GetValueFromKey(guid_key, '')\n\n        event_message_files = self._GetMessageFilePathsFromKey(\n            guid_key, 'MessageFileName')\n        event_log_provider.event_message_files = event_message_files\n\n        # TODO: add support for ResourceFileName value\n        # TODO: add support for ParameterFileName value\n\n        yield event_log_provider\n\n  def _CollectEventLogProvidersFromServicesKey(self, services_eventlog_key):\n    \"\"\"Collects Windows Event Log providers from a services Event Log key.\n\n    Args:\n      services_eventlog_key (dfwinreg.WinRegistryKey): services Event Log key.\n\n    Yield:\n      EventLogProvider: Event Log provider.\n    \"\"\"\n    if services_eventlog_key:\n      for log_type_key in services_eventlog_key.GetSubkeys():\n        for provider_key in log_type_key.GetSubkeys():\n          provider_identifier = self._GetValueFromKey(\n              provider_key, 'ProviderGuid', default_value='')\n          provider_identifier = provider_identifier.lower()\n\n          event_log_provider = EventLogProvider()\n          event_log_provider.identifier = provider_identifier or None\n          event_log_provider.log_sources = [provider_key.name]\n          event_log_provider.log_types = [log_type_key.name]\n\n          category_message_files = self._GetMessageFilePathsFromKey(\n              provider_key, 'CategoryMessageFile')\n          event_log_provider.category_message_files = category_message_files\n\n          event_message_files = self._GetMessageFilePathsFromKey(\n              provider_key, 'EventMessageFile')\n          event_log_provider.event_message_files = event_message_files\n\n          parameter_message_files = self._GetMessageFilePathsFromKey(\n              provider_key, 'ParameterMessageFile')\n          event_log_provider.parameter_message_files = parameter_message_files\n\n          yield event_log_provider\n\n  def _GetEventLogProviderSortedKey(self, event_log_provider):\n    \"\"\"Retrieves a key to sort Event Log providers on.\n\n    Args:\n      event_log_provider (EventLogProvider): Event Log provider.\n\n    Returns:\n      str: key to sort Event Log providers on.\n    \"\"\"\n    if not event_log_provider.log_sources:\n      return event_log_provider.name or ''\n\n    return event_log_provider.log_sources[0]\n\n  def _GetMessageFilePathsFromKey(self, registry_key, value_name):\n    \"\"\"Retrieves a value as a list of message file paths.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n      value_name (str): name of the value.\n\n    Returns:\n      set[str]: paths of message files.\n    \"\"\"\n    message_files = set()\n\n    registry_value = registry_key.GetValueByName(value_name)\n    if registry_value:\n      value_string = registry_value.GetDataAsObject()\n      for path in value_string.split(';'):\n        path = path.strip()\n        if path:\n          message_files.add(path)\n\n    return message_files\n\n  def _MergeEventLogProviders(\n      self, first_event_log_provider, second_event_log_provider):\n    \"\"\"Merges the information of the second Event Log provider into the first.\n\n    Args:\n      first_event_log_provider (EventLogProvider): first Event Log provider.\n      second_event_log_provider (EventLogProvider): second Event Log provider.\n    \"\"\"\n    for log_source in second_event_log_provider.log_sources:\n      if log_source not in first_event_log_provider.log_sources:\n        first_event_log_provider.log_sources.append(log_source)\n\n    for log_type in second_event_log_provider.log_types:\n      if log_type not in first_event_log_provider.log_types:\n        first_event_log_provider.log_types.append(log_type)\n\n    first_event_log_provider.category_message_files.update(\n        second_event_log_provider.category_message_files)\n    first_event_log_provider.event_message_files.update(\n        second_event_log_provider.event_message_files)\n    first_event_log_provider.parameter_message_files.update(\n        second_event_log_provider.parameter_message_files)\n\n  def _NormalizeMessageFiles(self, message_files):\n    \"\"\"Normalizes the message files.\n\n    Args:\n      message_files (list[str]): paths of the message files.\n\n    Returns:\n      set[str]: normalized paths of the message files.\n    \"\"\"\n    normalized_message_files = set()\n    paths_lower = set()\n    for path in message_files:\n      path_lower = path.lower()\n      if path_lower not in paths_lower:\n        paths_lower.add(path_lower)\n        normalized_message_files.add(path)\n\n    return normalized_message_files\n\n  def Collect(self, registry):\n    \"\"\"Collects Windows Event Log providers from a Windows Registry.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      generator[EventLogProvider]: Event Log provider generator.\n    \"\"\"\n    # TODO: add support to collect Event Log providers from all control sets.\n\n    services_eventlog_key = registry.GetKeyByPath(\n        self._SERVICES_EVENTLOG_KEY_PATH)\n    winevt_publishers_key = registry.GetKeyByPath(\n        self._WINEVT_PUBLISHERS_KEY_PATH)\n\n    return self._CollectEventLogProviders(\n        services_eventlog_key, winevt_publishers_key)\n"
  },
  {
    "path": "winregrc/filters.py",
    "content": "\"\"\"The Windows Registry key and value filters.\"\"\"\n\nimport abc\n\n\nclass BaseWindowsRegistryKeyFilter:\n  \"\"\"Windows Registry key filter interface.\"\"\"\n\n  # Note that redundant-returns-doc is broken for pylint 1.7.x\n  # pylint: disable=redundant-returns-doc\n\n  @property\n  def key_paths(self):\n    \"\"\"List of key paths defined by the filter.\"\"\"\n    return []\n\n  @abc.abstractmethod\n  def Match(self, registry_key):\n    \"\"\"Determines if a Windows Registry key matches the filter.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): a Windows Registry key.\n\n    Returns:\n      bool: True if a match, False otherwise.\n    \"\"\"\n\n\nclass WindowsRegistryKeyPathFilter(BaseWindowsRegistryKeyFilter):\n  \"\"\"Windows Registry key path filter.\"\"\"\n\n  _CONTROL_SET_PREFIX = (\n      'HKEY_LOCAL_MACHINE\\\\System\\\\CurrentControlSet')\n\n  # This list must be ordered with most specific matches first.\n  _WOW64_PREFIXES = [\n      'HKEY_CURRENT_USER\\\\Software\\\\Classes',\n      'HKEY_CURRENT_USER\\\\Software',\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Classes',\n      'HKEY_LOCAL_MACHINE\\\\Software']\n\n  def __init__(self, key_path):\n    \"\"\"Initializes a Windows Registry key filter.\n\n    Args:\n      key_path (str): key path.\n    \"\"\"\n    super().__init__()\n\n    key_path.rstrip('\\\\')\n    self._key_path = key_path\n\n    key_path = key_path.upper()\n    self._key_path_upper = key_path\n\n    self._wow64_key_path = None\n    self._wow64_key_path_upper = None\n\n    if key_path.startswith(self._CONTROL_SET_PREFIX.upper()):\n      self._key_path_prefix, _, self._key_path_suffix = key_path.partition(\n          'CurrentControlSet'.upper())\n\n    else:\n      self._key_path_prefix = None\n      self._key_path_suffix = None\n\n      # Handle WoW64 Windows Registry key redirection.\n      # Also see:\n      # https://msdn.microsoft.com/en-us/library/windows/desktop/\n      # ms724072%28v=vs.85%29.aspx\n      # https://msdn.microsoft.com/en-us/library/windows/desktop/\n      # aa384253(v=vs.85).aspx\n      wow64_prefix = None\n      for key_path_prefix in self._WOW64_PREFIXES:\n        if key_path.startswith(key_path_prefix.upper()):\n          wow64_prefix = key_path_prefix\n          break\n\n      if wow64_prefix:\n        key_path_suffix = self._key_path[len(wow64_prefix):]\n        if key_path_suffix.startswith('\\\\'):\n          key_path_suffix = key_path_suffix[1:]\n        self._wow64_key_path = '\\\\'.join([\n            wow64_prefix, 'Wow6432Node', key_path_suffix])\n        self._wow64_key_path_upper = self._wow64_key_path.upper()\n\n  @property\n  def key_paths(self):\n    \"\"\"Retrieves the key paths defined by the filter.\n\n    Returns:\n      list[str]: key paths defined by the filter.\n    \"\"\"\n    if self._wow64_key_path:\n      return [self._key_path, self._wow64_key_path]\n    return [self._key_path]\n\n  def Match(self, registry_key):\n    \"\"\"Determines if a Windows Registry key matches the filter.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): a Windows Registry key.\n\n    Returns:\n      bool: True if a match, False otherwise.\n    \"\"\"\n    key_path = registry_key.path.upper()\n    if self._key_path_prefix and self._key_path_suffix:\n      if (key_path.startswith(self._key_path_prefix) and\n          key_path.endswith(self._key_path_suffix)):\n\n        key_path_segment = key_path[\n            len(self._key_path_prefix):-len(self._key_path_suffix)]\n        if key_path_segment.startswith('ControlSet'.upper()):\n          try:\n            control_set = int(key_path_segment[10:], 10)\n          except ValueError:\n            control_set = None\n\n          # TODO: check if control_set is in bounds.\n          return control_set is not None\n\n    return key_path in (self._key_path_upper, self._wow64_key_path_upper)\n\n\nclass WindowsRegistryKeyPathPrefixFilter(BaseWindowsRegistryKeyFilter):\n  \"\"\"Windows Registry key path prefix filter.\"\"\"\n\n  def __init__(self, key_path_prefix):\n    \"\"\"Initializes a Windows Registry key filter.\n\n    Args:\n      key_path_prefix (str): key path prefix.\n    \"\"\"\n    super().__init__()\n    self._key_path_prefix = key_path_prefix\n\n  def Match(self, registry_key):\n    \"\"\"Determines if a Windows Registry key matches the filter.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): a Windows Registry key.\n\n    Returns:\n      bool: True if a match, False otherwise.\n    \"\"\"\n    return registry_key.path.startsswith(self._key_path_prefix)\n\n\nclass WindowsRegistryKeyPathSuffixFilter(BaseWindowsRegistryKeyFilter):\n  \"\"\"Windows Registry key path suffix filter.\"\"\"\n\n  def __init__(self, key_path_suffix):\n    \"\"\"Initializes a Windows Registry key filter.\n\n    Args:\n      key_path_suffix (str): key path suffix.\n    \"\"\"\n    super().__init__()\n    self._key_path_suffix = key_path_suffix\n\n  def Match(self, registry_key):\n    \"\"\"Determines if a Windows Registry key matches the filter.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): a Windows Registry key.\n\n    Returns:\n      bool: True if a match, False otherwise.\n    \"\"\"\n    return registry_key.path.endswith(self._key_path_suffix)\n\n\nclass WindowsRegistryKeyWithValuesFilter(BaseWindowsRegistryKeyFilter):\n  \"\"\"Windows Registry key with values filter.\"\"\"\n\n  _EMPTY_SET = frozenset()\n\n  def __init__(self, value_names):\n    \"\"\"Initializes a Windows Registry key filter.\n\n    Args:\n      value_names (list[str]): value names that should be present in the key.\n    \"\"\"\n    super().__init__()\n    self._value_names = frozenset(value_names)\n\n  def Match(self, registry_key):\n    \"\"\"Determines if a Windows Registry key matches the filter.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): a Windows Registry key.\n\n    Returns:\n      bool: True if a match, False otherwise.\n    \"\"\"\n    value_names = frozenset([\n        registry_value.name for registry_value in registry_key.GetValues()])\n\n    return self._value_names.issubset(value_names)\n"
  },
  {
    "path": "winregrc/hexdump.py",
    "content": "\"\"\"Function to provide hexadecimal representation of data.\"\"\"\n\n\n_HEXDUMP_CHARACTER_MAP = [\n    '.' if byte < 0x20 or byte > 0x7e else chr(byte) for byte in range(256)]\n\n\ndef Hexdump(data):\n  \"\"\"Formats data in a hexadecimal representation.\n\n  Args:\n    data (byte): data.\n\n  Returns:\n    str: hexadecimal representation of the data.\n  \"\"\"\n  in_group = False\n  previous_hexadecimal_string = None\n\n  lines = []\n  data_size = len(data)\n  for block_index in range(0, data_size, 16):\n    data_string = data[block_index:block_index + 16]\n\n    hexadecimal_byte_values = []\n    printable_values = []\n    for byte_value in data_string:\n      if isinstance(byte_value, str):\n        byte_value = ord(byte_value)\n\n      hexadecimal_byte_values.append(f'{byte_value:02x}')\n\n      printable_value = _HEXDUMP_CHARACTER_MAP[byte_value]\n      printable_values.append(printable_value)\n\n    remaining_size = 16 - len(data_string)\n    if remaining_size == 0:\n      whitespace = ''\n    elif remaining_size >= 8:\n      whitespace = ' ' * ((3 * remaining_size) - 1)\n    else:\n      whitespace = ' ' * (3 * remaining_size)\n\n    hexadecimal_string_part1 = ' '.join(hexadecimal_byte_values[0:8])\n    hexadecimal_string_part2 = ' '.join(hexadecimal_byte_values[8:16])\n    hexadecimal_string = (\n        f'{hexadecimal_string_part1:s}  {hexadecimal_string_part2:s}'\n        f'{whitespace:s}')\n\n    if (previous_hexadecimal_string is not None and\n        previous_hexadecimal_string == hexadecimal_string and\n        block_index + 16 < data_size):\n\n      if not in_group:\n        in_group = True\n\n        lines.append('...')\n\n    else:\n      printable_string = ''.join(printable_values)\n\n      lines.append(\n          f'0x{block_index:08x}  {hexadecimal_string:s}  {printable_string:s}')\n\n      in_group = False\n      previous_hexadecimal_string = hexadecimal_string\n\n  lines.extend(['', ''])\n  return '\\n'.join(lines)\n"
  },
  {
    "path": "winregrc/interface.py",
    "content": "\"\"\"Windows Registry key and value collector.\"\"\"\n\n\nclass WindowsRegistryKeyCollector:\n  \"\"\"Windows Registry key and value collector.\"\"\"\n\n  def __init__(self, debug=False):\n    \"\"\"Initializes a Windows Registry key and value collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n    \"\"\"\n    super().__init__()\n    self._debug = debug\n\n  def _GetStringValueFromKey(\n      self, registry_key, value_name, default_value=None):\n    \"\"\"Retrieves a string value from a Registry value.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n      value_name (str): name of the value.\n      default_value (Optional[str]): default value.\n\n    Returns:\n      str: value or the default value if not available.\n    \"\"\"\n    if not registry_key:\n      return default_value\n\n    registry_value = registry_key.GetValueByName(value_name)\n    if not registry_value:\n      return default_value\n\n    if not registry_value.DataIsString():\n      return default_value\n\n    return registry_value.GetDataAsObject()\n\n  def _GetValueDataFromKey(self, registry_key, value_name):\n    \"\"\"Retrieves the value data from a Registry value.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n      value_name (str): name of the value.\n\n    Returns:\n      bytes: value data or None if not available.\n    \"\"\"\n    if not registry_key:\n      return None\n\n    registry_value = registry_key.GetValueByName(value_name)\n    if not registry_value:\n      return None\n\n    return registry_value.data\n\n  def _GetValueFromKey(self, registry_key, value_name, default_value=None):\n    \"\"\"Retrieves a value from a Registry value.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n      value_name (str): name of the value.\n      default_value (Optional[str]): default value.\n\n    Returns:\n      str: value or the default value if not available.\n    \"\"\"\n    if not registry_key:\n      return default_value\n\n    registry_value = registry_key.GetValueByName(value_name)\n    if not registry_value:\n      return default_value\n\n    return registry_value.GetDataAsObject()\n"
  },
  {
    "path": "winregrc/knownfolders.py",
    "content": "\"\"\"Windows known folders collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass KnownFolder:\n  \"\"\"Known folder.\n\n  Attributes:\n    alternate_display_names (list[str]): alternate display names.\n    identifier (str): identifier.\n    localized_display_name (str): localized display name.\n    display_name (str): display name.\n  \"\"\"\n\n  def __init__(self, identifier, display_name, localized_display_name):\n    \"\"\"Initializes a known folder.\n\n    Args:\n      identifier (str): identifier.\n      display_name (str): display name.\n      localized_display_name (str): localized display name.\n    \"\"\"\n    super().__init__()\n    self.alternate_display_names = []\n    self.identifier = identifier\n    self.localized_display_name = localized_display_name\n    self.display_name = display_name\n\n\nclass KnownFoldersCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows known folders collector.\"\"\"\n\n  _FOLDER_DESCRIPTIONS_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n      'Explorer\\\\FolderDescriptions')\n\n  def _CollectKnownFolders(self, folder_descriptions_key):\n    \"\"\"Collects Windows known folders.\n\n    Args:\n      folder_descriptions_key (dfwinreg.WinRegistryKey): folder descriptions\n          Windows Registry key.\n\n    Yields:\n      KnownFolder: a known folder.\n    \"\"\"\n    for subkey in folder_descriptions_key.GetSubkeys():\n      identifier = subkey.name.lower()\n      display_name = self._GetValueFromKey(subkey, 'Name')\n      localized_display_name = self._GetValueFromKey(subkey, 'LocalizedName')\n\n      yield KnownFolder(identifier, display_name, localized_display_name)\n\n  def Collect(self, registry):\n    \"\"\"Collects Windows known folders.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Yields:\n      KnownFolder: a known folder.\n    \"\"\"\n    folder_descriptions_key = registry.GetKeyByPath(\n        self._FOLDER_DESCRIPTIONS_KEY_PATH)\n    if folder_descriptions_key:\n      yield from self._CollectKnownFolders(folder_descriptions_key)\n"
  },
  {
    "path": "winregrc/mounted_devices.py",
    "content": "\"\"\"Windows mounted devices collector.\"\"\"\n\nfrom winregrc import data_format\nfrom winregrc import errors\n\n\nclass MountedDevice:\n  \"\"\"Mounted device.\n\n  Attributes:\n    device (str): device.\n    disk_identity (int): MBR disk identity.\n    identifier (str): identifier.\n    partition_identifier (str): GPT partition identifier.\n    partition_offset (int): MBR partition offset.\n  \"\"\"\n\n  def __init__(self, identifier):\n    \"\"\"Initializes a mounted device.\n\n    Args:\n      identifier (str): identifier.\n    \"\"\"\n    super().__init__()\n    self.device = None\n    self.disk_identity = None\n    self.identifier = identifier\n    self.partition_identifier = None\n    self.partition_offset = None\n\n\nclass MountedDevicesCollector(data_format.BinaryDataFormat):\n  \"\"\"Windows mounted devices collector.\"\"\"\n\n  _DEFINITION_FILE = 'mounted_devices.yaml'\n\n  _MOUNTED_DEVICES_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\System\\\\MountedDevices')\n\n  def _ParseMountedDevicesValue(self, registry_value):\n    \"\"\"Parses a Windows mounted devices Windows Registry value.\n\n    Args:\n      registry_value (dfwinreg.WinRegistryValue): a mounted devices Windows\n          Registry value.\n\n    Returns:\n      MountedDevice: a mounted device.\n\n    Raises:\n      ParseError: if the value could not be parsed.\n    \"\"\"\n    mounted_device = MountedDevice(registry_value.name)\n    value_data_size = len(registry_value.data)\n\n    if value_data_size == 12:\n      data_type_map = self._GetDataTypeMap('mounted_devices_mbr_partition')\n\n      try:\n        partition_values = self._ReadStructureFromByteStream(\n            registry_value.data, 0, data_type_map,\n            'Mounted devices MBR partition values')\n      except (ValueError, errors.ParseError) as exception:\n        raise errors.ParseError((\n            f'Unable to parse Mounted devices MBR partition values with '\n            f'error: {exception!s}'))\n\n      mounted_device.disk_identity = partition_values.disk_identity\n      mounted_device.partition_offset = partition_values.partition_offset\n\n    elif value_data_size == 24:\n      data_type_map = self._GetDataTypeMap('mounted_devices_gpt_partition')\n\n      try:\n        partition_values = self._ReadStructureFromByteStream(\n            registry_value.data, 0, data_type_map,\n            'Mounted devices GPT partition values')\n      except (ValueError, errors.ParseError) as exception:\n        raise errors.ParseError((\n            f'Unable to parse Mounted devices GPT partition values with '\n            f'error: {exception!s}'))\n\n      mounted_device.partition_identifier = (\n          partition_values.partition_identifier)\n\n    else:\n      mounted_device.device = registry_value.data.decode('utf-16-le')\n\n    return mounted_device\n\n  def Collect(self, registry):\n    \"\"\"Collects Windows mounted devices.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Yields:\n      MountedDevice: a mounted device.\n\n    Raises:\n      ParseError: if a mounted devices value could not be parsed.\n    \"\"\"\n    mounted_devices_key = registry.GetKeyByPath(self._MOUNTED_DEVICES_KEY_PATH)\n    if mounted_devices_key:\n      for registry_value in mounted_devices_key.GetValues():\n        yield self._ParseMountedDevicesValue(registry_value)\n"
  },
  {
    "path": "winregrc/mounted_devices.yaml",
    "content": "# dtFabric format specification.\n---\nname: mounted_devices\ntype: format\ndescription: Windows Registry mounted devices format\n---\nname: byte\ntype: integer\nattributes:\n  format: unsigned\n  size: 1\n  units: bytes\n---\nname: uint32\ntype: integer\nattributes:\n  format: unsigned\n  size: 4\n  units: bytes\n---\nname: uint64\ntype: integer\nattributes:\n  format: unsigned\n  size: 8\n  units: bytes\n---\nname: mounted_devices_gpt_partition\ntype: structure\ndescription: Mounted devices GPT partition value data\nattributes:\n  byte_order: little-endian\nmembers:\n- name: signature\n  type: stream\n  element_data_type: byte\n  number_of_elements: 8\n  value: \"DMIO:ID:\"\n- name: partition_identifier\n  type: uuid\n---\nname: mounted_devices_mbr_partition\ntype: structure\ndescription: Mounted devices MBR partition value data\nattributes:\n  byte_order: little-endian\nmembers:\n- name: disk_identity\n  data_type: uint32\n- name: partition_offset\n  data_type: uint64\n"
  },
  {
    "path": "winregrc/mru.py",
    "content": "\"\"\"Most Recently Used (MRU) collector.\"\"\"\n\nfrom dtfabric.runtime import data_maps as dtfabric_data_maps\n\nfrom winregrc import data_format\nfrom winregrc import errors\n\n\nclass MostRecentlyUsedEntry:\n  \"\"\"Most Recently Used (MRU) entry.\n\n  Attributes:\n    key_path (str): path of the Windows Registry key.\n    shell_item_data (bytes): Shell Item data.\n    shell_item_list_data (bytes): Shell Item list data.\n    string (str): string.\n    value_name (str): name of the Windows Registry value.\n  \"\"\"\n\n  def __init__(\n      self, key_path=None, shell_item_data=None, shell_item_list_data=None,\n      string=None, value_name=None):\n    \"\"\"Initializes a Most Recently Used (MRU) entry.\n\n    Args:\n      key_path (Optional[str]): path of the Windows Registry key.\n      shell_item_data (Optional[bytes]): Shell Item data.\n      shell_item_list_data (Optional[bytes]): Shell Item list data.\n      string (Optional[str]): string.\n      value_name (Optional[str]): name of the Windows Registry value.\n    \"\"\"\n    super().__init__()\n    self.key_path = key_path\n    self.shell_item_data = shell_item_data\n    self.shell_item_list_data = shell_item_list_data\n    self.string = string\n    self.value_name = value_name\n\n\nclass MostRecentlyUsedCollector(data_format.BinaryDataFormat):\n  \"\"\"Most Recently Used (MRU) collector.\n\n  Attributes:\n    mru_entries (list[MostRecentlyUsedEntry]): most recently used (MRU) entries.\n  \"\"\"\n\n  _DEFINITION_FILE = 'mru.yaml'\n\n  _OPENSAVE_MRU_KEY_PATH = (\n      'HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n      'Explorer\\\\ComDlg32\\\\OpenSaveMRU').upper()\n\n  _SHELL_ITEM_MRU_KEY_PATHS = [\n      ('HKEY_CURRENT_USER\\\\Local Settings\\\\Software\\\\Microsoft\\\\Windows\\\\'\n       'Shell\\\\BagMRU'),\n      ('HKEY_CURRENT_USER\\\\Local Settings\\\\Software\\\\Microsoft\\\\Windows\\\\'\n       'ShellNoRoam\\\\BagMRU'),\n      'HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\Shell\\\\BagMRU',\n      ('HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\ShellNoRoam\\\\'\n       'BagMRU'),\n      ('HKEY_CURRENT_USER\\\\Software\\\\Classes\\\\Local Settings\\\\Software\\\\'\n       'Microsoft\\\\Windows\\\\Shell\\\\BagMRU'),\n      ('HKEY_CURRENT_USER\\\\Software\\\\Classes\\\\Local Settings\\\\Software\\\\'\n       'Microsoft\\\\Windows\\\\ShellNoRoam\\\\BagMRU'),\n      ('HKEY_CURRENT_USER\\\\Software\\\\Classes\\\\Wow6432Node\\\\Local Settings\\\\'\n       'Software\\\\Microsoft\\\\Windows\\\\Shell\\\\BagMRU'),\n      ('HKEY_CURRENT_USER\\\\Software\\\\Classes\\\\Wow6432Node\\\\Local Settings\\\\'\n       'Software\\\\Microsoft\\\\Windows\\\\ShellNoRoam\\\\BagMRU')]\n\n  _SHELL_ITEM_MRU_KEY_PATHS = [\n      key_path.upper() for key_path in _SHELL_ITEM_MRU_KEY_PATHS]\n\n  _SHELL_ITEM_LIST_MRU_KEY_PATHS = [\n      ('HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n       'Explorer\\\\DesktopStreamMRU'),\n      ('HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n       'Explorer\\\\ComDlg32\\\\OpenSavePidlMRU'),\n      ('HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n       'Explorer\\\\StreamMRU'),\n      ('HKEY_CURRENT_USER\\\\Software\\\\Classes\\\\Software\\\\Microsoft\\\\Windows\\\\'\n       'CurrentVersion\\\\Explorer\\\\StreamMRU')]\n\n  _SHELL_ITEM_LIST_MRU_KEY_PATHS = [\n      key_path.upper() for key_path in _SHELL_ITEM_LIST_MRU_KEY_PATHS]\n\n  _STRING_AND_SHELL_ITEM_MRU_KEY_PATHS = [\n      ('HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n       'Explorer\\\\RecentDocs')]\n\n  _STRING_AND_SHELL_ITEM_MRU_KEY_PATHS = [\n      key_path.upper() for key_path in _STRING_AND_SHELL_ITEM_MRU_KEY_PATHS]\n\n  _STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS = [\n      ('HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n       'Explorer\\\\ComDlg32\\\\LastVisitedPidlMRU')]\n\n  _STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS = [\n      key_path.upper()\n      for key_path in _STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS]\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a Most Recently Used (MRU) collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__(debug=debug)\n    self._output_writer = output_writer\n    self.mru_entries = []\n\n  def _InKeyPaths(self, key_path, key_paths):\n    \"\"\"Checks if a specific key path is defined in a list of key paths.\n\n    Args:\n      key_path (str): Windows Registry key path.\n      key_paths (list[str]): list of Windows Registry key paths in upper case.\n\n    Returns:\n      bool: True if the key path is defined in the list of key paths.\n    \"\"\"\n    key_path = key_path.upper()\n    for matching_key_path in key_paths:\n      if key_path.startswith(matching_key_path):\n        return True\n\n    return False\n\n  def _ProcessKey(self, registry_key):\n    \"\"\"Processes a Windows Registry key.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n\n    Returns:\n      bool: True if a Most Recently Used (MRU) key was found, False if not.\n    \"\"\"\n    result = False\n    value_names = [\n        registry_value.name for registry_value in registry_key.GetValues()]\n\n    if 'MRUList' in value_names:\n      if self._ProcessKeyWithMRUListValue(registry_key):\n        result = True\n\n    elif 'MRUListEx' in value_names:\n      if self._ProcessKeyWithMRUListExValue(registry_key):\n        result = True\n\n    for subkey in registry_key.GetSubkeys():\n      if self._ProcessKey(subkey):\n        result = True\n\n    return result\n\n  def _ProcessKeyWithMRUListValue(self, registry_key):\n    \"\"\"Processes a Windows Registry key that contains a MRUList value.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n\n    Returns:\n      bool: True if a Most Recently Used (MRU) key was found, False if not.\n\n    Raises:\n      ParseError: if the MRUList value could not be parsed.\n    \"\"\"\n    registry_value = registry_key.GetValueByName('MRUList')\n\n    data_type_map = self._GetDataTypeMap('mrulist_entries')\n\n    context = dtfabric_data_maps.DataTypeMapContext(values={\n        'data_size': len(registry_value.data)})\n\n    try:\n      mrulist_entries = self._ReadStructureFromByteStream(\n          registry_value.data, 0, data_type_map, 'MRUList entries',\n          context=context)\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse MRUList entries with error: {exception!s}')\n\n    mrulist = set([])\n    recovered_mrulist = set([])\n    is_recovered = False\n    for entry_letter in mrulist_entries:\n      if entry_letter == 0:\n        is_recovered = True\n\n      entry_letter = chr(entry_letter)\n\n      if is_recovered:\n        recovered_mrulist.add(entry_letter)\n      else:\n        mrulist.add(entry_letter)\n\n    result = False\n    for registry_value in registry_key.GetValues():\n      if registry_value.name in (\n          'MRUList', 'NodeSlot', 'NodeSlots', 'ViewStream'):\n        continue\n\n      if self._debug:\n        self._output_writer.WriteText(\n            f'Key: {registry_key.path:s}\\nValue: {registry_value.name:s}\\n')\n\n      if self._InKeyPaths(registry_key.path, self._SHELL_ITEM_MRU_KEY_PATHS):\n        self._ProcessMRUEntryShellItem(\n            registry_key.path, registry_value.name, registry_value.data)\n\n      elif self._InKeyPaths(\n          registry_key.path, self._SHELL_ITEM_LIST_MRU_KEY_PATHS):\n        self._ProcessMRUEntryShellItemList(\n            registry_key.path, registry_value.name, registry_value.data)\n\n      elif self._InKeyPaths(\n          registry_key.path, self._STRING_AND_SHELL_ITEM_MRU_KEY_PATHS):\n        self._ProcessMRUEntryStringAndShellItem(\n            registry_key.path, registry_value.name, registry_value.data)\n\n      elif self._InKeyPaths(\n          registry_key.path, self._STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS):\n        self._ProcessMRUEntryStringAndShellItemList(\n            registry_key.path, registry_value.name, registry_value.data)\n\n      else:\n        self._ProcessMRUEntryString(\n            registry_key.path, registry_value.name, registry_value.data)\n\n      result = True\n\n    return result\n\n  def _ProcessKeyWithMRUListExValue(self, registry_key):\n    \"\"\"Processes a Windows Registry key that contains a MRUListEx value.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n\n    Returns:\n      bool: True if a Most Recently Used (MRU) key was found, False if not.\n\n    Raises:\n      ParseError: if the MRUListEx value could not be parsed.\n    \"\"\"\n    # TODO: determine what trailing data is in:\n    # HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\\n    # ComDlg32\\CIDSizeMRU\n\n    registry_value = registry_key.GetValueByName('MRUListEx')\n\n    data_type_map = self._GetDataTypeMap('mrulistex_entries')\n\n    context = dtfabric_data_maps.DataTypeMapContext(values={\n        'data_size': len(registry_value.data)})\n\n    try:\n      mrulistex_entries = self._ReadStructureFromByteStream(\n          registry_value.data, 0, data_type_map, 'MRUListEx entries',\n          context=context)\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse MRUListEx entries with error: {exception!s}')\n\n    mrulistex = set([])\n    recovered_mrulistex = set([])\n    is_recovered = False\n    for entry_number in mrulistex_entries:\n      if entry_number == 0:\n        is_recovered = True\n\n      if is_recovered:\n        recovered_mrulistex.add(entry_number)\n      else:\n        mrulistex.add(entry_number)\n\n    result = False\n    for registry_value in registry_key.GetValues():\n      if registry_value.name in (\n          'MRUListEx', 'NodeSlot', 'NodeSlots', 'ViewStream'):\n        continue\n\n      if self._debug:\n        self._output_writer.WriteText(\n            f'Key: {registry_key.path:s}\\nValue: {registry_value.name:s}\\n')\n\n      if self._InKeyPaths(registry_key.path, self._SHELL_ITEM_MRU_KEY_PATHS):\n        self._ProcessMRUEntryShellItem(\n            registry_key.path, registry_value.name, registry_value.data)\n\n      elif self._InKeyPaths(\n          registry_key.path, self._SHELL_ITEM_LIST_MRU_KEY_PATHS):\n        self._ProcessMRUEntryShellItemList(\n            registry_key.path, registry_value.name, registry_value.data)\n\n      elif self._InKeyPaths(\n          registry_key.path, self._STRING_AND_SHELL_ITEM_MRU_KEY_PATHS):\n        self._ProcessMRUEntryStringAndShellItem(\n            registry_key.path, registry_value.name, registry_value.data)\n\n      elif self._InKeyPaths(\n          registry_key.path, self._STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS):\n        self._ProcessMRUEntryStringAndShellItemList(\n            registry_key.path, registry_value.name, registry_value.data)\n\n      else:\n        self._ProcessMRUEntryString(\n            registry_key.path, registry_value.name, registry_value.data)\n\n      result = True\n\n    return result\n\n  def _ProcessMRUEntryShellItem(self, key_path, value_name, value_data):\n    \"\"\"Processes a shell item MRUEntry.\n\n    Args:\n      key_path (str): path of the Windows Registry key.\n      value_name (str): name of the Windows Registry value.\n      value_data (bytes): Windows Registry value data.\n    \"\"\"\n    if self._debug:\n      self._output_writer.WriteDebugData('Shell item data', value_data)\n\n    mru_entry = MostRecentlyUsedEntry(\n        key_path=key_path, shell_item_data=value_data, value_name=value_name)\n    self.mru_entries.append(mru_entry)\n\n  def _ProcessMRUEntryShellItemList(self, key_path, value_name, value_data):\n    \"\"\"Processes a shell item list MRUEntry.\n\n    Args:\n      key_path (str): path of the Windows Registry key.\n      value_name (str): name of the Windows Registry value.\n      value_data (bytes): Windows Registry value data.\n    \"\"\"\n    if self._debug:\n      self._output_writer.WriteDebugData('Shell item list data', value_data)\n\n    mru_entry = MostRecentlyUsedEntry(\n        key_path=key_path, shell_item_list_data=value_data,\n        value_name=value_name)\n    self.mru_entries.append(mru_entry)\n\n  def _ProcessMRUEntryString(self, key_path, value_name, value_data):\n    \"\"\"Processes a string MRUEntry.\n\n    Args:\n      key_path (str): path of the Windows Registry key.\n      value_name (str): name of the Windows Registry value.\n      value_data (bytes): Windows Registry value data.\n    \"\"\"\n    value_data_size = len(value_data)\n\n    data_offset = 0\n    for data_offset in range(0, value_data_size, 2):\n      if value_data[data_offset:data_offset + 2] == b'\\0\\0':\n        data_offset += 2\n        break\n\n    if self._debug:\n      self._output_writer.WriteDebugData(\n          'String data', value_data[0:data_offset])\n\n    string = value_data[0:data_offset - 2].decode('utf-16-le')\n\n    if self._debug:\n      self._output_writer.WriteValue('String', string)\n\n    if self._debug and data_offset < value_data_size:\n      self._output_writer.WriteDebugData(\n          'Trailing data', value_data[data_offset:])\n\n    mru_entry = MostRecentlyUsedEntry(\n        key_path=key_path, string=string, value_name=value_name)\n    self.mru_entries.append(mru_entry)\n\n  def _ProcessMRUEntryStringAndShellItem(\n      self, key_path, value_name, value_data):\n    \"\"\"Processes a string and shell item MRUEntry.\n\n    Args:\n      key_path (str): path of the Windows Registry key.\n      value_name (str): name of the Windows Registry value.\n      value_data (bytes): Windows Registry value data.\n    \"\"\"\n    value_data_size = len(value_data)\n\n    data_offset = 0\n    for data_offset in range(0, value_data_size, 2):\n      if value_data[data_offset:data_offset + 2] == b'\\0\\0':\n        data_offset += 2\n        break\n\n    if self._debug:\n      self._output_writer.WriteDebugData(\n          'String data', value_data[0:data_offset])\n\n    string = value_data[0:data_offset - 2].decode('utf-16-le')\n\n    if self._debug:\n      self._output_writer.WriteValue('String', string)\n\n    if data_offset < value_data_size:\n      if self._debug:\n        self._output_writer.WriteDebugData(\n            'Shell item data', value_data[data_offset:])\n\n    mru_entry = MostRecentlyUsedEntry(\n        key_path=key_path, shell_item_data=value_data[data_offset:],\n        string=string, value_name=value_name)\n    self.mru_entries.append(mru_entry)\n\n  def _ProcessMRUEntryStringAndShellItemList(\n      self, key_path, value_name, value_data):\n    \"\"\"Processes a string and shell item list MRUEntry.\n\n    Args:\n      key_path (str): path of the Windows Registry key.\n      value_name (str): name of the Windows Registry value.\n      value_data (bytes): Windows Registry value data.\n    \"\"\"\n    value_data_size = len(value_data)\n\n    data_offset = 0\n    for data_offset in range(0, value_data_size, 2):\n      if value_data[data_offset:data_offset + 2] == b'\\0\\0':\n        data_offset += 2\n        break\n\n    if self._debug:\n      self._output_writer.WriteDebugData(\n          'String data', value_data[0:data_offset])\n\n    string = value_data[0:data_offset - 2].decode('utf-16-le')\n\n    if self._debug:\n      self._output_writer.WriteValue('String', string)\n\n    if data_offset < value_data_size:\n      if self._debug:\n        self._output_writer.WriteDebugData(\n            'Shell item list data', value_data[data_offset:])\n\n    mru_entry = MostRecentlyUsedEntry(\n        key_path=key_path, shell_item_list_data=value_data[data_offset:],\n        string=string, value_name=value_name)\n    self.mru_entries.append(mru_entry)\n\n  def Collect(self, registry):  # pylint: disable=arguments-differ\n    \"\"\"Collects Most Recently Used (MRU) entries.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      bool: True if a Most Recently Used (MRU) key was found, False if not.\n    \"\"\"\n    result = False\n\n    current_user_key = registry.GetKeyByPath('HKEY_CURRENT_USER')\n    if current_user_key:\n      if self._ProcessKey(current_user_key):\n        result = True\n\n    if not result:\n      # Fallback for if source is a single UsrClass.dat file.\n      current_user_classes_key = registry.GetKeyByPath(\n          'HKEY_CURRENT_USER\\\\Software\\\\Classes')\n      if current_user_classes_key:\n        if self._ProcessKey(current_user_classes_key):\n          result = True\n\n    return result\n"
  },
  {
    "path": "winregrc/mru.yaml",
    "content": "# dtFabric format specification.\n---\nname: mru\ntype: format\ndescription: Most recently used (MRU) formats\n---\nname: byte\ntype: integer\nattributes:\n  format: unsigned\n  size: 1\n  units: bytes\n---\nname: uint16\ntype: integer\nattributes:\n  format: unsigned\n  size: 2\n  units: bytes\n---\nname: int32\ntype: integer\nattributes:\n  format: signed\n  size: 4\n  units: bytes\n---\nname: wchar16\ntype: character\nattributes:\n  size: 2\n  units: bytes\n---\nname: mrulist_entries\ntype: sequence\ndescription: MRUList entries\nelement_data_type: uint16\nelements_data_size: data_size\n---\nname: mrulistex_entries\ntype: sequence\ndescription: MRUListEx entries\nelement_data_type: int32\nelements_data_size: data_size\n---\nname: utf16le_string\ntype: string\nencoding: utf-16-le\nelement_data_type: wchar16\nelements_terminator: \"\\x00\\x00\"\n"
  },
  {
    "path": "winregrc/msie_zone_info.py",
    "content": "\"\"\"Microsoft Internet Explorer (MSIE) zone information collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass MSIEZoneInformation:\n  \"\"\"MSIE zone information.\n\n  Attributes:\n    control (str): control.\n    control_value (int|str): value to which the control is set.\n    zone (str): identifier of the zone to which the control applies.\n    zone_name (str): name of the zone to which the control applies.\n  \"\"\"\n\n  def __init__(self, zone, zone_name, control, control_value):\n    \"\"\"Initializes MSIE zone information.\n\n    Args:\n      zone (str): identifier of the zone to which the control applies.\n      zone_name (str): name of the zone to which the control applies.\n      control (str): control.\n      control_value (int|str): value to which the control is set.\n    \"\"\"\n    super().__init__()\n    self.control = control\n    self.control_value = control_value\n    self.zone = zone\n    self.zone_name = zone_name\n\n\nclass MSIEZoneInformationCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"MSIE zone information collector.\"\"\"\n\n  _LOCKDOWN_KEY_PATHS = [\n      # HKEY_CURRENT_USER\n      ('HKEY_CURRENT_USER\\\\Software\\\\Policies\\\\Microsoft\\\\Internet Explorer\\\\'\n       'Main\\\\FeatureControl\\\\FEATURE_LOCALMACHINE_LOCKDOWN'),\n      ('HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Internet Explorer\\\\Main\\\\'\n       'FeatureControl\\\\FEATURE_LOCALMACHINE_LOCKDOWN'),\n      # HKEY_LOCAL_MACHINE\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Policies\\\\Microsoft\\\\'\n       'Internet Explorer\\\\Main\\\\FeatureControl\\\\'\n       'FEATURE_LOCALMACHINE_LOCKDOWN'),\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Internet Explorer\\\\Main\\\\'\n       'FeatureControl\\\\FEATURE_LOCALMACHINE_LOCKDOWN'),\n      # HKEY_LOCAL_MACHINE WoW64\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Wow6432Node\\\\Policies\\\\Microsoft\\\\'\n       'Internet Explorer\\\\Main\\\\FeatureControl\\\\'\n       'FEATURE_LOCALMACHINE_LOCKDOWN'),\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Wow6432Node\\\\Microsoft\\\\'\n       'Internet Explorer\\\\Main\\\\FeatureControl\\\\'\n       'FEATURE_LOCALMACHINE_LOCKDOWN')]\n\n  _ZONES_KEY_PATHS = [\n      # HKEY_CURRENT_USER\n      ('HKEY_CURRENT_USER\\\\Software\\\\Policies\\\\Microsoft\\\\Windows\\\\'\n       'CurrentVersion\\\\Internet Settings\\\\Zones'),\n      ('HKEY_CURRENT_USER\\\\Software\\\\Policies\\\\Microsoft\\\\Windows\\\\'\n       'CurrentVersion\\\\Internet Settings\\\\Lockdown_Zones'),\n      ('HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n       'Internet Settings\\\\Zones'),\n      ('HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n       'Internet Settings\\\\Lockdown_Zones'),\n      # HKEY_LOCAL_MACHINE\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Policies\\\\Microsoft\\\\Windows\\\\'\n       'CurrentVersion\\\\Internet Settings\\\\Zones'),\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Policies\\\\Microsoft\\\\Windows\\\\'\n       'CurrentVersion\\\\Internet Settings\\\\Lockdown_Zones'),\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n       'Internet Settings\\\\Zones'),\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n       'Internet Settings\\\\Lockdown_Zones'),\n      # HKEY_LOCAL_MACHINE WoW64\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Wow6432Node\\\\Policies\\\\Microsoft\\\\'\n       'Windows\\\\CurrentVersion\\\\Internet Settings\\\\Zones'),\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Wow6432Node\\\\Policies\\\\Microsoft\\\\'\n       'Windows\\\\CurrentVersion\\\\Internet Settings\\\\Lockdown_Zones'),\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Wow6432Node\\\\Microsoft\\\\Windows\\\\'\n       'CurrentVersion\\\\Internet Settings\\\\Zones'),\n      ('HKEY_LOCAL_MACHINE\\\\Software\\\\Wow6432Node\\\\Microsoft\\\\Windows\\\\'\n       'CurrentVersion\\\\Internet Settings\\\\Lockdown_Zones')]\n\n  def _CollectZoneInformationFromLockdownKey(self, lockdown_key):\n    \"\"\"Collects MSIE zone information from a lockdown key.\n\n    Args:\n      lockdown_key (dfwinreg.WinRegistryKey): lockdown Windows Registry key.\n    \"\"\"\n    program_name = 'iexplore.exe'\n    program_value = lockdown_key.GetValueByName(program_name)\n\n    if program_value:\n      value = program_value.GetDataAsObject()\n    else:\n      value = 0\n\n    if self._debug:\n      if value == 1:\n        print(f'Local Machine lockdown for {program_name:s}: True')\n      else:\n        print(f'Local Machine lockdown for {program_name:s}: False')\n      print('')\n\n    # TODO: implement.\n\n  def _CollectZoneInformationFromZonesKey(self, zones_key):\n    \"\"\"Collects MSIE zone information from a zones key.\n\n    Args:\n      zones_key (dfwinreg.WinRegistryKey): zones Windows Registry key.\n\n    Yields:\n      MSIEZoneInformation: MSIE zone information.\n    \"\"\"\n    for zone_key in zones_key.GetSubkeys():\n      zone_name = self._GetValueFromKey(zone_key, 'DisplayName')\n\n      for setting_value in zone_key.GetValues():\n        # The 'Description' value contains a description of the zone.\n        # The 'PMDisplayName' value contains the display name of the zone in\n        # protected mode.\n        if setting_value.name in (\n            None, 'Description', 'DisplayName', 'PMDisplayName'):\n          continue\n\n        if len(setting_value.name) == 4 and setting_value.name != 'Icon':\n          if len(setting_value.data) != 4:\n            value_string = setting_value.data.encode('hex')\n          else:\n            value_string = setting_value.GetDataAsObject()\n\n        else:\n          value_string = None\n\n        yield MSIEZoneInformation(\n            zone_key.name, zone_name, setting_value.name, value_string)\n\n  def Collect(self, registry):\n    \"\"\"Collects the MSIE zone information.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Yields:\n      MSIEZoneInformation: MSIE zone information.\n    \"\"\"\n    for key_path in self._LOCKDOWN_KEY_PATHS:\n      lockdown_key = registry.GetKeyByPath(key_path)\n      if lockdown_key:\n        # TODO: do something with information in lockdown key\n        self._CollectZoneInformationFromLockdownKey(lockdown_key)\n\n    # TODO: check for value Policies\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\\n    # Internet Settings\\\\Security_HKEY_LOCAL_MACHINE_only and its data\n    # if not exists or 0, not enabled if 1 only HKLM policy applies\n\n    for key_path in self._ZONES_KEY_PATHS:\n      zones_key = registry.GetKeyByPath(key_path)\n      if zones_key:\n        yield from self._CollectZoneInformationFromZonesKey(zones_key)\n"
  },
  {
    "path": "winregrc/output_writers.py",
    "content": "\"\"\"Output writer.\"\"\"\n\nimport abc\n\nfrom dfdatetime import fat_date_time as dfdatetime_fat_date_time\nfrom dfdatetime import filetime as dfdatetime_filetime\n\nfrom winregrc import hexdump\n\n\nclass OutputWriter:\n  \"\"\"Output writer interface.\"\"\"\n\n  # Note that redundant-returns-doc is broken for pylint 1.7.x\n  # pylint: disable=redundant-returns-doc\n\n  _HEXDUMP_CHARACTER_MAP = [\n      '.' if byte < 0x20 or byte > 0x7e else chr(byte) for byte in range(256)]\n\n  def _FormatDataInHexadecimal(self, data):\n    \"\"\"Formats data in a hexadecimal representation.\n\n    Args:\n      data (bytes): data.\n\n    Returns:\n      str: hexadecimal representation of the data.\n    \"\"\"\n    in_group = False\n    previous_hexadecimal_string = None\n\n    lines = []\n    data_size = len(data)\n    for block_index in range(0, data_size, 16):\n      data_string = data[block_index:block_index + 16]\n\n      hexadecimal_byte_values = []\n      printable_values = []\n      for byte_value in data_string:\n        if isinstance(byte_value, str):\n          byte_value = ord(byte_value)\n\n        hexadecimal_byte_values.append(f'{byte_value:02x}')\n\n        printable_value = self._HEXDUMP_CHARACTER_MAP[byte_value]\n        printable_values.append(printable_value)\n\n      remaining_size = 16 - len(data_string)\n      if remaining_size == 0:\n        whitespace = ''\n      elif remaining_size >= 8:\n        whitespace = ' ' * ((3 * remaining_size) - 1)\n      else:\n        whitespace = ' ' * (3 * remaining_size)\n\n      hexadecimal_string_part1 = ' '.join(hexadecimal_byte_values[0:8])\n      hexadecimal_string_part2 = ' '.join(hexadecimal_byte_values[8:16])\n      hexadecimal_string = (\n          f'{hexadecimal_string_part1:s}  {hexadecimal_string_part2:s}'\n          f'{whitespace:s}')\n\n      if (previous_hexadecimal_string is not None and\n          previous_hexadecimal_string == hexadecimal_string and\n          block_index + 16 < data_size):\n\n        if not in_group:\n          in_group = True\n\n          lines.append('...')\n\n      else:\n        printable_string = ''.join(printable_values)\n\n        lines.append(\n            f'0x{block_index:08x}  {hexadecimal_string:s}  '\n            f'{printable_string:s}')\n\n        in_group = False\n        previous_hexadecimal_string = hexadecimal_string\n\n    lines.extend(['', ''])\n    return '\\n'.join(lines)\n\n  def _FormatFATDateTimeValue(self, value):\n    \"\"\"Formats a FAT date time value.\n\n    Args:\n      value (int): FAT date time value.\n\n    Returns:\n      str: date time string.\n    \"\"\"\n    if not value:\n      date_time_string = 'Not set (0)'\n    else:\n      date_time = dfdatetime_fat_date_time.FATDateTime(fat_date_time=value)\n      date_time_string = date_time.CopyToDateTimeString()\n      if not date_time_string:\n        date_time_string = f'0x{value:04x}'\n\n    return date_time_string\n\n  def _FormatFiletimeValue(self, value):\n    \"\"\"Formats a FILETIME timestamp value.\n\n    Args:\n      value (int): FILETIME timestamp value.\n\n    Returns:\n      str: date time string.\n    \"\"\"\n    if value == 0:\n      date_time_string = 'Not set (0)'\n    elif value == 0x7fffffffffffffff:\n      date_time_string = 'Never (0x7fffffffffffffff)'\n    else:\n      date_time = dfdatetime_filetime.Filetime(timestamp=value)\n      date_time_string = date_time.CopyToDateTimeString()\n      if date_time_string:\n        date_time_string = f'{date_time_string:s} UTC'\n      else:\n        date_time_string = f'0x{value:08x}'\n\n    return date_time_string\n\n  @abc.abstractmethod\n  def Close(self):\n    \"\"\"Closes the output writer.\"\"\"\n\n  def DebugPrintData(self, description, data):\n    \"\"\"Prints data for debugging.\n\n    Args:\n      description (str): description.\n      data (bytes): data.\n    \"\"\"\n    self.WriteText(f'{description:s}:\\n')\n\n    value_string = self._FormatDataInHexadecimal(data)\n    self.WriteText(value_string)\n\n  def DebugPrintValue(self, description, value):\n    \"\"\"Prints a value for debugging.\n\n    Args:\n      description (str): description.\n      value (object): value.\n    \"\"\"\n    alignment, _ = divmod(len(description), 8)\n    alignment_string = '\\t' * (8 - alignment + 1)\n    self.WriteText(f'{description:s}{alignment_string:s}: {value!s}\\n')\n\n  def DebugPrintText(self, text):\n    \"\"\"Prints text for debugging.\n\n    Args:\n      text (str): text.\n    \"\"\"\n    self.WriteText(text)\n\n  @abc.abstractmethod\n  def Open(self):\n    \"\"\"Opens the output writer.\n\n    Returns:\n      bool: True if successful or False if not.\n    \"\"\"\n\n  @abc.abstractmethod\n  def WriteDebugData(self, description, data):\n    \"\"\"Writes data for debugging.\n\n    Args:\n      description (str): description.\n      data (bytes): data to write.\n    \"\"\"\n\n  @abc.abstractmethod\n  def WriteIntegerValueAsDecimal(self, description, value):\n    \"\"\"Writes an integer value as decimal.\n\n    Args:\n      description (str): description.\n      value (int): value to write.\n    \"\"\"\n\n  @abc.abstractmethod\n  def WriteFiletimeValue(self, description, value):\n    \"\"\"Writes a FILETIME timestamp value.\n\n    Args:\n      description (str): description.\n      value (str): value to write.\n    \"\"\"\n\n  @abc.abstractmethod\n  def WriteText(self, text):\n    \"\"\"Writes text.\n\n    Args:\n      text (str): text to write.\n    \"\"\"\n\n  @abc.abstractmethod\n  def WriteValue(self, description, value):\n    \"\"\"Writes a value.\n\n    Args:\n      description (str): description.\n      value (str): value to write.\n    \"\"\"\n\n\nclass StdoutOutputWriter(OutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def Close(self):\n    \"\"\"Closes the output writer.\"\"\"\n    return\n\n  def Open(self):\n    \"\"\"Opens the output writer.\n\n    Returns:\n      bool: True if successful or False if not.\n    \"\"\"\n    return True\n\n  def WriteDebugData(self, description, data):\n    \"\"\"Writes data for debugging.\n\n    Args:\n      description (str): description.\n      data (bytes): data.\n    \"\"\"\n    self.WriteText(description)\n    self.WriteText('\\n')\n\n    hexdump_text = hexdump.Hexdump(data)\n    self.WriteText(hexdump_text)\n\n  def WriteFiletimeValue(self, description, value):\n    \"\"\"Writes a FILETIME timestamp value.\n\n    Args:\n      description (str): description.\n      value (int): FILETIME timestamp value.\n    \"\"\"\n    date_time_string = self._FormatFiletimeValue(value)\n    self.WriteValue(description, date_time_string)\n\n  def WriteIntegerValueAsDecimal(self, description, value):\n    \"\"\"Writes an integer value as decimal.\n\n    Args:\n      description (str): description.\n      value (int): integer value.\n    \"\"\"\n    self.WriteValue(description, f'{value:d}')\n\n  def WriteText(self, text):\n    \"\"\"Writes text.\n\n    Args:\n      text (str): text to write.\n    \"\"\"\n    print(text, end='')\n\n  def WriteValue(self, description, value):\n    \"\"\"Writes a value.\n\n    Args:\n      description (str): description.\n      value (object): value.\n    \"\"\"\n    description_no_tabs = description.replace('\\t', ' ' * 8)\n    alignment, _ = divmod(len(description_no_tabs), 8)\n    alignment_string = '\\t' * (8 - alignment + 1)\n    self.WriteText(f'{description:s}{alignment_string:s}: {value!s}\\n')\n"
  },
  {
    "path": "winregrc/profiles.py",
    "content": "\"\"\"Windows user profiles collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass UserProfile:\n  \"\"\"User profile.\n\n  Attributes:\n    profile_path (str): path of the users profile.\n    security_identifier (str): security identifier of the user.\n  \"\"\"\n\n  def __init__(self, security_identifier, profile_path):\n    \"\"\"Initializes an user profile.\n\n    Args:\n      security_identifier (str): security identifier of the user.\n      profile_path (str): path of the users profile.\n    \"\"\"\n    super().__init__()\n    self.profile_path = profile_path\n    self.security_identifier = security_identifier\n\n\nclass UserProfilesCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows user profiles collector.\"\"\"\n\n  _PROFILE_LIST_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\'\n      'ProfileList')\n\n  def _CollectUserProfiles(self, profile_list_key):\n    \"\"\"Collects user profiles.\n\n    Args:\n      profile_list_key (dfwinreg.WinRegistryKey): profile list Windows Registry.\n\n    Yields:\n      UserProfile: an user profile.\n    \"\"\"\n    for subkey in profile_list_key.GetSubkeys():\n      profile_image_path = self._GetValueFromKey(subkey, 'ProfileImagePath')\n\n      yield UserProfile(subkey.name, profile_image_path)\n\n  def Collect(self, registry):\n    \"\"\"Collects user profiles.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Yields:\n      UserProfile: an user profile.\n    \"\"\"\n    profile_list_key = registry.GetKeyByPath(self._PROFILE_LIST_KEY_PATH)\n    if profile_list_key:\n      yield from self._CollectUserProfiles(profile_list_key)\n"
  },
  {
    "path": "winregrc/programscache.py",
    "content": "\"\"\"Windows Programs Cache information collector.\"\"\"\n\nimport logging\nimport uuid\n\nfrom dtfabric.runtime import data_maps as dtfabric_data_maps\n\nimport pyfwsi\n\nfrom winregrc import data_format\nfrom winregrc import errors\nfrom winregrc import interface\n\n\nclass ProgramsCacheDataParser(data_format.BinaryDataFormat):\n  \"\"\"Programs Cache data parser.\"\"\"\n\n  _DEFINITION_FILE = 'programscache.yaml'\n\n  def _DebugPrintEntryFooter(self, entry_footer):\n    \"\"\"Prints entry footer value debug information.\n\n    Args:\n      entry_footer (programscache_entry_footer): entry footer.\n    \"\"\"\n    self._DebugPrintValue('Sentinel', f'0x{entry_footer.sentinel:02x}')\n\n  def _DebugPrintEntryHeader(self, entry_header):\n    \"\"\"Prints entry header value debug information.\n\n    Args:\n      entry_header (programscache_entry_header): entry header.\n    \"\"\"\n    self._DebugPrintDecimalValue('Entry data size', entry_header.data_size)\n\n  def _DebugPrintHeader(self, header):\n    \"\"\"Prints header value debug information.\n\n    Args:\n      header (programscache_header): header.\n    \"\"\"\n    self._DebugPrintDecimalValue('Format version', header.format_version)\n\n  def _DebugPrintShellItem(self, shell_item):\n    \"\"\"Prints shell item value debug information.\n\n    Args:\n      shell_item (pyfwsi.shell_item): shell item.\n    \"\"\"\n    self._DebugPrintValue(\n        'Shell item class type', f'0x{shell_item.class_type:02x}')\n\n    value_string = getattr(shell_item, 'name', '')\n    self._DebugPrintValue('Shell item name', value_string)\n\n  def _ParseEntryFooter(self, value_data, value_data_offset):\n    \"\"\"Parses an entry footer from the value data.\n\n    Args:\n      value_data (bytes): value data.\n      value_data_offset (int): offset of the entry footer relative to the start\n          of the value data.\n\n    Returns:\n      tuple: containing:\n\n        programscache_entry_footer: entry footer.\n        int: entry footer data size.\n\n    Raises:\n      ParseError: if the entry footer could not be parsed.\n    \"\"\"\n    data_type_map = self._GetDataTypeMap('programscache_entry_footer')\n    data_size = data_type_map.GetSizeHint()\n\n    if self._debug:\n      self._DebugPrintData(\n          'Entry footer data',\n          value_data[value_data_offset:value_data_offset + data_size])\n\n    try:\n      entry_footer = self._ReadStructureFromByteStream(\n          value_data[value_data_offset:], value_data_offset, data_type_map,\n          'entry footer')\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse entry footer value with error: {exception!s}')\n\n    if self._debug:\n      self._DebugPrintEntryFooter(entry_footer)\n\n    return entry_footer, data_size\n\n  def _ParseHeader(self, value_data):\n    \"\"\"Parses a header from the value data.\n\n    Args:\n      value_data (bytes): value data.\n\n    Returns:\n      tuple: containing:\n\n        programscache_header: header.\n        int: header data size.\n\n    Raises:\n      ParseError: if the header could not be parsed.\n    \"\"\"\n    data_type_map = self._GetDataTypeMap('programscache_header')\n    data_size = data_type_map.GetSizeHint()\n\n    if self._debug:\n      self._DebugPrintData('Header data', value_data[:data_size])\n\n    try:\n      header = self._ReadStructureFromByteStream(\n          value_data, 0, data_type_map, 'header')\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse header value with error: {exception!s}')\n\n    if self._debug:\n      self._DebugPrintHeader(header)\n\n    if header.format_version not in (1, 9, 12, 19):\n      raise errors.ParseError('Unsupported format.')\n\n    return header, data_size\n\n  def Parse(self, value_data):\n    \"\"\"Parses the value data.\n\n    Args:\n      value_data (bytes): value data.\n\n    Raises:\n      ParseError: if the value data could not be parsed.\n    \"\"\"\n    if self._debug:\n      self._DebugPrintData('Value data', value_data)\n\n    header, value_data_offset = self._ParseHeader(value_data)\n\n    if header.format_version == 1:\n      value_data_offset += 4\n\n    elif header.format_version == 9:\n      data_type_map = self._GetDataTypeMap('programscache_header9')\n      context = dtfabric_data_maps.DataTypeMapContext()\n\n      try:\n        header9 = self._ReadStructureFromByteStream(\n            value_data[value_data_offset:], value_data_offset, data_type_map,\n            'header9', context=context)\n      except (ValueError, errors.ParseError) as exception:\n        raise errors.ParseError(\n            f'Unable to parse header9 value with error: {exception!s}')\n\n      value_data_offset += context.byte_size\n\n      if self._debug:\n        self._DebugPrintValue('Unknown1', f'0x{header9.unknown1:08x}')\n\n    elif header.format_version in (12, 19):\n      uuid_object = uuid.UUID(bytes_le=value_data[4:20])\n      value_data_offset += 16\n\n      if self._debug:\n        self._DebugPrintValue('Known folder identifier', f'{uuid_object!s}')\n\n    sentinel = 0\n    if header.format_version != 9:\n      entry_footer, data_size = self._ParseEntryFooter(\n          value_data, value_data_offset)\n\n      value_data_offset += data_size\n\n      sentinel = entry_footer.sentinel\n\n    if self._debug:\n      self._DebugPrintText('\\n')\n\n    value_data_size = len(value_data)\n    while sentinel in (0, 1):\n      if value_data_offset >= value_data_size:\n        break\n\n      data_type_map = self._GetDataTypeMap('programscache_entry_header')\n      context = dtfabric_data_maps.DataTypeMapContext()\n\n      try:\n        entry_header = self._ReadStructureFromByteStream(\n            value_data[value_data_offset:], value_data_offset, data_type_map,\n            'entry header', context=context)\n      except (ValueError, errors.ParseError) as exception:\n        raise errors.ParseError(\n            f'Unable to parse entry header value with error: {exception!s}')\n\n      if self._debug:\n        self._DebugPrintValue('Entry data offset', f'0x{value_data_offset:08x}')\n\n        self._DebugPrintEntryHeader(entry_header)\n\n      value_data_offset += context.byte_size\n\n      entry_data_size = entry_header.data_size\n\n      shell_item_list = pyfwsi.item_list()\n      shell_item_list.copy_from_byte_stream(value_data[value_data_offset:])\n\n      for shell_item in iter(shell_item_list.items):\n        if self._debug:\n          self._DebugPrintShellItem(shell_item)\n\n      value_data_offset += entry_data_size\n\n      entry_footer, data_size = self._ParseEntryFooter(\n          value_data, value_data_offset)\n\n      value_data_offset += data_size\n\n      if self._debug:\n        self._DebugPrintText('\\n')\n\n      if entry_footer.sentinel == 2 and value_data_offset < value_data_size:\n        # TODO: determine the logic to this value.\n        while ord(value_data[value_data_offset]) != 0x00:\n          value_data_offset += 1\n        value_data_offset += 7\n\n        entry_footer, data_size = self._ParseEntryFooter(\n            value_data, value_data_offset)\n\n        value_data_offset += data_size\n\n        if self._debug:\n          self._DebugPrintText('\\n')\n\n    if value_data_offset < value_data_size:\n      self._DebugPrintValue(\n          'Trailing data offset', f'0x{value_data_offset:08x}')\n\n      self._DebugPrintData(\n          'Trailing data:', value_data[value_data_offset:])\n\n\nclass ProgramsCacheCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows program cache collector.\"\"\"\n\n  _STARTPAGE_KEY_PATH = (\n      'HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n      'Explorer\\\\StartPage')\n\n  _STARTPAGE2_KEY_PATH = (\n      'HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n      'Explorer\\\\StartPage2')\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a Windows program cache collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__(debug=debug)\n    self._parser = ProgramsCacheDataParser(\n        debug=debug, output_writer=output_writer)\n\n  def _CollectProgramsCacheFromValue(self, registry, key_path, value_name):\n    \"\"\"Collects Programs Cache from a Windows Registry value.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n      key_path (str): path of the Programs Cache key.\n      value_name (str): name of the Programs Cache value.\n\n    Returns:\n      bool: True if the Programs Cache information key was found, False if not.\n    \"\"\"\n    startpage_key = registry.GetKeyByPath(key_path)\n    if not startpage_key:\n      return False\n\n    value = startpage_key.GetValueByName(value_name)\n    if not value:\n      logging.warning(f'Missing {value_name:s} value in key: {key_path:s}')\n      return True\n\n    self._parser.Parse(value.data)\n\n    return True\n\n  def Collect(self, registry):  # pylint: disable=arguments-differ\n    \"\"\"Collects the Programs Cache information.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      bool: True if the Programs Cache information key was found, False if not.\n    \"\"\"\n    result = False\n\n    if self._CollectProgramsCacheFromValue(\n        registry, self._STARTPAGE_KEY_PATH, 'ProgramsCache'):\n      result = True\n\n    if self._CollectProgramsCacheFromValue(\n        registry, self._STARTPAGE2_KEY_PATH, 'ProgramsCache'):\n      result = True\n\n    if self._CollectProgramsCacheFromValue(\n        registry, self._STARTPAGE2_KEY_PATH, 'ProgramsCacheSMP'):\n      result = True\n\n    if self._CollectProgramsCacheFromValue(\n        registry, self._STARTPAGE2_KEY_PATH, 'ProgramsCacheTBP'):\n      result = True\n\n    return result\n"
  },
  {
    "path": "winregrc/programscache.yaml",
    "content": "# dtFabric format specification.\n---\nname: programcache\ntype: format\ndescription: Programs Cache format\n---\nname: uint8\ntype: integer\nattributes:\n  format: unsigned\n  size: 1\n  units: bytes\n---\nname: uint16\ntype: integer\nattributes:\n  format: unsigned\n  size: 2\n  units: bytes\n---\nname: uint32\ntype: integer\nattributes:\n  format: unsigned\n  size: 4\n  units: bytes\n---\nname: programscache_header\ntype: structure\nattributes:\n  byte_order: little-endian\nmembers:\n- name: format_version\n  data_type: uint32\n---\nname: programscache_header9\ntype: structure\nattributes:\n  byte_order: little-endian\nmembers:\n- name: unknown1\n  data_type: uint16\n---\nname: programscache_entry_header\ntype: structure\nattributes:\n  byte_order: little-endian\nmembers:\n- name: data_size\n  data_type: uint32\n---\nname: programscache_entry_footer\ntype: structure\nattributes:\n  byte_order: little-endian\nmembers:\n- name: sentinel\n  data_type: uint8\n"
  },
  {
    "path": "winregrc/sam.py",
    "content": "\"\"\"Security Accounts Manager (SAM) collector.\"\"\"\n\nimport pyfwnt\n\nfrom dfdatetime import filetime as dfdatetime_filetime\nfrom dfdatetime import semantic_time as dfdatetime_semantic_time\n\nfrom winregrc import data_format\nfrom winregrc import errors\nfrom winregrc import interface\n\n\nclass UserAccount:\n  \"\"\"User account.\n\n  Attributes:\n    account_expiration_time (dfdatetime.DateTimeValues): account expiration\n      date and time.\n    codepage (str): code page.\n    comment (str): comment.\n    full_name (str): full name.\n    last_login_time (dfdatetime.DateTimeValues): last log-in date and time.\n    last_password_failure_time (dfdatetime.DateTimeValues): last password\n        failure date and time.\n    last_password_set_time (dfdatetime.DateTimeValues): last password set\n        date and time.\n    name (str): name\n    number_of_logons (int): number of log-ons.\n    number_of_password_failures (int): number of password failures.\n    primary_gid (int): primary group identifier (GID).\n    rid (str): relative identifier (RID).\n    user_account_control_flags (int): user account control flags.\n    user_comment (str): user comment.\n    username (str): username.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes an user account.\"\"\"\n    super().__init__()\n    self.account_expiration_time = None\n    self.codepage = None\n    self.comment = None\n    self.full_name = None\n    self.last_login_time = None\n    self.last_password_failure_time = None\n    self.last_password_set_time = None\n    self.name = None\n    self.number_of_logons = None\n    self.number_of_password_failures = None\n    self.primary_gid = None\n    self.rid = None\n    self.user_account_control_flags = None\n    self.user_comment = None\n    self.username = None\n\n\nclass SecurityAccountManagerDataParser(data_format.BinaryDataFormat):\n  \"\"\"Security Accounts Manager (SAM) data parser.\"\"\"\n\n  _DEFINITION_FILE = 'sam.yaml'\n\n  _USER_INFORMATION_DESCRIPTORS = [\n      'security descriptor',\n      'username',\n      'full name',\n      'comment',\n      'user comment',\n      'unknown1',\n      'home directory',\n      'home directory connect',\n      'script path',\n      'profile path',\n      'workstations',\n      'hours allowed',\n      'unknown2',\n      'LM hash',\n      'NTLM hash',\n      'unknown3',\n      'unknown4']\n\n  _USER_ACCOUNT_CONTROL_FLAGS = {\n      0x00000001: 'USER_ACCOUNT_DISABLED',\n      0x00000002: 'USER_HOME_DIRECTORY_REQUIRED',\n      0x00000004: 'USER_PASSWORD_NOT_REQUIRED',\n      0x00000008: 'USER_TEMP_DUPLICATE_ACCOUNT',\n      0x00000010: 'USER_NORMAL_ACCOUNT',\n      0x00000020: 'USER_MNS_LOGON_ACCOUNT',\n      0x00000040: 'USER_INTERDOMAIN_TRUST_ACCOUNT',\n      0x00000080: 'USER_WORKSTATION_TRUST_ACCOUNT',\n      0x00000100: 'USER_SERVER_TRUST_ACCOUNT',\n      0x00000200: 'USER_DONT_EXPIRE_PASSWORD',\n      0x00000400: 'USER_ACCOUNT_AUTO_LOCKED',\n      0x00000800: 'USER_ENCRYPTED_TEXT_PASSWORD_ALLOWED',\n      0x00001000: 'USER_SMARTCARD_REQUIRED',\n      0x00002000: 'USER_TRUSTED_FOR_DELEGATION',\n      0x00004000: 'USER_NOT_DELEGATED',\n      0x00008000: 'USER_USE_DES_KEY_ONLY',\n      0x00010000: 'USER_DONT_REQUIRE_PREAUTH',\n      0x00020000: 'USER_PASSWORD_EXPIRED',\n      0x00040000: 'USER_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION',\n      0x00080000: 'USER_NO_AUTH_DATA_REQUIRED',\n      0x00100000: 'USER_PARTIAL_SECRETS_ACCOUNT',\n      0x00200000: 'USER_USE_AES_KEYS'}\n\n  _DEBUG_INFO_C_VALUE = [\n      ('format_version', 'Format version', '_FormatIntegerAsDecimal'),\n      ('unknown1', 'Unknown1', '_FormatIntegerAsHexadecimal2'),\n      ('unknown2', 'Unknown1', '_FormatIntegerAsHexadecimal4'),\n      ('security_descriptor_size', 'Security descriptor size',\n       '_FormatIntegerAsDecimal'),\n      ('unknown3', 'Unknown1', '_FormatIntegerAsHexadecimal2'),\n      ('unknown4', 'Unknown1', '_FormatIntegerAsHexadecimal2'),\n      ('security_descriptor', 'Security descriptor',\n       '_FormatSecurityDescriptor')]\n\n  _DEBUG_INFO_F_VALUE = [\n      ('major_version', 'Major version', '_FormatIntegerAsDecimal'),\n      ('minor_version', 'Minor version', '_FormatIntegerAsDecimal'),\n      ('unknown1', 'Unknown1', '_FormatIntegerAsHexadecimal8'),\n      ('last_login_time', 'Last login time', '_FormatIntegerAsFiletime'),\n      ('unknown2', 'Unknown2', '_FormatIntegerAsHexadecimal8'),\n      ('last_password_set_time', 'Last password set time',\n       '_FormatIntegerAsFiletime'),\n      ('account_expiration_time', 'Account expiration time',\n       '_FormatIntegerAsFiletime'),\n      ('last_password_failure_time', 'Last password failure time',\n       '_FormatIntegerAsFiletime'),\n      ('rid', 'Relative identifier (RID)', '_FormatIntegerAsDecimal'),\n      ('primary_gid', 'Primary group identifier (GID)',\n       '_FormatIntegerAsDecimal'),\n      ('user_account_control_flags', 'User account control flags',\n       '_FormatIntegerAsHexadecimal8'),\n      ('user_account_control_flags', None, '_FormatUserAccountControlFlags'),\n      ('country_code', 'Country code', '_FormatIntegerAsHexadecimal4'),\n      ('codepage', 'Codepage', '_FormatIntegerAsDecimal'),\n      ('number_of_password_failures', 'Number of password failures',\n       '_FormatIntegerAsDecimal'),\n      ('number_of_logons', 'Number of logons', '_FormatIntegerAsDecimal'),\n      ('unknown6', 'Unknown6', '_FormatIntegerAsHexadecimal8'),\n      ('unknown7', 'Unknown7', '_FormatIntegerAsHexadecimal8'),\n      ('unknown8', 'Unknown8', '_FormatIntegerAsHexadecimal8')]\n\n  def _DebugPrintUserInformationDescriptor(\n      self, index, descriptor, descriptor_data_offset, descriptor_data):\n    \"\"\"Prints an user information descriptor.\n\n    Args:\n      index (int): index of the user information descriptor.\n      descriptor (user_information_descriptor): user information descriptor.\n      descriptor_data_offset (int): offset of the descriptor data relative from\n          the start of the V value data.\n      descriptor_data (bytes): descriptor data.\n    \"\"\"\n    descriptor_index = index + 1\n    self._DebugPrintText(\n        f'User information descriptor: {descriptor_index:d}:\\n')\n\n    value_string = self._USER_INFORMATION_DESCRIPTORS[index]\n    self._DebugPrintValue('Description', value_string)\n\n    self._DebugPrintValue('Offset', (\n        f'0x{descriptor.offset:08x} (0x{descriptor_data_offset:08x})'))\n\n    self._DebugPrintDecimalValue('Size', descriptor.size)\n\n    self._DebugPrintValue('Unknown1', f'0x{descriptor.unknown1:08x}')\n\n    self._DebugPrintData('Data', descriptor_data)\n\n  # pylint: disable=no-member,using-constant-test\n\n  def _FormatSecurityDescriptor(self, security_descriptor_data):\n    \"\"\"Formats security descriptor.\n\n    Args:\n      security_descriptor_data (bytes): security descriptor data.\n\n    Returns:\n      str: formatted security descriptor.\n    \"\"\"\n    fwnt_descriptor = pyfwnt.security_descriptor()\n    fwnt_descriptor.copy_from_byte_stream(security_descriptor_data)\n\n    lines = []\n\n    if fwnt_descriptor.owner:\n      identifier_string = fwnt_descriptor.owner.get_string()\n      lines.append(f'\\tOwner: {identifier_string:s}')\n\n    if fwnt_descriptor.group:\n      identifier_string = fwnt_descriptor.group.get_string()\n      lines.append(f'\\tGroup: {identifier_string:s}')\n\n    # TODO: format SACL\n    # TODO: format DACL\n\n    lines.append('')\n    return '\\n'.join(lines)\n\n  # pylint: enable=no-member,using-constant-test\n\n  def _FormatUserAccountControlFlags(self, user_account_control_flags):\n    \"\"\"Formats user account control flags.\n\n    Args:\n      user_account_control_flags (int): user account control flags.\n\n    Returns:\n      str: formatted user account control flags.\n    \"\"\"\n    lines = []\n    if user_account_control_flags:\n      for flag, identifier in sorted(\n          self._USER_ACCOUNT_CONTROL_FLAGS.items()):\n        if flag & user_account_control_flags:\n          lines.append(f'\\t{identifier:s} (0x{flag:08x})')\n\n      lines.append('')\n\n    lines.append('')\n    return '\\n'.join(lines)\n\n  def ParseCValue(self, value_data):\n    \"\"\"Parses the C value data.\n\n    Args:\n      value_data (bytes): F value data.\n\n    Raises:\n      ParseError: if the value data could not be parsed.\n    \"\"\"\n    data_type_map = self._GetDataTypeMap('c_value')\n\n    try:\n      c_value = self._ReadStructureFromByteStream(\n          value_data, 0, data_type_map, 'C value')\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse C value with error: {exception!s}')\n\n    if self._debug:\n      self._DebugPrintStructureObject(c_value, self._DEBUG_INFO_C_VALUE)\n\n  def _ParseFiletime(self, filetime):\n    \"\"\"Parses a FILETIME timestamp value.\n\n    Args:\n      filetime (int): a FILETIME timestamp value.\n\n    Returns:\n      dfdatetime.DateTimeValues: date and time values.\n    \"\"\"\n    if filetime == 0:\n      return dfdatetime_semantic_time.SemanticTime(string='Not set')\n\n    if filetime == 0x7fffffffffffffff:\n      return dfdatetime_semantic_time.SemanticTime(string='Never')\n\n    return dfdatetime_filetime.Filetime(timestamp=filetime)\n\n  def ParseFValue(self, value_data, user_account):\n    \"\"\"Parses the F value data.\n\n    Args:\n      value_data (bytes): F value data.\n      user_account (UserAccount): user account.\n\n    Raises:\n      ParseError: if the value data could not be parsed.\n    \"\"\"\n    data_type_map = self._GetDataTypeMap('f_value')\n\n    try:\n      f_value = self._ReadStructureFromByteStream(\n          value_data, 0, data_type_map, 'F value')\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse F value with error: {exception!s}')\n\n    # TODO: change FILETIME timestamps into date time values.\n    # date_time = self._ParseFiletime(f_value.last_login_time)\n\n    user_account.last_login_time = f_value.last_login_time\n\n    user_account.last_password_set_time = f_value.last_password_set_time\n    user_account.account_expiration_time = f_value.account_expiration_time\n    user_account.last_password_failure_time = f_value.last_password_failure_time\n    user_account.rid = f_value.rid\n    user_account.primary_gid = f_value.primary_gid\n    user_account.user_account_control_flags = f_value.user_account_control_flags\n    user_account.codepage = f_value.codepage\n    user_account.number_of_password_failures = (\n        f_value.number_of_password_failures)\n    user_account.number_of_logons = f_value.number_of_logons\n\n    if self._debug:\n      self._DebugPrintStructureObject(f_value, self._DEBUG_INFO_F_VALUE)\n\n  def ParseVValue(self, value_data, user_account):\n    \"\"\"Parses the V value data.\n\n    Args:\n      value_data (bytes): V value data.\n      user_account (UserAccount): user account.\n\n    Raises:\n      ParseError: if the value data could not be parsed.\n    \"\"\"\n    data_type_map = self._GetDataTypeMap('v_value')\n\n    try:\n      v_value = self._ReadStructureFromByteStream(\n          value_data, 0, data_type_map, 'V value')\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse V value with error: {exception!s}')\n\n    for index in range(0, 17):\n      user_information_descriptor = v_value[index]\n\n      data_start_offset = user_information_descriptor.offset + 0xcc\n      data_end_offset = data_start_offset + user_information_descriptor.size\n      descriptor_data = value_data[data_start_offset:data_end_offset]\n\n      if self._debug:\n        self._DebugPrintUserInformationDescriptor(\n            index, user_information_descriptor, data_start_offset,\n            descriptor_data)\n\n      if index == 0:\n        if self._debug:\n          value_string = self._FormatSecurityDescriptor(descriptor_data)\n\n          self._DebugPrintText('Security descriptor:\\n')\n          self._DebugPrintText(value_string)\n          self._DebugPrintText('\\n')\n\n      elif index == 1:\n        user_account.username = descriptor_data.decode(\n            'utf-16-le').rstrip('\\x00')\n\n        if self._debug:\n          self._DebugPrintValue('Username', user_account.username)\n          self._DebugPrintText('\\n')\n\n      elif index == 2:\n        user_account.full_name = descriptor_data.decode(\n            'utf-16-le').rstrip('\\x00')\n\n        if self._debug:\n          self._DebugPrintValue('Full name', user_account.full_name)\n          self._DebugPrintText('\\n')\n\n      elif index == 3:\n        user_account.comment = descriptor_data.decode(\n            'utf-16-le').rstrip('\\x00')\n\n        if self._debug:\n          self._DebugPrintValue('Comment', user_account.comment)\n          self._DebugPrintText('\\n')\n\n      elif index == 4:\n        user_account.user_comment = descriptor_data.decode(\n            'utf-16-le').rstrip('\\x00')\n\n        if self._debug:\n          self._DebugPrintValue(\n              'User comment', user_account.user_comment)\n          self._DebugPrintText('\\n')\n\n    if self._debug:\n      self._DebugPrintText('\\n')\n\n\nclass SecurityAccountManagerCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Security Accounts Manager (SAM) collector.\n\n  Attributes:\n    user_accounts (list[UserAccount]): user accounts.\n  \"\"\"\n\n  _USERS_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\SAM\\\\SAM\\\\Domains\\\\Account\\\\Users')\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a Security Accounts Manager (SAM) collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__(debug=debug)\n    self._parser = SecurityAccountManagerDataParser(\n        debug=debug, output_writer=output_writer)\n\n    self.user_accounts = []\n\n  def Collect(self, registry):  # pylint: disable=arguments-differ\n    \"\"\"Collects the Security Accounts Manager (SAM) information.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      bool: True if the Security Accounts Manager (SAM) information key was\n          found, False if not.\n    \"\"\"\n    main_key = registry.GetKeyByPath('HKEY_LOCAL_MACHINE\\\\SAM\\\\SAM')\n    if not main_key:\n      return False\n\n    c_value = main_key.GetValueByName('C')\n    if c_value:\n      self._parser.ParseCValue(c_value.data)\n\n    users_key = registry.GetKeyByPath(self._USERS_KEY_PATH)\n    if not users_key:\n      return False\n\n    for subkey in users_key.GetSubkeys():\n      if subkey.name == 'Names':\n        continue\n\n      user_account = UserAccount()\n\n      f_value = subkey.GetValueByName('F')\n      if f_value:\n        self._parser.ParseFValue(f_value.data, user_account)\n\n      v_value = subkey.GetValueByName('V')\n      if v_value:\n        self._parser.ParseVValue(v_value.data, user_account)\n\n      self.user_accounts.append(user_account)\n\n    return True\n"
  },
  {
    "path": "winregrc/sam.yaml",
    "content": "# dtFabric format specification.\n---\nname: sam\ntype: format\ndescription: Security Accounts Manager (SAM) format\n---\nname: byte\ntype: integer\nattributes:\n  format: unsigned\n  size: 1\n  units: bytes\n---\nname: uint16\ntype: integer\nattributes:\n  format: unsigned\n  size: 2\n  units: bytes\n---\nname: uint32\ntype: integer\nattributes:\n  format: unsigned\n  size: 4\n  units: bytes\n---\nname: uint64\ntype: integer\nattributes:\n  format: unsigned\n  size: 8\n  units: bytes\n---\nname: c_value\ntype: structure\ndescription: Security Accounts Manager C value.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: format_version\n  data_type: uint16\n- name: unknown1\n  data_type: uint16\n- name: unknown2\n  data_type: uint32\n- name: security_descriptor_size\n  data_type: uint32\n- name: unknown3\n  data_type: uint16\n- name: unknown4\n  data_type: uint16\n- name: security_descriptor\n  type: stream\n  element_data_type: byte\n  elements_data_size: c_value.security_descriptor_size\n---\nname: f_value\ntype: structure\ndescription: Security Accounts Manager F value.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: major_version\n  data_type: uint16\n- name: minor_version\n  data_type: uint16\n- name: unknown1\n  data_type: uint32\n- name: last_login_time\n  data_type: uint64\n- name: unknown2\n  data_type: uint64\n- name: last_password_set_time\n  data_type: uint64\n- name: account_expiration_time\n  data_type: uint64\n- name: last_password_failure_time\n  data_type: uint64\n- name: rid\n  data_type: uint32\n- name: primary_gid\n  data_type: uint32\n- name: user_account_control_flags\n  data_type: uint32\n- name: country_code\n  data_type: uint16\n- name: codepage\n  data_type: uint16\n- name: number_of_password_failures\n  data_type: uint16\n- name: number_of_logons\n  data_type: uint16\n- name: unknown6\n  data_type: uint32\n- name: unknown7\n  data_type: uint32\n- name: unknown8\n  data_type: uint32\n---\nname: user_information_descriptor\ntype: structure\ndescription: Security Accounts Manager user information descriptor.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: offset\n  data_type: uint32\n- name: size\n  data_type: uint32\n- name: unknown1\n  data_type: uint32\n---\nname: v_value\ntype: sequence\ndescription: Security Accounts Manager V value.\nelement_data_type: user_information_descriptor\nnumber_of_elements: 17\n"
  },
  {
    "path": "winregrc/scripts/__init__.py",
    "content": ""
  },
  {
    "path": "winregrc/scripts/appcompatcache.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract Application Compatibility Cache information.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import appcompatcache\nfrom winregrc import output_writers\nfrom winregrc import volume_scanner\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract AppCompatCache information.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts Application Compatibility Cache information from '\n      'a SYSTEM Registry file.'))\n\n  argument_parser.add_argument(\n      '--all', dest='all_control_sets', action='store_true', default=False,\n      help=(\n          'Process all control sets instead of only the current control set.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SYSTEM Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  output_writer = output_writers.StdoutOutputWriter()\n\n  if not output_writer.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    collector_object = appcompatcache.AppCompatCacheCollector(\n        debug=options.debug, output_writer=output_writer)\n\n    # TODO: change collector to generate AppCompatCacheCachedEntry\n    has_results = collector_object.Collect(\n        scanner.registry, all_control_sets=options.all_control_sets)\n    if has_results:\n      for cached_entry in collector_object.cached_entries:\n        output_writer.WriteFiletimeValue(\n            'Last modification time', cached_entry.last_modification_time)\n        output_writer.WriteValue('Path', cached_entry.path)\n        output_writer.WriteText('\\n')\n\n  finally:\n    output_writer.Close()\n\n  if not has_results:\n    print('No application compatibility cache entries found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/application_identifiers.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract Windows application identifiers (AppID).\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import application_identifiers\nfrom winregrc import output_writers\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def WriteApplicationIdentifier(self, application_identifier):\n    \"\"\"Writes an application identifier to the output.\n\n    Args:\n      application_identifier (ApplicationIdentifier): application identifier.\n    \"\"\"\n    self.WriteValue(\n        application_identifier.guid, application_identifier.description)\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract Windows AppIDs.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the Windows application identifiers (AppID) from the Windows '\n      'Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  collector_object = application_identifiers.ApplicationIdentifiersCollector(\n      debug=options.debug)\n\n  output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    has_results = False\n    for application_identifier in collector_object.Collect(scanner.registry):\n      output_writer_object.WriteApplicationIdentifier(application_identifier)\n      has_results = True\n\n  finally:\n    output_writer_object.Close()\n\n  if not has_results:\n    print('No Windows application identifiers (AppID) found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/cached_credentials.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract cached credentials.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import cached_credentials\nfrom winregrc import output_writers\nfrom winregrc import volume_scanner\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract cached credentials.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the cached credentials from a SECURITY Registry file.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False, help=(\n          'enable debug output.'))\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None, help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SECURITY and SYSTEM Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  output_writer = output_writers.StdoutOutputWriter()\n\n  if not output_writer.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  if scanner.IsSingleFileRegistry():\n    print('Both SECURITY and SYSYEM Registry files are required.')\n    print('')\n    return 1\n\n  # TODO: map collector to available Registry keys.\n  collector_object = cached_credentials.CachedCredentialsKeyCollector(\n      debug=options.debug, output_writer=output_writer)\n\n  result = collector_object.Collect(scanner.registry)\n  if not result:\n    print('No Cache key found.')\n  else:\n    output_writer.WriteText('\\n')\n\n  output_writer.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/catalog.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract a catalog of Windows Registry keys and values.\"\"\"\n\nimport argparse\nimport logging\nimport re\nimport sys\n\nfrom dfwinreg import creg as dfwinreg_creg\nfrom dfwinreg import regf as dfwinreg_regf\nfrom dfwinreg import registry as dfwinreg_registry\n\nfrom winregrc import catalog\nfrom winregrc import output_writers\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def WriteKeyPath(self, key_path):\n    \"\"\"Writes a key path to the output.\n\n    Args:\n      key_path (str): key path.\n    \"\"\"\n    self.WriteText(f'{key_path:s}\\n')\n\n  def WriteValueDescriptor(self, value_name, value_data_type):\n    \"\"\"Writes a value descriptor to the output.\n\n    Args:\n      value_name (str): name of the value.\n      value_data_type (str): data type of the value.\n    \"\"\"\n    self.WriteText(f'\\t{value_name:s}\\t{value_data_type:s}\\n')\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract Windows Registry catalogs.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts a catalog of Windows Registry keys and values.'))\n\n  argument_parser.add_argument(\n      '--group_keys', '--group-keys', dest='group_keys', action='store_true',\n      default=False, help='Group keys with similar values.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help='path of a Windows Registry file.')\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  with open(options.source, 'rb') as file_object:\n    try:\n      registry_file = dfwinreg_regf.REGFWinRegistryFile()\n\n      registry_file.Open(file_object)\n    except OSError:\n      registry_file = None\n\n    if not registry_file:\n      try:\n        registry_file = dfwinreg_creg.CREGWinRegistryFile()\n\n        registry_file.Open(file_object)\n      except OSError:\n        registry_file = None\n\n    if not registry_file:\n      print('Unable to open Windows Registry file.')\n      return 1\n\n    # Using dfWinReg to determine Windows native key paths if available.\n    registry = dfwinreg_registry.WinRegistry()\n\n    key_path_prefix = registry.GetRegistryFileMapping(registry_file)\n    registry_file.SetKeyPathPrefix(key_path_prefix)\n\n    root_key = registry_file.GetRootKey()\n\n    output_writer_object = StdoutWriter()\n\n    if not output_writer_object.Open():\n      print('Unable to open output writer.')\n      print('')\n      return 1\n\n    collector_object = catalog.CatalogCollector(group_keys=options.group_keys)\n\n    def AlphanumericCompare(key):\n      return (int(text) if text.isdigit() else text.lower()\n              for text in re.split('([0-9]+)', key[0]))\n\n    try:\n      has_results = False\n      for key_descriptor in collector_object.Collect(root_key):\n        output_writer_object.WriteKeyPath(key_descriptor.key_path)\n\n        for key_path in key_descriptor.grouped_key_paths:\n          output_writer_object.WriteKeyPath(key_path)\n\n        for value_name, data_type_string in sorted(\n            key_descriptor.value_descriptors, key=AlphanumericCompare):\n          output_writer_object.WriteValueDescriptor(\n              value_name, data_type_string)\n\n        if options.group_keys:\n          output_writer_object.WriteText('\\n')\n\n        has_results = True\n\n    finally:\n      output_writer_object.Close()\n\n  if not has_results:\n    print('No keys and values found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/controlpanel_items.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract Windows control panel items from the Windows Registry.\"\"\"\n\nimport argparse\nimport logging\nimport sys\nimport yaml\n\nfrom winregrc import controlpanel_items\nfrom winregrc import output_writers\nfrom winregrc import versions\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  _WINDOWS_VERSIONS_KEY_FUNCTION = versions.WindowsVersions.KeyFunction\n\n  def WriteHeader(self):\n    \"\"\"Writes the header to stdout.\"\"\"\n    print('# winreg-kb controlpanel items definitions')\n\n  def WriteKnownFolder(self, control_panel_item, windows_versions):\n    \"\"\"Writes the control panel item to stdout.\n\n    Args:\n      control_panel_item (KnownFolder): the control panel item.\n      windows_versions (list[str]): the Windows versions.\n    \"\"\"\n    print('---')\n    print(f'identifier: \"{control_panel_item.identifier:s}\"')\n    if control_panel_item.module_name:\n      print(f'module_name: \"{control_panel_item.module_name:s}\"')\n\n    if control_panel_item.alternate_module_names:\n      alternate_module_names = ', '.join([\n          f'\"{name:s}\"' for name in control_panel_item.alternate_module_names])\n      print(f'alternate_module_names: [{alternate_module_names:s}]')\n\n    windows_versions = ', '.join([f'\"{version:s}\"' for version in sorted(\n        windows_versions, key=self._WINDOWS_VERSIONS_KEY_FUNCTION)])\n    print(f'windows_versions: [{windows_versions:s}]')\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract control panel items.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts Windows control panel items from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      '-w', '--windows_version', '--windows-version', dest='windows_version',\n      action='store', metavar='VERSION', default=None,\n      help='string that identifies the Windows version.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  try:\n    with open(options.source, 'r', encoding='utf-8') as file_object:\n      source_definitions = list(yaml.safe_load_all(file_object))\n\n  except (SyntaxError, UnicodeDecodeError, yaml.parser.ParserError):\n    source_definitions = [{\n        'source': options.source, 'windows_version': options.windows_version}]\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.username = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  control_panel_item_per_identifier = {}\n  windows_versions_per_control_panel_item = {}\n\n  for source_definition in source_definitions:\n    source_path = source_definition['source']\n    logging.info(f'Processing: {source_path:s}')\n\n    if not scanner.ScanForWindowsVolume(\n        source_path, options=volume_scanner_options):\n      logging.error((\n          f'Unable to retrieve the volume with the Windows directory from: '\n          f'{source_path:s}.'))\n      continue\n\n    collector_object = controlpanel_items.ControlPanelItemsCollector(\n        debug=options.debug)\n\n    # TODO: determine Windows version from source.\n    windows_version = source_definition['windows_version']\n\n    for item in collector_object.Collect(scanner.registry):\n      # TODO: compare attributes with existing item.\n      existing_item = control_panel_item_per_identifier.get(\n          item.identifier, None)\n\n      # Ignore a module name that is the same as the identifier.\n      if (item.module_name and\n          item.module_name.lower() == item.identifier):\n        item.module_name = None\n\n      if not existing_item:\n        control_panel_item_per_identifier[item.identifier] = item\n      elif not existing_item.module_name:\n        existing_item.module_name = item.module_name\n      elif (item.module_name and\n            item.module_name != existing_item.module_name and\n            item.module_name not in existing_item.alternate_module_names):\n        existing_item.alternate_module_names.append(item.module_name)\n\n      if item.identifier not in (\n          windows_versions_per_control_panel_item):\n        windows_versions_per_control_panel_item[item.identifier] = []\n\n      if windows_version:\n        windows_versions_per_control_panel_item[item.identifier].append(\n            windows_version)\n\n  if not control_panel_item_per_identifier:\n    print('No control panel items found.')\n    return 0\n\n  output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    output_writer_object.WriteHeader()\n    for identifier, windows_versions in sorted(\n        windows_versions_per_control_panel_item.items()):\n      control_panel_item = control_panel_item_per_identifier[identifier]\n      output_writer_object.WriteKnownFolder(\n          control_panel_item, windows_versions)\n\n  finally:\n    output_writer_object.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/delegatefolders.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract Windows delegate folders from the Windows Registry.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import delegatefolders\nfrom winregrc import output_writers\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def WriteDelegateFolder(self, delegate_folder):\n    \"\"\"Writes a delegate folder to the output.\n\n    Args:\n      delegate_folder (DelegateFolder): delegate folder.\n    \"\"\"\n    self.WriteValue('Identifier', delegate_folder.identifier)\n    self.WriteValue('Name', delegate_folder.name)\n    self.WriteValue('Namespace', delegate_folder.namespace)\n\n    self.WriteText('\\n')\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract Windows delegate folders.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts Windows delegate folders from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of a '\n          'storage media image containing the C:\\\\Windows directory, or the '\n          'path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  collector_object = delegatefolders.DelegateFoldersCollector(\n      debug=options.debug)\n\n  output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    has_results = False\n    for delegate_folder in collector_object.Collect(scanner.registry):\n      output_writer_object.WriteDelegateFolder(delegate_folder)\n      has_results = True\n\n  finally:\n    output_writer_object.Close()\n\n  if not has_results:\n    print('No Windows delegate folders found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/environment_variables.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract environment variables.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import environment_variables\nfrom winregrc import output_writers\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def WriteEnvironmentVariable(self, environment_variable):\n    \"\"\"Writes an environment variable to the output.\n\n    Args:\n      environment_variable (EnvironmentVariable): environment variable.\n    \"\"\"\n    self.WriteValue(environment_variable.name, environment_variable.value)\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract environment variables.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the environment variables from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  collector_object = environment_variables.EnvironmentVariablesCollector(\n      debug=options.debug)\n\n  output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    has_results = False\n    for environment_variable in sorted(\n        collector_object.Collect(scanner.registry),\n        key=lambda environment_variable: environment_variable.name):\n      output_writer_object.WriteEnvironmentVariable(environment_variable)\n      has_results = True\n\n  finally:\n    output_writer_object.Close()\n\n  if not has_results:\n    print('No environment variables found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/eventlog_providers.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract Windows Event Log providers from the Windows Registry.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import eventlog_providers\nfrom winregrc import output_writers\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def WriteEventLogProvider(self, eventlog_provider):\n    \"\"\"Writes a Event Log provider to the output.\n\n    Args:\n      eventlog_provider (EventLogProvider): Event Log provider.\n    \"\"\"\n    if eventlog_provider.name:\n      self.WriteText(f'Name\\t\\t\\t\\t: {eventlog_provider.name:s}\\n')\n\n    if eventlog_provider.identifier:\n      self.WriteText(f'Identifier\\t\\t\\t: {eventlog_provider.identifier:s}\\n')\n\n    if eventlog_provider.additional_identifier:\n      self.WriteText((\n          f'Additional identifier\\t\\t: '\n          f'{eventlog_provider.additional_identifier:s}\\n'))\n\n    for index, log_type in enumerate(sorted(eventlog_provider.log_types)):\n      if index == 0:\n        text = f'Log type(s)\\t\\t\\t: {log_type:s}\\n'\n      else:\n        text = f'\\t\\t\\t\\t: {log_type:s}\\n'\n      self.WriteText(text)\n\n    for index, log_source in enumerate(sorted(eventlog_provider.log_sources)):\n      if index == 0:\n        text = f'Log source(s)\\t\\t\\t: {log_source:s}\\n'\n      else:\n        text = f'\\t\\t\\t\\t: {log_source:s}\\n'\n      self.WriteText(text)\n\n    for index, path in enumerate(sorted((\n        eventlog_provider.category_message_files))):\n      if index == 0:\n        text = f'Category message file(s)\\t: {path:s}\\n'\n      else:\n        text = f'\\t\\t\\t\\t: {path:s}\\n'\n      self.WriteText(text)\n\n    for index, path in enumerate(sorted((\n        eventlog_provider.event_message_files))):\n      if index == 0:\n        text = f'Event message file(s)\\t\\t: {path:s}\\n'\n      else:\n        text = f'\\t\\t\\t\\t: {path:s}\\n'\n      self.WriteText(text)\n\n    for index, path in enumerate(sorted((\n        eventlog_provider.parameter_message_files))):\n      if index == 0:\n        text = f'Parameter message file(s)\\t: {path:s}\\n'\n      else:\n        text = f'\\t\\t\\t\\t: {path:s}\\n'\n      self.WriteText(text)\n\n    self.WriteText('\\n')\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract Event Log providers.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts Windows Event Log providers from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=('path of the volume containing C:\\\\Windows, the filename of '\n            'a storage media image containing the C:\\\\Windows directory, '\n            'or the path of a SOFTWARE or SYSTEM Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  collector_object = eventlog_providers.EventLogProvidersCollector(\n      debug=options.debug)\n\n  output_writer_object = StdoutWriter()\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    has_results = False\n    for eventlog_provider in collector_object.Collect(scanner.registry):\n      output_writer_object.WriteEventLogProvider(eventlog_provider)\n      has_results = True\n\n  finally:\n    output_writer_object.Close()\n\n  if not has_results:\n    print('No Windows Event Log providers found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/knownfolders.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract Windows known folders from the Windows Registry.\"\"\"\n\nimport argparse\nimport logging\nimport sys\nimport yaml\n\nfrom winregrc import knownfolders\nfrom winregrc import output_writers\nfrom winregrc import versions\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  _WINDOWS_VERSIONS_KEY_FUNCTION = versions.WindowsVersions.KeyFunction\n\n  def WriteHeader(self):\n    \"\"\"Writes the header to stdout.\"\"\"\n    print('# winreg-kb knownfolder definitions')\n\n  def WriteKnownFolder(self, known_folder, windows_versions):\n    \"\"\"Writes the known folder to stdout.\n\n    Args:\n      known_folder (KnownFolder): the known folder.\n      windows_versions (list[str]): the Windows versions.\n    \"\"\"\n    print('---')\n    print(f'identifier: \"{known_folder.identifier:s}\"')\n    # TODO: escape \\ in display name\n    print(f'display_name: \"{known_folder.display_name:s}\"')\n\n    if known_folder.localized_display_name:\n      # TODO: escape \\ in localized display_name\n      print(\n          f'localized_display_name: \"{known_folder.localized_display_name:s}\"')\n\n    if known_folder.alternate_display_names:\n      alternate_display_names = ', '.join([\n          f'\"{name:s}\"' for name in known_folder.alternate_display_names])\n      print(f'alternate_display_names: [{alternate_display_names:s}]')\n\n    windows_versions = ', '.join([f'\"{version:s}\"' for version in sorted(\n        windows_versions, key=self._WINDOWS_VERSIONS_KEY_FUNCTION)])\n    print(f'windows_versions: [{windows_versions:s}]')\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract known folders.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts Windows known folders from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      '-w', '--windows_version', '--windows-version', dest='windows_version',\n      action='store', metavar='VERSION', default=None,\n      help='string that identifies the Windows version.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  try:\n    with open(options.source, 'r', encoding='utf-8') as file_object:\n      source_definitions = list(yaml.safe_load_all(file_object))\n\n  except (SyntaxError, UnicodeDecodeError, yaml.parser.ParserError):\n    source_definitions = [{\n        'source': options.source, 'windows_version': options.windows_version}]\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.username = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  known_folder_per_identifier = {}\n  windows_versions_per_known_folder = {}\n\n  for source_definition in source_definitions:\n    source_path = source_definition['source']\n    logging.info(f'Processing: {source_path:s}')\n\n    if not scanner.ScanForWindowsVolume(\n        source_path, options=volume_scanner_options):\n      logging.error((\n          f'Unable to retrieve the volume with the Windows directory from: '\n          f'{source_path:s}.'))\n      continue\n\n    collector_object = knownfolders.KnownFoldersCollector(debug=options.debug)\n\n    # TODO: determine Windows version from source.\n    windows_version = source_definition['windows_version']\n\n    for known_folder in collector_object.Collect(scanner.registry):\n      # TODO: compare attributes with existing with known folder.\n      existing_known_folder = known_folder_per_identifier.get(\n          known_folder.identifier, None)\n\n      if not existing_known_folder:\n        known_folder_per_identifier[known_folder.identifier] = known_folder\n      elif not existing_known_folder.display_name:\n        existing_known_folder.display_name = known_folder.display_name\n      elif (known_folder.display_name and\n            known_folder.display_name != existing_known_folder.display_name and\n            known_folder.display_name not in (\n                existing_known_folder.alternate_display_names)):\n        existing_known_folder.alternate_display_names.append(\n            known_folder.display_name)\n\n      if known_folder.identifier not in windows_versions_per_known_folder:\n        windows_versions_per_known_folder[known_folder.identifier] = []\n\n      if windows_version:\n        windows_versions_per_known_folder[known_folder.identifier].append(\n            windows_version)\n\n  if not known_folder_per_identifier:\n    print('No known folders found.')\n    return 0\n\n  output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    output_writer_object.WriteHeader()\n    for identifier, windows_versions in sorted(\n        windows_versions_per_known_folder.items()):\n      known_folder = known_folder_per_identifier[identifier]\n      output_writer_object.WriteKnownFolder(known_folder, windows_versions)\n\n  finally:\n    output_writer_object.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/mounted_devices.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract Windows mounted devices.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import mounted_devices\nfrom winregrc import output_writers\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def WriteMountedDevice(self, mounted_device):\n    \"\"\"Writes a mounted device to the output.\n\n    Args:\n      mounted_device (MountedDevice): mounted device.\n    \"\"\"\n    self.WriteText(f'Identifier\\t\\t\\t: {mounted_device.identifier:s}\\n')\n\n    if mounted_device.disk_identity:\n      self.WriteText(\n          f'MBR disk identity\\t\\t: 0x{mounted_device.disk_identity:08x}\\n')\n      self.WriteText((\n          f'MBR partition offset\\t\\t: {mounted_device.partition_offset:d} '\n          f'(0x{mounted_device.partition_offset:08x})\\n'))\n\n    elif mounted_device.partition_identifier:\n      self.WriteText((\n          f'GPT partition identifier\\t: '\n          f'{mounted_device.partition_identifier!s}\\n'))\n\n    elif mounted_device.device:\n      self.WriteText(f'Device\\t\\t\\t\\t: {mounted_device.device:s}\\n')\n\n    self.WriteText('\\n')\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract Windows mounted devices.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts Windows mounted devices from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  collector_object = mounted_devices.MountedDevicesCollector(\n      debug=options.debug)\n\n  output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    has_results = False\n    for mounted_device in collector_object.Collect(scanner.registry):\n      output_writer_object.WriteMountedDevice(mounted_device)\n      has_results = True\n\n  finally:\n    output_writer_object.Close()\n\n  if not has_results:\n    print('No Windows mounted devices found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/mru.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract Most Recently Used (MRU) information.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.lib import errors as dfvfs_errors\n\nimport pyfwps\nimport pyfwsi\n\nfrom winregrc import mru\nfrom winregrc import output_writers\nfrom winregrc import shell_property_keys\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def _WritePropertyStore(self, fwps_store):\n    \"\"\"Writes a property store to stdout.\n\n    Args:\n      fwps_store (pyfwps.store): property store.\n\n    Raises:\n      RuntimeError: if a property value type is not supported.\n    \"\"\"\n    for fwps_set in iter(fwps_store.sets):\n      for fwps_record in iter(fwps_set.records):\n        if fwps_record.value_type == 0x0001:\n          value_string = '<VT_NULL>'\n        elif fwps_record.value_type in (0x0003, 0x0013, 0x0014, 0x0015):\n          value_string = str(fwps_record.get_data_as_integer())\n        elif fwps_record.value_type in (0x0008, 0x001e, 0x001f):\n          value_string = fwps_record.get_data_as_string()\n        elif fwps_record.value_type == 0x000b:\n          value_string = str(fwps_record.get_data_as_boolean())\n        elif fwps_record.value_type == 0x0040:\n          filetime = fwps_record.get_data_as_integer()\n          value_string = self._FormatFiletimeValue(filetime)\n        elif fwps_record.value_type == 0x0042:\n          # TODO: add support\n          value_string = '<VT_STREAM>'\n        elif fwps_record.value_type == 0x0048:\n          value_string = fwps_record.get_data_as_guid()\n        elif fwps_record.value_type & 0xf000 == 0x1000:\n          # TODO: add support\n          value_string = '<VT_VECTOR>'\n        else:\n          raise RuntimeError(\n              f'Unsupported value type: 0x{fwps_record.value_type:04x}')\n\n        if fwps_record.entry_name:\n          entry_string = fwps_record.entry_name\n        else:\n          entry_string = f'{fwps_record.entry_type:d}'\n\n        property_key = f'{{{fwps_set.identifier:s}}}/{entry_string:s}'\n        shell_property_key = shell_property_keys.SHELL_PROPERTY_KEYS.get(\n            property_key, 'Unknown')\n        self.WriteText(\n            f'\\tProperty: {property_key:s} ({shell_property_key:s})\\n')\n\n        self.WriteValue(\n            f'\\t\\tValue (0x{fwps_record.value_type:04x})', value_string)\n\n  def _WriteShellItem(self, fwsi_item):\n    \"\"\"Writes a shell item to stdout.\n\n    Args:\n      fwsi_item (pyfwsi.item): Shell item.\n    \"\"\"\n    if isinstance(fwsi_item, pyfwsi.compressed_folder):\n      shell_item_type = 'Compressed Folder'\n    elif isinstance(fwsi_item, pyfwsi.control_panel_category):\n      shell_item_type = 'Control Panel Category'\n    elif isinstance(fwsi_item, pyfwsi.control_panel_item):\n      shell_item_type = 'Control Panel Item'\n    elif isinstance(fwsi_item, pyfwsi.file_entry):\n      shell_item_type = 'File Entry'\n    elif isinstance(fwsi_item, pyfwsi.network_location):\n      shell_item_type = 'Network Location'\n    elif isinstance(fwsi_item, pyfwsi.root_folder):\n      shell_item_type = 'Root Folder'\n    elif isinstance(fwsi_item, pyfwsi.users_property_view):\n      shell_item_type = 'Users Property View'\n    elif isinstance(fwsi_item, pyfwsi.volume):\n      shell_item_type = 'Volume'\n    else:\n      shell_item_type = f'Unknown (0x{fwsi_item.class_type:02x})'\n\n    self.WriteValue('\\tItem type', shell_item_type)\n\n    if fwsi_item.delegate_folder_identifier:\n      self.WriteValue(\n          '\\tDelegate folder', fwsi_item.delegate_folder_identifier)\n\n    if isinstance(fwsi_item, pyfwsi.compressed_folder):\n      self._WriteShellItemCompressedFolder(fwsi_item)\n\n    elif isinstance(fwsi_item, pyfwsi.control_panel_category):\n      self._WriteShellItemControlPanelCategory(fwsi_item)\n\n    elif isinstance(fwsi_item, pyfwsi.control_panel_item):\n      self._WriteShellItemControlPanelItem(fwsi_item)\n\n    elif isinstance(fwsi_item, pyfwsi.file_entry):\n      self._WriteShellItemFileEntry(fwsi_item)\n\n    elif isinstance(fwsi_item, pyfwsi.network_location):\n      self._WriteShellItemNetworkLocation(fwsi_item)\n\n    elif isinstance(fwsi_item, pyfwsi.root_folder):\n      self.WriteValue(\n          '\\tRoot shell folder identifier', fwsi_item.shell_folder_identifier)\n\n    elif isinstance(fwsi_item, pyfwsi.users_property_view):\n      self._WriteShellItemUsersPropertyView(fwsi_item)\n\n    elif isinstance(fwsi_item, pyfwsi.volume):\n      self._WriteShellItemVolume(fwsi_item)\n\n    if fwsi_item.number_of_extension_blocks:\n      self.WriteValue(\n          '\\tNumber of extension blocks',\n          f'{fwsi_item.number_of_extension_blocks:d}')\n\n      for index, extension_block in enumerate(fwsi_item.extension_blocks):\n        display_index = index + 1\n        self.WriteText(f'Extension block: {display_index:d}\\n')\n\n        # TODO: print human readable description of signature\n        self.WriteValue('\\tSignature', f'0x{extension_block.signature:04x}')\n\n        if isinstance(extension_block, pyfwsi.file_entry_extension):\n          fat_date_time = extension_block.get_creation_time_as_integer()\n          date_time_string = self._FormatFATDateTimeValue(fat_date_time)\n          self.WriteValue('\\tCreation time', date_time_string)\n\n          fat_date_time = extension_block.get_access_time_as_integer()\n          date_time_string = self._FormatFATDateTimeValue(fat_date_time)\n          self.WriteValue('\\tAccess time', date_time_string)\n\n          self.WriteValue('\\tLong name', extension_block.long_name)\n\n          if extension_block.localized_name:\n            self.WriteValue(\n                '\\tLocalized name', extension_block.localized_name)\n\n          file_reference = extension_block.file_reference\n          if file_reference is not None:\n            if file_reference > 0x1000000000000:\n              mft_entry = file_reference & 0xffffffffffff\n              sequence_number = file_reference >> 48\n              file_reference = f'{mft_entry:d}-{sequence_number:d}'\n            else:\n              file_reference = f'0x{file_reference:04x}'\n\n            self.WriteValue('\\tFile reference', file_reference)\n\n        # TODO: add support for other extension blocks\n\n    self.WriteText('\\n')\n\n  def _WriteShellItemCompressedFolder(self, fwsi_item):\n    \"\"\"Writes a compressed folder shell item to stdout.\n\n    Args:\n      fwsi_item (pyfwsi.compressed_folder): compressed folder shell item.\n    \"\"\"\n    self.WriteValue('\\tName', fwsi_item.name)\n\n  def _WriteShellItemControlPanelCategory(self, fwsi_item):\n    \"\"\"Writes a control panel category shell item to stdout.\n\n    Args:\n      fwsi_item (pyfwsi.control_panel_category): control panel category shell\n          item.\n    \"\"\"\n    self.WriteValue(\n        '\\tControl panel category identifier', f'{fwsi_item.identifier:d}')\n\n  def _WriteShellItemControlPanelItem(self, fwsi_item):\n    \"\"\"Writes a control panel item shell item to stdout.\n\n    Args:\n      fwsi_item (pyfwsi.control_panel_item): control panel item shell item.\n    \"\"\"\n    self.WriteValue('\\tControl panel item identifier', fwsi_item.identifier)\n\n  def _WriteShellItemFileEntry(self, fwsi_item):\n    \"\"\"Writes a file entry shell item to stdout.\n\n    Args:\n      fwsi_item (pyfwsi.file_entry): File entry shell item.\n    \"\"\"\n    self.WriteValue('\\tFile size', f'{fwsi_item.file_size:d}')\n\n    fat_date_time = fwsi_item.get_modification_time_as_integer()\n    date_time_string = self._FormatFATDateTimeValue(fat_date_time)\n    self.WriteValue('\\tModification time', date_time_string)\n\n    self.WriteValue(\n        '\\tFile attribute flags',\n        f'0x08{fwsi_item.file_attribute_flags:08x}')\n\n    self.WriteValue('\\tName', fwsi_item.name)\n\n  def _WriteShellItemNetworkLocation(self, fwsi_item):\n    \"\"\"Writes a network location shell item to stdout.\n\n    Args:\n      fwsi_item (pyfwsi.network_location): network location shell item.\n    \"\"\"\n    self.WriteValue('\\tNetwork location', fwsi_item.location)\n\n    if fwsi_item.description:\n      self.WriteValue('\\tDescription', fwsi_item.description)\n\n    if fwsi_item.comments:\n      self.WriteValue('\\tComments', fwsi_item.comments)\n\n  def _WriteShellItemUsersPropertyView(self, fwsi_item):\n    \"\"\"Writes an users property view item to stdout.\n\n    Args:\n      fwsi_item (pyfwsi.users_property_view): users property view shell item.\n    \"\"\"\n    if fwsi_item.property_store_data:\n      fwps_store = pyfwps.store()\n      fwps_store.copy_from_byte_stream(fwsi_item.property_store_data)\n\n      self._WritePropertyStore(fwps_store)\n\n  def _WriteShellItemVolume(self, fwsi_item):\n    \"\"\"Writes a volume shell item to stdout.\n\n    Args:\n      fwsi_item (pyfwsi.volume): volume shell item.\n    \"\"\"\n    if fwsi_item.name:\n      self.WriteValue('\\tVolume name', fwsi_item.name)\n\n    if fwsi_item.identifier:\n      self.WriteValue('\\tVolume identifier', fwsi_item.identifier)\n\n    if fwsi_item.shell_folder_identifier:\n      self.WriteValue(\n          '\\tVolume shell folder identifier',\n          fwsi_item.shell_folder_identifier)\n\n  def WriteShellItem(self, fwsi_item):\n    \"\"\"Writes a shell item to stdout.\n\n    Args:\n      fwsi_item (pyfwsi.item): Shell item.\n    \"\"\"\n    self.WriteText('Shell item:\\n')\n    self._WriteShellItem(fwsi_item)\n\n  def WriteShellItemList(self, fwsi_item_list):\n    \"\"\"Writes a shell item list to stdout.\n\n    Args:\n      fwsi_item_list (pyfwsi.item_list): Shell item list.\n    \"\"\"\n    self.WriteText('Shell item list:\\n')\n    self.WriteValue('\\tNumber of items', fwsi_item_list.number_of_items)\n    self.WriteText('\\n')\n\n    for item_index, fwsi_item in enumerate(fwsi_item_list.items):\n      display_item_index = item_index + 1\n      self.WriteText(f'Shell item: {display_item_index:d}\\n')\n\n      self._WriteShellItem(fwsi_item)\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract Most Recently Used information.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts Most Recently Used information from a NTUSER.DAT Registry '\n      'file.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      '-u', '--username', dest='username', action='store', metavar='USERNAME',\n      default=None, help='username within a storage media image.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a NTUSER.DAT or UsrClass.dat Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  output_writer = StdoutWriter()\n\n  if not output_writer.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.username = options.username\n  volume_scanner_options.volumes = ['none']\n\n  try:\n    result = scanner.ScanForWindowsVolume(\n        options.source, options=volume_scanner_options)\n\n  except dfvfs_errors.ScannerError as exception:\n    print(f'[ERROR] {exception!s}', file=sys.stderr)\n    print('')\n    return 1\n\n  except KeyboardInterrupt:\n    print('Aborted by user.', file=sys.stderr)\n    print('')\n    return 1\n\n  if not result:\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  collector_object = mru.MostRecentlyUsedCollector(\n      debug=options.debug, output_writer=output_writer)\n\n  # TODO: change collector to generate MostRecentlyUsedEntry\n  result = collector_object.Collect(scanner.registry)\n  if not result:\n    print('No Most Recently Used key found.')\n    return 0\n\n  for mru_entry in collector_object.mru_entries:\n    output_writer.WriteValue('Key path', mru_entry.key_path)\n    output_writer.WriteValue('Value name', mru_entry.value_name)\n\n    if mru_entry.string:\n      output_writer.WriteValue('String', mru_entry.string)\n      output_writer.WriteText('\\n')\n\n    if mru_entry.shell_item_data:\n      fwsi_item = pyfwsi.item()\n      fwsi_item.copy_from_byte_stream(mru_entry.shell_item_data)\n\n      output_writer.WriteShellItem(fwsi_item)\n\n    elif mru_entry.shell_item_list_data:\n      shell_item_list = pyfwsi.item_list()\n      shell_item_list.copy_from_byte_stream(mru_entry.shell_item_list_data)\n\n      output_writer.WriteShellItemList(shell_item_list)\n\n  output_writer.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/msie_zone_info.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract MSIE zone information.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import msie_zone_info\nfrom winregrc import output_writers\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  _DEFAULT_ZONE_NAMES = {\n      '0': 'My Computer',\n      '1': 'Local Intranet',\n      '2': 'Trusted sites',\n      '3': 'Internet',\n      '4': 'Restricted sites'}\n\n  # Sources:\n  # http://support.microsoft.com/kb/182569\n  # http://technet.microsoft.com/en-us/library/cc783259(v=ws.10).aspx\n  _CONTROL_DESCRIPTIONS = {\n      '1001': 'Download signed ActiveX controls',\n      '1004': 'Download unsigned ActiveX controls',\n      '1200': 'Run ActiveX controls and plug-ins',\n      '1201': ('Initialize and script ActiveX controls not marked as safe for '\n               'scripting'),\n      '1206': 'Allow scripting of Internet Explorer Web browser control',\n      '1207': 'Reserved',\n      '1208': 'Allow previously unused ActiveX controls to run without prompt',\n      '1209': 'Allow Scriptlets',\n      '120A': 'Override Per-Site (domain-based) ActiveX restrictions',\n      '120B': 'Override Per-Site (domain-based) ActiveX restrictions',\n      '1400': 'Active scripting',\n      '1402': 'Scripting of Java applets',\n      '1405': 'Script ActiveX controls marked as safe for scripting',\n      '1406': 'Access data sources across domains',\n      '1407': 'Allow Programmatic clipboard access',\n      '1408': 'Reserved',\n      '1601': 'Submit non-encrypted form data',\n      '1604': 'Font download',\n      '1605': 'Run Java',\n      '1606': 'Userdata persistence',\n      '1607': 'Navigate sub-frames across different domains',\n      '1608': 'Allow META REFRESH',\n      '1609': 'Display mixed content',\n      '160A': 'Include local directory path when uploading files to a server',\n      '1800': 'Installation of desktop items',\n      '1802': 'Drag and drop or copy and paste files',\n      '1803': 'File Download',\n      '1804': 'Launching programs and files in an IFRAME',\n      '1805': 'Launching programs and files in webview',\n      '1806': 'Launching applications and unsafe files',\n      '1807': 'Reserved',\n      '1808': 'Reserved',\n      '1809': 'Use Pop-up Blocker',\n      '180A': 'Reserved',\n      '180B': 'Reserved',\n      '180C': 'Reserved',\n      '180D': 'Reserved',\n      '1A00': 'Logon',\n      '1A02': 'Allow persistent cookies that are stored on your computer',\n      '1A03': 'Allow per-session cookies (not stored)',\n      '1A04': ('Don\\'t prompt for client certificate selection when no '\n               'certificates or only one certificate exists'),\n      '1A05': 'Allow 3rd party persistent cookies',\n      '1A06': 'Allow 3rd party session cookies',\n      '1A10': 'Privacy Settings',\n      '1C00': 'Java permissions',\n      '1E05': 'Software channel permissions',\n      '1F00': 'Reserved',\n      '2000': 'Binary and script behaviors',\n      '2001': 'Run components signed with Authenticode',\n      '2004': 'Run components not signed with Authenticode',\n      '2100': 'Open files based on content, not file extension',\n      '2101': ('Web sites in less privileged web content zone can navigate '\n               'into this zone'),\n      '2102': ('Allow script initiated windows without size or position '\n               'constraints'),\n      '2103': 'Allow status bar updates via script',\n      '2104': 'Allow websites to open windows without address or status bars',\n      '2105': 'Allow websites to prompt for information using scripted windows',\n      '2200': 'Automatic prompting for file downloads',\n      '2201': 'Automatic prompting for ActiveX controls',\n      '2300': 'Allow web pages to use restricted protocols for active content',\n      '2301': 'Use Phishing Filter',\n      '2400': '.NET Framework: XAML browser applications',\n      '2401': '.NET Framework: XPS documents',\n      '2402': '.NET Framework: Loose XAML',\n      '2500': 'Turn on Protected Mode [Vista only setting]',\n      '2600': 'Enable .NET Framework setup'}\n\n  _CONTROL_VALUES_COMMON_ENABLE = {\n      0x00000000: 'Enable',\n      0x00000001: 'Prompt',\n      0x00000003: 'Disable',\n      0x00010000: 'Administrator approved'}\n\n  _CONTROL_VALUES_COMMON_SAFETY = {\n      0x00010000: 'High safety',\n      0x00020000: 'Medium safety',\n      0x00030000: 'Low safety'}\n\n  _CONTROL_VALUES_1A00 = {\n      0x00000000: 'Automatic logon with current user name and password',\n      0x00010000: 'Prompt for user name and password',\n      0x00020000: 'Automatic logon only in Intranet zone',\n      0x00030000: 'Anonymous logon'}\n\n  _CONTROL_VALUES_1C00 = {\n      0x00000000: 'Disable Java',\n      0x00010000: 'High safety',\n      0x00020000: 'Medium safety',\n      0x00030000: 'Low safety',\n      0x00800000: 'Custom'}\n\n  def _GetControlValueDescription(self, control, control_value):\n    \"\"\"Retrieves the description of a specific control value.\n\n    Args:\n      control (str): control.\n      control_value (str): value to which the control is set.\n\n    Returns:\n      str: description of the control value or None if not available.\n    \"\"\"\n    if control in (\n        '1001', '1004', '1200', '1201', '1400', '1402', '1405', '1406', '1407',\n        '1601', '1604', '1606', '1607', '1608', '1609', '1800', '1802', '1803',\n        '1804', '1809', '1A04', '2000', '2001', '2004', '2100', '2101', '2102',\n        '2200', '2201', '2300'):\n      return self._CONTROL_VALUES_COMMON_ENABLE.get(control_value)\n\n    if control == '1A00':\n      return self._CONTROL_VALUES_1A00.get(control_value)\n\n    if control == '1C00':\n      return self._CONTROL_VALUES_1C00.get(control_value)\n\n    if control == '1E05':\n      return self._CONTROL_VALUES_COMMON_SAFETY.get(control_value)\n\n    return None\n\n  def WriteZoneInformation(self, zone_information):\n    \"\"\"Writes MSIE zone information to the output.\n\n    Args:\n      zone_information (MSIEZoneInformation): MSIE zone information.\n    \"\"\"\n    zone_name = zone_information.zone_name\n    if not zone_name:\n      zone_name = self._DEFAULT_ZONE_NAMES.get(zone_information.zone)\n\n    if zone_name:\n      text = f'Zone\\t\\t\\t: {zone_information.zone:s} ({zone_name:s})\\n'\n    else:\n      text = f'Zone\\t\\t\\t: {zone_information.zone:s}\\n'\n    self.WriteText(text)\n\n    control_description = self._CONTROL_DESCRIPTIONS.get(\n        zone_information.control, None)\n\n    if control_description:\n      text = (f'Control\\t\\t\\t: {zone_information.control:s} '\n              f'({control_description:s})\\n')\n    else:\n      text = f'Control\\t\\t\\t: {zone_information.control:s}\\n'\n    self.WriteText(text)\n\n    control_value_description = self._GetControlValueDescription(\n        zone_information.control, zone_information.control_value)\n\n    if control_value_description:\n      text = (f'Value\\t\\t\\t: {zone_information.control_value!s} '\n              f'({control_value_description:s})\\n')\n    else:\n      text = f'Value\\t\\t\\t: {zone_information.control_value!s}\\n'\n    self.WriteText(text)\n\n    self.WriteText('\\n')\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract MSIE zone information.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the MSIE zone information from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a NTUSER.DAT or SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  collector_object = msie_zone_info.MSIEZoneInformationCollector(\n      debug=options.debug)\n\n  output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    has_results = False\n    for zone_information in collector_object.Collect(scanner.registry):\n      output_writer_object.WriteZoneInformation(zone_information)\n      has_results = True\n\n  finally:\n    output_writer_object.Close()\n\n  if not has_results:\n    print('No MSIE zone information found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/profiles.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract user profiles.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import output_writers\nfrom winregrc import profiles\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def WriteUserProfile(self, user_profile):\n    \"\"\"Writes an user profile to the output.\n\n    Args:\n      user_profile (UserProfile): user profile.\n    \"\"\"\n    self.WriteText((\n        f'{user_profile.security_identifier:s}: '\n        f'{user_profile.home_directory:s}\\n'))\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract user profiles.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the user profiles from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  # TODO: map collector to available Registry keys.\n  collector_object = profiles.UserProfilesCollector(\n      debug=options.debug)\n\n  output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    has_results = False\n    for user_profile in collector_object.Collect(scanner.registry):\n      output_writer_object.WriteUserProfile(user_profile)\n      has_results = True\n\n    if has_results:\n      output_writer_object.WriteText('\\n')\n\n  finally:\n    output_writer_object.Close()\n\n  if not has_results:\n    print('No user profiles found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/programscache.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract the program cache.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import output_writers\nfrom winregrc import programscache\nfrom winregrc import volume_scanner\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract the program cache.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the program cache from a NTUSER.DAT Registry file.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a NTUSER.DAT Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  # TODO: add support to select user.\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  output_writer = output_writers.StdoutOutputWriter()\n\n  if not output_writer.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    collector_object = programscache.ProgramsCacheCollector(\n        debug=options.debug, output_writer=output_writer)\n\n    # TODO: change collector to generate ProgramCacheEntry\n    has_results = collector_object.Collect(scanner.registry)\n\n  finally:\n    output_writer.Close()\n\n  if not has_results:\n    print('No program cache entries found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/sam.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract Security Account Manager (SAM) information.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import output_writers\nfrom winregrc import sam\nfrom winregrc import volume_scanner\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract SAM information.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts Security Account Manager information from a SAM Registry '\n      'file.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SAM Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  output_writer = output_writers.StdoutOutputWriter()\n\n  if not output_writer.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  # TODO: map collector to available Registry keys.\n  collector_object = sam.SecurityAccountManagerCollector(\n      debug=options.debug, output_writer=output_writer)\n\n  result = collector_object.Collect(scanner.registry)\n  if not result:\n    output_writer.WriteText('No Security Account Manager key found.')\n    output_writer.WriteText('')\n\n  else:\n    for user_account in collector_object.user_accounts:\n      output_writer.WriteValue('Username', user_account.username)\n      output_writer.WriteValue('Relative identifier (RID)', user_account.rid)\n      output_writer.WriteValue(\n          'Primary group identifier', user_account.primary_gid)\n\n      if user_account.full_name:\n        output_writer.WriteValue('Full name', user_account.full_name)\n\n      if user_account.comment:\n        output_writer.WriteValue('Comment', user_account.comment)\n\n      if user_account.user_comment:\n        output_writer.WriteValue('User comment', user_account.user_comment)\n\n      output_writer.WriteFiletimeValue(\n          'Last log-in time', user_account.last_login_time)\n\n      output_writer.WriteFiletimeValue(\n          'Last password set time', user_account.last_password_set_time)\n\n      output_writer.WriteFiletimeValue(\n          'Account expiration time', user_account.account_expiration_time)\n\n      output_writer.WriteFiletimeValue(\n          'Last password failure time', user_account.last_password_failure_time)\n\n      output_writer.WriteValue(\n          'Number of log-ons', user_account.number_of_logons)\n      output_writer.WriteValue(\n          'Number of password failures',\n          user_account.number_of_password_failures)\n\n      if user_account.codepage:\n        output_writer.WriteValue('Codepage', user_account.codepage)\n\n      output_writer.WriteText('\\n')\n\n  output_writer.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/services.py",
    "content": "\n\"\"\"Script to extract services information.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import output_writers\nfrom winregrc import services\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def __init__(self, use_tsv=False):\n    \"\"\"Initializes a stdout output writer.\n\n    Args:\n      use_tsv (bool): True if the output should in tab separated values.\n    \"\"\"\n    super().__init__()\n    self._printed_header = False\n    self._use_tsv = use_tsv\n\n  def WriteWindowsService(self, service):\n    \"\"\"Writes the Windows service to stdout.\n\n    Args:\n      service (WindowsService): Windows service.\n    \"\"\"\n    service_type_description = ''\n    if service.service_type:\n      service_type_description = service.GetServiceTypeDescription()\n\n    start_value_description = ''\n    if service.start_value is not None:\n      start_value_description = service.GetStartValueDescription()\n\n    if self._use_tsv:\n      if not self._printed_header:\n        print('\\t'.join([\n            'Service', 'Type', 'Display name', 'Description', 'Executable',\n            'Start']))\n        self._printed_header = True\n\n      service_display_name = service.display_name or ''\n      service_description = service.description or ''\n      service_image_path = service.image_path or ''\n\n      print('\\t'.join([\n          service.name, service_type_description, service_display_name,\n          service_description, service_image_path, start_value_description]))\n\n    else:\n      print(f'{service.name:s}')\n\n      if service.service_type:\n        print(f'\\tType\\t\\t\\t: {service_type_description:s}')\n\n      if service.display_name:\n        print(f'\\tDisplay name\\t\\t: {service.display_name:s}')\n\n      if service.description:\n        print(f'\\tDescription\\t\\t: {service.description:s}')\n\n      if service.image_path:\n        print(f'\\tExecutable\\t\\t: {service.image_path:s}')\n\n      if service.object_name:\n        object_name_description = service.GetObjectNameDescription()\n        print(f'\\t{object_name_description:s}\\t\\t: {service.object_name:s}')\n\n      if service.start_value is not None:\n        print(f'\\tStart\\t\\t\\t: {start_value_description:s}')\n\n      print('')\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract services information.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the services information from a SYSTEM Registry file.'))\n\n  argument_parser.add_argument(\n      '--all', dest='all_control_sets', action='store_true', default=False,\n      help=(\n          'Process all control sets instead of only the current control set.'))\n\n  argument_parser.add_argument(\n      '--diff', dest='diff_control_sets', action='store_true', default=False,\n      help='Only list differences between control sets.')\n\n  argument_parser.add_argument(\n      '--tsv', dest='use_tsv', action='store_true', default=False,\n      help='Use tab separated value (TSV) output.')\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SYSTEM Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  collector_object = services.WindowsServicesCollector(debug=options.debug)\n\n  output_writer_object = StdoutWriter(use_tsv=options.use_tsv)\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    if options.diff_control_sets:\n      has_results = collector_object.Compare(\n          scanner.registry, output_writer_object)\n\n    else:\n      has_results = False\n      for windows_service in collector_object.Collect(\n          scanner.registry, all_control_sets=options.all_control_sets):\n        output_writer_object.WriteWindowsService(windows_service)\n        has_results = True\n\n  finally:\n    output_writer_object.Close()\n\n  if not has_results:\n    print('No Services key found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/shellfolders.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract shell folder identifiers.\"\"\"\n\nimport argparse\nimport logging\nimport sys\nimport yaml\n\nfrom winregrc import output_writers\nfrom winregrc import shellfolders\nfrom winregrc import versions\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  _WINDOWS_VERSIONS_KEY_FUNCTION = versions.WindowsVersions.KeyFunction\n\n  def WriteHeader(self):\n    \"\"\"Writes the header to stdout.\"\"\"\n    print('# winreg-kb shellfolder definitions')\n\n  def WriteShellFolder(self, shell_folder, windows_versions):\n    \"\"\"Writes the shell folder to stdout.\n\n    Args:\n      shell_folder (WindowsShellFolder): the shell folder.\n      windows_versions (list[str]): the Windows versions.\n    \"\"\"\n    print('---')\n    print(f'identifier: \"{shell_folder.identifier:s}\"')\n\n    if shell_folder.class_name:\n      print(f'class_name: {shell_folder.class_name:s}')\n\n    name = shell_folder.name\n    if '\\\\' in name:\n      name = name.replace('\\\\', '\\\\\\\\')\n\n    if shell_folder.name:\n      print(f'name: \"{name:s}\"')\n\n    if shell_folder.alternate_names:\n      alternate_names = ', '.join([\n          f'\"{name:s}\"' for name in shell_folder.alternate_names])\n      print(f'alternate_names: [{alternate_names:s}]')\n\n    windows_versions = ', '.join([f'\"{version:s}\"' for version in sorted(\n        windows_versions, key=self._WINDOWS_VERSIONS_KEY_FUNCTION)])\n    print(f'windows_versions: [{windows_versions:s}]')\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract shell folder identifiers.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the shell folder identifiers from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      '-w', '--windows_version', '--windows-version', dest='windows_version',\n      action='store', metavar='VERSION', default=None,\n      help='string that identifies the Windows version.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None, help=(\n          'path of the volume containing C:\\\\Windows, the filename of a '\n          'storage media image containing the C:\\\\Windows directory, or the '\n          'path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  try:\n    with open(options.source, 'r', encoding='utf-8') as file_object:\n      source_definitions = list(yaml.safe_load_all(file_object))\n\n  except (SyntaxError, UnicodeDecodeError, yaml.parser.ParserError):\n    source_definitions = [{\n        'source': options.source, 'windows_version': options.windows_version}]\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.username = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  shell_folder_per_identifier = {}\n  windows_versions_per_shell_folder = {}\n\n  for source_definition in source_definitions:\n    source_path = source_definition['source']\n    logging.info(f'Processing: {source_path:s}')\n\n    if not scanner.ScanForWindowsVolume(\n        source_path, options=volume_scanner_options):\n      logging.error((\n          f'Unable to retrieve the volume with the Windows directory from: '\n          f'{source_path:s}.'))\n      continue\n\n    # TODO: map collector to available Registry keys.\n    collector_object = shellfolders.ShellFoldersCollector(\n        debug=options.debug)\n\n    # TODO: determine Windows version from source.\n    windows_version = source_definition['windows_version']\n\n    for shell_folder in collector_object.Collect(scanner.registry):\n      # TODO: compare attributes with existing with shell folder.\n      existing_shell_folder = shell_folder_per_identifier.get(\n          shell_folder.identifier, None)\n\n      if not existing_shell_folder:\n        shell_folder_per_identifier[shell_folder.identifier] = shell_folder\n      elif not existing_shell_folder.name:\n        existing_shell_folder.name = shell_folder.name\n      elif (shell_folder.name and\n            shell_folder.name != existing_shell_folder.name and\n            shell_folder.name not in existing_shell_folder.alternate_names):\n        existing_shell_folder.alternate_names.append(shell_folder.name)\n\n      if windows_version:\n        if shell_folder.identifier not in windows_versions_per_shell_folder:\n          windows_versions_per_shell_folder[shell_folder.identifier] = []\n\n        windows_versions_per_shell_folder[shell_folder.identifier].append(\n            windows_version)\n\n  if not shell_folder_per_identifier:\n    print('No shell folder identifiers found.')\n    return 0\n\n  output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    output_writer_object.WriteHeader()\n    for identifier, windows_versions in sorted(\n        windows_versions_per_shell_folder.items()):\n      shell_folder = shell_folder_per_identifier[identifier]\n      output_writer_object.WriteShellFolder(shell_folder, windows_versions)\n\n  finally:\n    output_writer_object.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/srum_extensions.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract System Resource Usage Monitor (SRUM) extensions.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import output_writers\nfrom winregrc import srum_extensions\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def WriteSRUMExtension(self, srum_extension):\n    \"\"\"Writes a SRUM extension to the output.\n\n    Args:\n      srum_extension (SRUMExtension): SRUM extension.\n    \"\"\"\n    self.WriteText(f'{srum_extension.guid:s}\\t{srum_extension.dll_name:s}\\n')\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract SRUM extensions.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the User Assist information from a NTUSER.DAT Registry file.'))\n\n  argument_parser.add_argument(\n      '--codepage', dest='codepage', action='store', metavar='CODEPAGE',\n      default='cp1252', help='the codepage of the extended ASCII strings.')\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a NTUSER.DAT Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  # TODO: map collector to available Registry keys.\n  collector_object = srum_extensions.SRUMExtensionsCollector(\n      debug=options.debug)\n\n  result = collector_object.Collect(scanner.registry, output_writer_object)\n  if not result:\n    print('No SRUM extensions key found.')\n\n  output_writer_object.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/sysinfo.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract system information.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import output_writers\nfrom winregrc import sysinfo\nfrom winregrc import volume_scanner\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract system information.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the system information from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False, help=(\n          'enable debug output.'))\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None, help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  output_writer = output_writers.StdoutOutputWriter()\n\n  if not output_writer.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  # TODO: map collector to available Registry keys.\n  collector_object = sysinfo.SystemInfoCollector(\n      debug=options.debug, output_writer=output_writer)\n\n  result = collector_object.Collect(scanner.registry)\n  if not result:\n    print('No Current Version key found.')\n  else:\n    output_writer.WriteValue(\n        'Product name', collector_object.system_information.product_name)\n    output_writer.WriteValue(\n        'Product identifier',\n        collector_object.system_information.product_identifier)\n\n    output_writer.WriteValue(\n        'Current version', collector_object.system_information.current_version)\n    output_writer.WriteValue(\n        'Current type', collector_object.system_information.current_type)\n    output_writer.WriteValue(\n        'Current build number',\n        collector_object.system_information.current_build_number)\n    output_writer.WriteValue(\n        'CSD version', collector_object.system_information.csd_version)\n\n    output_writer.WriteValue(\n        'Registered organization',\n        collector_object.system_information.registered_organization)\n    output_writer.WriteValue(\n        'Registered owner',\n        collector_object.system_information.registered_owner)\n\n    date_time_value = collector_object.system_information.installation_date\n    date_time_string = date_time_value.CopyToDateTimeString()\n    output_writer.WriteValue('Installation date', date_time_string)\n\n    output_writer.WriteValue(\n        'Path name', collector_object.system_information.path_name)\n    output_writer.WriteValue(\n        '%SystemRoot%', collector_object.system_information.system_root)\n\n    output_writer.WriteText('\\n')\n\n  output_writer.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/syskey.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract system key.\"\"\"\n\nimport argparse\nimport codecs\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import output_writers\nfrom winregrc import syskey\nfrom winregrc import volume_scanner\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract system key.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the system key from a SYSTEM Registry file.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False, help=(\n          'enable debug output.'))\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None, help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SYSTEM Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  output_writer = output_writers.StdoutOutputWriter()\n\n  if not output_writer.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  # TODO: map collector to available Registry keys.\n  collector_object = syskey.SystemKeyCollector(\n      debug=options.debug, output_writer=output_writer)\n\n  result = collector_object.Collect(scanner.registry)\n  if not result:\n    print('No LSA key found.')\n  else:\n    boot_key = codecs.encode(collector_object.system_key.boot_key, 'hex')\n    output_writer.WriteValue('Boot key', boot_key.decode('ascii'))\n\n    output_writer.WriteText('\\n')\n\n  output_writer.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/task_cache.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract Task Scheduler Task Cache information.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import output_writers\nfrom winregrc import task_cache\nfrom winregrc import volume_scanner\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract Scheduler Task Cache information.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts Task Scheduler Task Cache information from the Windows '\n      'Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  output_writer = output_writers.StdoutOutputWriter()\n\n  if not output_writer.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  # TODO: map collector to available Registry keys.\n  collector_object = task_cache.TaskCacheCollector(\n      debug=options.debug, output_writer=output_writer)\n\n  result = collector_object.Collect(scanner.registry)\n  if not result:\n    print('No Task Cache key found.')\n\n  output_writer.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/time_zones.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract tize zone information from the Windows Registry.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import time_zones\nfrom winregrc import output_writers\nfrom winregrc import volume_scanner\n\n\nclass CSVFileWriter(output_writers.OutputWriter):\n  \"\"\"CSV file output writer.\"\"\"\n\n  # pylint: disable=abstract-method\n\n  def __init__(self, path):\n    \"\"\"Initializes a CSV file output writer.\n\n    Args:\n      path (str): path of the CSV file to write to.\n    \"\"\"\n    super().__init__()\n    self._file_object = None\n    self._path = path\n\n  def Close(self):\n    \"\"\"Closes the output writer.\"\"\"\n    self._file_object.close()\n    self._file_object = None\n\n  def Open(self):\n    \"\"\"Opens the output writer.\n\n    Returns:\n      bool: True if successful or False if not.\n    \"\"\"\n    # self._file_object = open(self._path, 'wt', encoding='utf-8')\n    self._file_object = open(self._path, 'at', encoding='utf-8')  # pylint: disable=consider-using-with\n    return 0\n\n  def WriteTimeZone(self, time_zone):\n    \"\"\"Writes a time zone to the output.\n\n    Args:\n      time_zone (TimeZone): time zone.\n    \"\"\"\n    hours_from_utc, minutes_from_utc = divmod(time_zone.offset, 60)\n\n    if hours_from_utc < 0:\n      hours_from_utc *= -1\n      sign = '-'\n    else:\n      sign = '+'\n\n    self._file_object.write((\n        f'{time_zone.name:s},{sign:s}{hours_from_utc:02d}:'\n        f'{minutes_from_utc:02d}\\n'))\n\n  def WriteText(self, text):\n    \"\"\"Writes text.\n\n    Args:\n      text (str): text to write.\n    \"\"\"\n    return\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  def WriteTimeZone(self, time_zone):\n    \"\"\"Writes a time zone to the output.\n\n    Args:\n      time_zone (TimeZone): time zone.\n    \"\"\"\n    hours_from_utc, minutes_from_utc = divmod(time_zone.offset, 60)\n\n    if hours_from_utc < 0:\n      hours_from_utc *= -1\n      sign = '-'\n    else:\n      sign = '+'\n\n    self.WriteText((\n        f'{time_zone.name:s}\\t{sign:s}{hours_from_utc:02d}:'\n        f'{minutes_from_utc:02d}\\n'))\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract tize zone information.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts time zone information for the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      '--csv', dest='csv_file', action='store', metavar='time_zones.csv',\n      default=None, help='path of the CSV file to write to.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  if options.csv_file:\n    output_writer_object = CSVFileWriter(options.csv_file)\n  else:\n    output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  # TODO: map collector to available Registry keys.\n  collector_object = time_zones.TimeZonesCollector(debug=options.debug)\n\n  result = collector_object.Collect(scanner.registry, output_writer_object)\n  if not result:\n    print('No \"Time Zones\" key found.')\n\n  output_writer_object.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/type_libraries.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract type libraries.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import output_writers\nfrom winregrc import type_libraries\nfrom winregrc import volume_scanner\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract type libraries.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the type libraries from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SOFTWARE Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  output_writer = output_writers.StdoutOutputWriter()\n\n  if not output_writer.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  # TODO: map collector to available Registry keys.\n  collector_object = type_libraries.TypeLibrariesCollector(\n      debug=options.debug, output_writer=output_writer)\n\n  result = collector_object.Collect(scanner.registry)\n  if not result:\n    print('No TypeLib key found.')\n  else:\n    for type_library in collector_object.type_libraries:\n      print((f'{type_library.identifier:s}\\t{type_library.version:s}\\t'\n             f'{type_library.description:s}\\t'\n             f'{type_library.typelib_filename:s}'))\n\n  output_writer.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/usbstor.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract USB storage devices.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import output_writers\nfrom winregrc import usbstor\nfrom winregrc import volume_scanner\n\n\nclass StdoutWriter(output_writers.StdoutOutputWriter):\n  \"\"\"Stdout output writer.\"\"\"\n\n  _PROPERTY_IDENTIFIERS_PER_SET = {\n      '{540b947e-8b40-45bc-a8a2-6a0b894cbda2}': {\n          '00000004': 'System.Devices.NumaNode'},\n      '{83da6326-97a6-4088-9453-a1923f573b29}': {\n          '00000006': 'System.Devices.SessionId',\n          # DEVPKEY_Device_InstallDate\n          '00000064': 'System.Devices.InstallDate',\n          # DEVPKEY_Device_FirstInstallDate\n          '00000065': 'System.Devices.FirstInstallDate',\n          # DEVPKEY_Device_LastArrivalDate\n          '00000066': 'System.Devices.LastArrivalDate',\n          # DEVPKEY_Device_LastRemovalDate\n          '00000067': 'System.Devices.LastRemovalDate'},\n      '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}': {\n\t      '00000002': 'System.Drivers.AssemblyDate',\n          '00000003': 'System.Drivers.Version',\n          '00000004': 'System.Drivers.Description',\n          '00000005': 'System.Drivers.InfPath',\n          '00000006': 'System.Drivers.InfSection',\n          '00000007': 'System.Drivers.InfSectionExt',\n          '00000008': 'System.Drivers.MatchingDeviceId',\n          '00000009': 'System.Drivers.Provider',\n          '0000000a': 'System.Drivers.PropPageProvider',\n          '0000000b': 'System.Drivers.CoInstallers',\n          '0000000c': 'System.Drivers.ResourcePickerTags',\n          '0000000d': 'System.Drivers.ResourcePickerExceptions',\n          '0000000e': 'System.Drivers.Rank',\n          '0000000f': 'System.Drivers.LogoLevel'}}\n\n  def WriteUserProfile(self, storage_device):\n    \"\"\"Writes an USB storage device to the output.\n\n    Args:\n      storage_device (UserProfile): USB storage device.\n    \"\"\"\n    self.WriteText(f'Key path\\t: {storage_device.key_path:s}\\n')\n    self.WriteText(f'Device type\\t: {storage_device.device_type:s}\\n')\n    self.WriteText(f'Display name\\t: {storage_device.display_name:s}\\n')\n    self.WriteText(f'Product\\t\\t: {storage_device.product:s}\\n')\n\n    if storage_device.revision:\n      self.WriteText(f'Revision\\t: {storage_device.revision:s}\\n')\n\n    if storage_device.vendor:\n      self.WriteText(f'Vendor\\t\\t: {storage_device.vendor:s}\\n')\n\n    if storage_device.properties:\n      self.WriteText('Properties:\\n')\n      for storage_device_property in storage_device.properties:\n        self.WriteText((\n            f'\\t{storage_device_property.property_set:s} '\n            f'{storage_device_property.identifier:s}'))\n\n        description = self._PROPERTY_IDENTIFIERS_PER_SET.get(\n            storage_device_property.property_set, {}).get(\n                storage_device_property.identifier, None)\n        if description:\n          self.WriteText(f' ({description:s})')\n\n        self.WriteText(f' (0x{storage_device_property.value_type:08x})')\n\n        value = storage_device_property.value\n        if storage_device_property.value_type == 0x00000007:\n          self.WriteText(f': 0x{value:08x}\\n')\n        elif storage_device_property.value_type == 0x00000010:\n          value = value.CopyToDateTimeStringISO8601()\n          self.WriteText(f': {value:s}\\n')\n        else:\n          self.WriteText(f': {value!s}\\n')\n\n    self.WriteText('\\n')\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract USB storage devices.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the USB storage devices from the Windows Registry.'))\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None,\n      help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a SYSTEM Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  # TODO: map collector to available Registry keys.\n  collector_object = usbstor.USBStorageDeviceCollector(debug=options.debug)\n\n  output_writer_object = StdoutWriter()\n\n  if not output_writer_object.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  try:\n    has_results = False\n    for storage_device in collector_object.Collect(scanner.registry):\n      output_writer_object.WriteUserProfile(storage_device)\n      has_results = True\n\n  finally:\n    output_writer_object.Close()\n\n  if not has_results:\n    print('No USB storage devices found.')\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/scripts/userassist.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to extract UserAssist information.\"\"\"\n\nimport argparse\nimport logging\nimport sys\n\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\n\nfrom winregrc import output_writers\nfrom winregrc import userassist\nfrom winregrc import volume_scanner\n\n\ndef Main():\n  \"\"\"Entry point of console script to extract UserAssist information.\n\n  Returns:\n    int: exit code that is provided to sys.exit().\n  \"\"\"\n  argument_parser = argparse.ArgumentParser(description=(\n      'Extracts the UserAssist information from a NTUSER.DAT Registry file.'))\n\n  argument_parser.add_argument(\n      '--codepage', dest='codepage', action='store', metavar='CODEPAGE',\n      default='cp1252', help='the codepage of the extended ASCII strings.')\n\n  argument_parser.add_argument(\n      '-d', '--debug', dest='debug', action='store_true', default=False,\n      help='enable debug output.')\n\n  argument_parser.add_argument(\n      'source', nargs='?', action='store', metavar='PATH', default=None, help=(\n          'path of the volume containing C:\\\\Windows, the filename of '\n          'a storage media image containing the C:\\\\Windows directory, '\n          'or the path of a NTUSER.DAT Registry file.'))\n\n  options = argument_parser.parse_args()\n\n  if not options.source:\n    print('Source value is missing.')\n    print('')\n    argument_parser.print_help()\n    print('')\n    return 1\n\n  logging.basicConfig(\n      level=logging.INFO, format='[%(levelname)s] %(message)s')\n\n  output_writer = output_writers.StdoutOutputWriter()\n\n  if not output_writer.Open():\n    print('Unable to open output writer.')\n    print('')\n    return 1\n\n  mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()\n  scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)\n\n  volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()\n  volume_scanner_options.partitions = ['all']\n  volume_scanner_options.snapshots = ['none']\n  volume_scanner_options.volumes = ['none']\n\n  if not scanner.ScanForWindowsVolume(\n      options.source, options=volume_scanner_options):\n    print((f'Unable to retrieve the volume with the Windows directory from: '\n           f'{options.source:s}.'))\n    print('')\n    return 1\n\n  # TODO: map collector to available Registry keys.\n  collector_object = userassist.UserAssistCollector(\n      debug=options.debug, output_writer=output_writer)\n\n  result = collector_object.Collect(scanner.registry)\n  if not result:\n    print('No UserAssist key found.')\n  else:\n    guid = None\n    for user_assist_entry in collector_object.user_assist_entries:\n      if user_assist_entry.guid != guid:\n        print(f'GUID\\t\\t: {user_assist_entry.guid:s}')\n        guid = user_assist_entry.guid\n\n      print(f'Name\\t\\t: {user_assist_entry.name:s}')\n      print(f'Original name\\t: {user_assist_entry.value_name:s}')\n\n  print('')\n  output_writer.Close()\n\n  return 0\n\n\nif __name__ == '__main__':\n  sys.exit(Main())\n"
  },
  {
    "path": "winregrc/services.py",
    "content": "\"\"\"Windows services and drivers collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass WindowsService:\n  \"\"\"Windows service.\n\n  Attributes:\n    description (str): service description.\n    display_name (str): display name.\n    image_path (str): image path.\n    name (str): name.\n    object_name (str): object name\n    service_type (str): service type.\n    start_value (str): start value.\n  \"\"\"\n\n  _OBJECT_NAME_DESCRIPTIONS = {\n      0x00000010: 'Account name',\n      0x00000020: 'Account name',\n      0x00000110: 'Account name',\n  }\n\n  _SERVICE_TYPE_DESCRIPTIONS = {\n      0x00000001: 'Kernel device driver',\n      0x00000002: 'File system driver',\n      0x00000004: 'Adapter arguments',\n      0x00000010: 'Stand-alone service',\n      0x00000020: 'Shared service',\n  }\n\n  _START_VALUE_DESCRIPTIONS = {\n      0x00000000: 'Boot',\n      0x00000001: 'System',\n      0x00000002: 'Automatic',\n      0x00000003: 'On demand',\n      0x00000004: 'Disabled',\n  }\n\n  def __init__(\n      self, name, service_type, display_name, description, image_path,\n      object_name, start_value):\n    \"\"\"Initializes a Windows service.\n\n    Args:\n      name (str): name.\n      service_type (str): service type.\n      display_name (str): display name.\n      description (str): service description.\n      image_path (str): image path.\n      object_name (str): object name\n      start_value (str): start value.\n    \"\"\"\n    super().__init__()\n    self.description = description\n    self.display_name = display_name\n    self.image_path = image_path\n    self.name = name\n    self.object_name = object_name\n    self.service_type = service_type\n    self.start_value = start_value\n\n  def __eq__(self, other):\n    \"\"\"Determines the current Windows service is equal to the other.\n\n    Returns:\n      bool: True if equal.\n    \"\"\"\n    return (\n        other is not None and\n        self.description == other.description and\n        self.display_name == other.display_name and\n        self.image_path == other.image_path and\n        self.name == other.name and\n        self.object_name == other.object_name and\n        self.service_type == other.service_type and\n        self.start_value == other.start_value)\n\n  def __ne__(self, other):\n    \"\"\"Determines the current Windows service is not equal to the other.\n\n    Returns:\n      bool: True if not equal.\n    \"\"\"\n    return (\n        other is None or\n        self.description != other.description or\n        self.display_name != other.display_name or\n        self.image_path != other.image_path or\n        self.name != other.name or\n        self.object_name != other.object_name or\n        self.service_type != other.service_type or\n        self.start_value != other.start_value)\n\n  def GetObjectNameDescription(self):\n    \"\"\"Retrieves the object name description.\n\n    Return:\n      str: object name description.\n    \"\"\"\n    return self._OBJECT_NAME_DESCRIPTIONS.get(self.service_type, 'Object name')\n\n  def GetServiceTypeDescription(self):\n    \"\"\"Retrieves the service type description.\n\n    Return:\n      str: service type description.\n    \"\"\"\n    return self._SERVICE_TYPE_DESCRIPTIONS.get(\n        self.service_type, f'Unknown 0x{self.service_type:08x}')\n\n  def GetStartValueDescription(self):\n    \"\"\"Retrieves the start value description.\n\n    Return:\n      str: start value description.\n    \"\"\"\n    return self._START_VALUE_DESCRIPTIONS.get(\n        self.start_value, f'Unknown 0x{self.start_value:08x}')\n\n\nclass WindowsServicesCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows services and drivers collector.\"\"\"\n\n  def _CollectWindowsServicesFromServicesKey(self, services_key):\n    \"\"\"Collects the Windows services from a services key.\n\n    Args:\n      services_key (dfwinreg.WinRegistryKey): services Windows Registry key.\n\n    Yields:\n      WindowsService: a Windows service.\n    \"\"\"\n    for service_key in services_key.GetSubkeys():\n      display_name = self._GetStringValueFromKey(service_key, 'DisplayName')\n      description = self._GetValueFromKey(service_key, 'Description')\n      image_path = self._GetValueFromKey(service_key, 'ImagePath')\n      object_name = self._GetValueFromKey(service_key, 'ObjectName')\n      start_value = self._GetValueFromKey(service_key, 'Start')\n      type_value = self._GetValueFromKey(service_key, 'Type')\n\n      yield WindowsService(\n          service_key.name, type_value, display_name, description, image_path,\n          object_name, start_value)\n\n  def _CollectWindowsServicesFromSystemKey(self, system_key):\n    \"\"\"Collects the Windows services from a system key.\n\n    Args:\n      system_key (dfwinreg.WinRegistryKey): system Windows Registry key.\n\n    Yields:\n      WindowsService: a Windows service.\n    \"\"\"\n    for control_set_key in system_key.GetSubkeys():\n      if control_set_key.name.startswith('ControlSet'):\n        services_key = control_set_key.GetSubkeyByName('Services')\n        if services_key:\n          yield from self._CollectWindowsServicesFromServicesKey(services_key)\n\n  def Collect(self, registry, all_control_sets=False):\n    \"\"\"Collects Windows services and drivers.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n      all_control_sets (Optional[bool]): True if the services should be\n          collected from all control sets instead of only the current control\n          set.\n\n    Yields:\n      WindowsService: a Windows service.\n    \"\"\"\n    if all_control_sets:\n      system_key = registry.GetKeyByPath('HKEY_LOCAL_MACHINE\\\\System')\n      if system_key:\n        yield from self._CollectWindowsServicesFromSystemKey(system_key)\n\n    else:\n      services_key = registry.GetKeyByPath(\n          'HKEY_LOCAL_MACHINE\\\\System\\\\CurrentControlSet\\\\Services')\n      if services_key:\n        yield from self._CollectWindowsServicesFromServicesKey(services_key)\n\n  def Compare(self, registry, output_writer):\n    \"\"\"Compares services in the different control sets.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n      output_writer (OutputWriter): output writer.\n\n    Returns:\n      bool: True if the services key was found, False if not.\n    \"\"\"\n    system_key = registry.GetKeyByPath('HKEY_LOCAL_MACHINE\\\\System')\n    if not system_key:\n      return False\n\n    result = False\n    control_sets = []\n    service_names = set()\n    for control_set_key in system_key.GetSubkeys():\n      if control_set_key.name.startswith('ControlSet'):\n        services_key = control_set_key.GetSubkeyByName('Services')\n        if not services_key:\n          continue\n\n        result = True\n\n        services = {}\n        for windows_service in self._CollectWindowsServicesFromServicesKey(\n            services_key):\n          if windows_service.name in services:\n            # TODO: print warning.\n            continue\n\n          windows_service_name = windows_service.name.lower()\n          service_names.add(windows_service_name)\n          services[windows_service_name] = windows_service\n\n        control_sets.append(services)\n\n    number_of_control_sets = len(control_sets)\n    for name in service_names:\n      services_diff = set()\n\n      windows_service = control_sets[0].get(name)\n      for control_set_index in range(1, number_of_control_sets):\n        control_set = control_sets[control_set_index]\n\n        compare_windows_service = control_set.get(name)\n        if windows_service != compare_windows_service:\n          services_diff.add(windows_service)\n          services_diff.add(compare_windows_service)\n\n      for windows_service in services_diff:\n        if not windows_service:\n          if self._debug:\n            print('Not defined')\n        else:\n          output_writer.WriteWindowsService(windows_service)\n\n    return result\n"
  },
  {
    "path": "winregrc/shell_property_keys.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Windows serialized property to shell property key mappings.\n\nThis file was generated by the winsps-kb project.\n\"\"\"\n\n\nSHELL_PROPERTY_KEYS = {\n    '{00000000-0000-0000-0000-000000000000}/0': 'PKEY_Null',\n    '{000214a1-0000-0000-c000-000000000046}/9': 'PKEY_Status',\n    '{00bc20a3-bd48-4085-872c-a88d77f5097e}/105': (\n        'PKEY_Music_ComposerSortOverride'),\n    '{00f23377-7ac6-4b7a-8443-345e731fa57a}/10': (\n        'PKEY_PhotoAcquire_DuplicateDetectionID'),\n    '{00f23377-7ac6-4b7a-8443-345e731fa57a}/2': (\n        'PKEY_PhotoAcquire_RelativePathname'),\n    '{00f23377-7ac6-4b7a-8443-345e731fa57a}/3': (\n        'PKEY_PhotoAcquire_FinalFilename'),\n    '{00f23377-7ac6-4b7a-8443-345e731fa57a}/4': 'PKEY_PhotoAcquire_GroupTag',\n    '{00f23377-7ac6-4b7a-8443-345e731fa57a}/5': (\n        'PKEY_PhotoAcquire_TransferResult'),\n    '{00f23377-7ac6-4b7a-8443-345e731fa57a}/6': (\n        'PKEY_PhotoAcquire_OriginalFilename'),\n    '{00f23377-7ac6-4b7a-8443-345e731fa57a}/7': (\n        'PKEY_PhotoAcquire_CameraSequenceNumber'),\n    '{00f23377-7ac6-4b7a-8443-345e731fa57a}/8': (\n        'PKEY_PhotoAcquire_IntermediateFile'),\n    '{00f23377-7ac6-4b7a-8443-345e731fa57a}/9': 'PKEY_PhotoAcquire_SkipImport',\n    '{00f58a38-c54b-4c40-8696-97235980eae1}/100': 'PKEY_Calendar_Resources',\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/101': (\n        'PKEY_Contact_JobInfo1YomiCompanyName'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/102': (\n        'PKEY_Contact_JobInfo1CompanyName'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/103': 'PKEY_Contact_JobInfo1Title',\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/104': (\n        'PKEY_Contact_JobInfo1OfficeLocation'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/105': (\n        'PKEY_Contact_JobInfo1Manager'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/106': (\n        'PKEY_Contact_JobInfo1Department'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/107': (\n        'PKEY_Contact_JobInfo2YomiCompanyName'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/108': (\n        'PKEY_Contact_JobInfo2CompanyName'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/109': 'PKEY_Contact_JobInfo2Title',\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/110': (\n        'PKEY_Contact_JobInfo2OfficeLocation'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/112': (\n        'PKEY_Contact_JobInfo2Manager'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/113': (\n        'PKEY_Contact_JobInfo2Department'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/114': (\n        'PKEY_Contact_JobInfo3YomiCompanyName'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/115': (\n        'PKEY_Contact_JobInfo3CompanyName'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/116': 'PKEY_Contact_JobInfo3Title',\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/117': (\n        'PKEY_Contact_JobInfo3OfficeLocation'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/118': (\n        'PKEY_Contact_JobInfo3Manager'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/119': (\n        'PKEY_Contact_JobInfo3Department'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/120': (\n        'PKEY_Contact_JobInfo1CompanyAddress'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/121': (\n        'PKEY_Contact_JobInfo2CompanyAddress'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/123': (\n        'PKEY_Contact_JobInfo3CompanyAddress'),\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/124': 'PKEY_Contact_Webpage2',\n    '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/125': 'PKEY_Contact_Webpage3',\n    '{026e516e-b814-414b-83cd-856d6fef4822}/2': (\n        'PKEY_DeviceInterface_FriendlyName'),\n    '{026e516e-b814-414b-83cd-856d6fef4822}/3': 'PKEY_DeviceInterface_Enabled',\n    '{026e516e-b814-414b-83cd-856d6fef4822}/4': (\n        'PKEY_Devices_InterfaceClassGuid'),\n    '{026e516e-b814-414b-83cd-856d6fef4822}/6': (\n        'PKEY_Devices_RestrictedInterface'),\n    '{026e516e-b814-414b-83cd-856d6fef4822}/9': 'PKEY_Devices_SchematicName',\n    '{029c0252-5b86-46c7-aca0-2769ffc8e3d4}/100': 'PKEY_GPS_LatitudeRef',\n    '{02b0f689-a914-4e45-821d-1dda452ed2c4}/100': 'PKEY_GPS_LongitudeNumerator',\n    '{03089873-8ee8-4191-bd60-d31f72b7900b}/100': (\n        'PKEY_Contact_DisplayOtherPhoneNumbers'),\n    '{0337ecec-39fb-4581-a0bd-4c4cc51e9914}/100': (\n        'PKEY_Photo_ApertureNumerator'),\n    '{048658ad-2db8-41a4-bbb6-ac1ef1207eb1}/100': 'PKEY_ItemClassType',\n    '{06704b0c-e830-4c81-9178-91e4e95a80a0}/2': (\n        'PKEY_Devices_NotificationStore'),\n    '{06704b0c-e830-4c81-9178-91e4e95a80a0}/3': 'PKEY_Devices_Notification',\n    '{084d8a0a-e6d5-40de-bf1f-c8820e7c877c}/100': 'PKEY_Task_CompletionStatus',\n    '{08a65aa1-f4c9-43dd-9ddf-a33d8e7ead85}/100': (\n        'PKEY_Contact_HomeAddressCountry'),\n    '{08c0c253-a154-4746-9005-82de5317148b}/1': 'PKEY_FunctionInstance',\n    '{08c7cc5f-60f2-4494-ad75-55e3e0b5add0}/100': 'PKEY_Task_Owner',\n    '{08f6d7c2-e3f2-44fc-af1e-5aa5c81a2d3e}/100': 'PKEY_Photo_MaxAperture',\n    '{0933f3f5-4786-4f46-a8e8-d64dd37fa521}/100': (\n        'PKEY_Photo_FocalPlaneXResolutionDenominator'),\n    '{09429607-582d-437f-84c3-de93a2b24c3c}/100': (\n        'PKEY_Calendar_OptionalAttendeeNames'),\n    '{09edd5b6-b301-43c5-9990-d00302effd46}/100': 'PKEY_Media_AverageLevel',\n    '{0a7b84ef-0c27-463f-84ef-06c5070001be}/10': (\n        'PKEY_DeviceInterface_PrinterName'),\n    '{0adef160-db3f-4308-9a21-06237b16fa2a}/100': (\n        'PKEY_Contact_HomeAddressStreet'),\n    '{0b48f35a-be6e-4f17-b108-3c4073d1669a}/15': 'PKEY_Device_PrinterURL',\n    '{0b63e343-9ccc-11d0-bcdb-00805fccce04}/12': (\n        'PKEY_Search_UrlToIndexWithModificationTime'),\n    '{0b63e343-9ccc-11d0-bcdb-00805fccce04}/2': 'PKEY_Search_UrlToIndex',\n    '{0b63e343-9ccc-11d0-bcdb-00805fccce04}/23': (\n        'PKEY_Search_IsClosedDirectory'),\n    '{0b63e343-9ccc-11d0-bcdb-00805fccce04}/24': 'PKEY_Search_IsFullyContained',\n    '{0b63e350-9ccc-11d0-bcdb-00805fccce04}/5': 'PKEY_MIMEType',\n    '{0b63e350-9ccc-11d0-bcdb-00805fccce04}/8': 'PKEY_Search_GatherTime',\n    '{0b8bb018-2725-4b44-92ba-7933aeb2dde7}/2': (\n        'PKEY_Contact_AccountPictureDynamicVideo'),\n    '{0b8bb018-2725-4b44-92ba-7933aeb2dde7}/3': (\n        'PKEY_Contact_AccountPictureLarge'),\n    '{0b8bb018-2725-4b44-92ba-7933aeb2dde7}/4': (\n        'PKEY_Contact_AccountPictureSmall'),\n    '{0ba7d6c3-568d-4159-ab91-781a91fb71e5}/100': (\n        'PKEY_Calendar_RequiredAttendeeAddresses'),\n    '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/11': (\n        'PKEY_Devices_AepContainer_IsPresent'),\n    '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/12': (\n        'PKEY_Devices_AepContainer_ContainerId'),\n    '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/13': (\n        'PKEY_Devices_AepContainer_ProtocolIds'),\n    '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/2': (\n        'PKEY_Devices_AepContainer_Children'),\n    '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/3': (\n        'PKEY_Devices_AepContainer_CanPair'),\n    '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/4': (\n        'PKEY_Devices_AepContainer_IsPaired'),\n    '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/6': (\n        'PKEY_Devices_AepContainer_Manufacturer'),\n    '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/7': (\n        'PKEY_Devices_AepContainer_ModelName'),\n    '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/8': (\n        'PKEY_Devices_AepContainer_ModelIds'),\n    '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/9': (\n        'PKEY_Devices_AepContainer_Categories'),\n    '{0be1c8e7-1981-4676-ae14-fdd78f05a6e7}/100': 'PKEY_Message_SenderAddress',\n    '{0c73b141-39d6-4653-a683-cab291eaf95b}/2': 'PKEY_Supplemental_AlbumID',\n    '{0c73b141-39d6-4653-a683-cab291eaf95b}/3': 'PKEY_Supplemental_ResourceId',\n    '{0c840a88-b043-466d-9766-d4b26da3fa77}/100': (\n        'PKEY_Photo_SubjectDistanceDenominator'),\n    '{0cb2bf5a-9ee7-4a86-8222-f01e07fdadaf}/100': (\n        'PKEY_PropGroup_PhotoAdvanced'),\n    '{0cef7d53-fa64-11d1-a203-0000f81fedee}/3': 'PKEY_FileDescription',\n    '{0cef7d53-fa64-11d1-a203-0000f81fedee}/4': 'PKEY_FileVersion',\n    '{0cef7d53-fa64-11d1-a203-0000f81fedee}/5': 'PKEY_InternalName',\n    '{0cef7d53-fa64-11d1-a203-0000f81fedee}/6': 'PKEY_OriginalFileName',\n    '{0cef7d53-fa64-11d1-a203-0000f81fedee}/7': 'PKEY_Software_ProductName',\n    '{0cef7d53-fa64-11d1-a203-0000f81fedee}/9': 'PKEY_Trademarks',\n    '{0cf8fb02-1837-42f1-a697-a7017aa289b9}/100': 'PKEY_GPS_DOP',\n    '{0da41cfa-d224-4a18-ae2f-596158db4b3a}/100': 'PKEY_Message_SenderName',\n    '{0f55cde2-4f49-450d-92c1-dcd16301b1b7}/100': 'PKEY_GPS_LatitudeDecimal',\n    '{10984e0a-f9f2-4321-b7ef-baf195af4319}/100': 'PKEY_ParentalRatingReason',\n    '{10b24595-41a2-4e20-93c2-5761c1395f32}/100': (\n        'PKEY_GPS_ImgDirectionDenominator'),\n    '{10dabe05-32aa-4c29-bf1a-63e2d220587f}/100': 'PKEY_Image_ImageID',\n    '{11d6336b-38c4-4ec9-84d6-eb38d0b150af}/100': (\n        'PKEY_Contact_OtherEmailAddresses'),\n    '{125491f4-818f-46b2-91b5-d537753617b2}/100': 'PKEY_GPS_Status',\n    '{13673f42-a3d6-49f6-b4da-ae46e0c5237c}/2': 'PKEY_Devices_DevObjectType',\n    '{13eb7ffc-ec89-4346-b19d-ccc6f1784223}/101': (\n        'PKEY_Music_AlbumTitleSortOverride'),\n    '{14977844-6b49-4aad-a714-a4513bf60460}/100': 'PKEY_Contact_FirstName',\n    '{149c0b69-2c2d-48fc-808f-d318d78c4636}/2': 'PKEY_Volume_IsMappedDrive',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/18248': 'PKEY_Photo_Event',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/18258': 'PKEY_DateImported',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/259': 'PKEY_Image_Compression',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/271': (\n        'PKEY_Photo_CameraManufacturer'),\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/272': 'PKEY_Photo_CameraModel',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/273': (\n        'PKEY_Photo_CameraSerialNumber'),\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/274': 'PKEY_Photo_Orientation',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/305': 'PKEY_SoftwareUsed',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/33434': 'PKEY_Photo_ExposureTime',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/33437': 'PKEY_Photo_FNumber',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/34850': (\n        'PKEY_Photo_ExposureProgram'),\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/34855': 'PKEY_Photo_ISOSpeed',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/36867': 'PKEY_Photo_DateTaken',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37377': 'PKEY_Photo_ShutterSpeed',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37378': 'PKEY_Photo_Aperture',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37380': 'PKEY_Photo_ExposureBias',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37382': (\n        'PKEY_Photo_SubjectDistance'),\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37383': 'PKEY_Photo_MeteringMode',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37384': 'PKEY_Photo_LightSource',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37385': 'PKEY_Photo_Flash',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37386': 'PKEY_Photo_FocalLength',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/40961': 'PKEY_Image_ColorSpace',\n    '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/41483': 'PKEY_Photo_FlashEnergy',\n    '{14c83a99-0b3f-44b7-be4c-a178d3990564}/2': (\n        'PKEY_DeviceInterfaceClass_DefaultInterface'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/10': (\n        'PKEY_Devices_WiFiDirect_Services'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/11': (\n        'PKEY_Devices_WiFiDirect_SupportedChannelList'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/12': (\n        'PKEY_Devices_WiFiDirect_InformationElements'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/13': (\n        'PKEY_Devices_WiFiDirect_DeviceAddress'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/2': (\n        'PKEY_Devices_WiFiDirect_InterfaceAddress'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/3': (\n        'PKEY_Devices_WiFiDirect_InterfaceGuid'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/4': (\n        'PKEY_Devices_WiFiDirect_GroupId'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/5': (\n        'PKEY_Devices_WiFiDirect_IsConnected'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/6': (\n        'PKEY_Devices_WiFiDirect_IsVisible'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/7': (\n        'PKEY_Devices_WiFiDirect_IsLegacyDevice'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/8': (\n        'PKEY_Devices_WiFiDirect_MiracastVersion'),\n    '{1506935d-e3e7-450f-8637-82233ebe5f6e}/9': (\n        'PKEY_Devices_WiFiDirect_IsMiracastLcpSupported'),\n    '{16473c91-d017-4ed9-ba4d-b6baa55dbcf8}/100': 'PKEY_GPS_ImgDirection',\n    '{16cbb924-6500-473b-a5be-f1599bcbe413}/100': (\n        'PKEY_Photo_DigitalZoomNumerator'),\n    '{16e634ee-2bff-497b-bd8a-4341ad39eeb9}/100': (\n        'PKEY_GPS_LatitudeDenominator'),\n    '{16ea4042-d6f4-4bca-8349-7c78d30fb333}/100': (\n        'PKEY_Photo_ShutterSpeedNumerator'),\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/20': 'PKEY_Contact_HomeTelephone',\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/25': (\n        'PKEY_Contact_PrimaryTelephone'),\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/35': 'PKEY_Contact_MobileTelephone',\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/47': 'PKEY_Contact_Birthday',\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/48': (\n        'PKEY_Contact_PrimaryEmailAddress'),\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/6': 'PKEY_Contact_JobTitle',\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/65': 'PKEY_Contact_HomeAddressCity',\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/69': 'PKEY_Contact_PersonalTitle',\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/7': 'PKEY_Contact_OfficeLocation',\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/71': 'PKEY_Contact_MiddleName',\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/73': 'PKEY_Contact_Suffix',\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/74': 'PKEY_Contact_NickName',\n    '{176dc63c-2688-4e89-8143-a347800f25e9}/75': 'PKEY_Contact_Prefix',\n    '{182c1ea6-7c1c-4083-ab4b-ac6c9f4ed128}/100': 'PKEY_GPS_DestLongitudeRef',\n    '{188c1f91-3c40-4132-9ec5-d8b03b72a8a2}/100': (\n        'PKEY_Calendar_ResponseStatus'),\n    '{18bbd425-ecfd-46ef-b612-7b4a6034eda0}/100': (\n        'PKEY_Contact_PrimaryAddressPostalCode'),\n    '{19b51fa6-1f92-4a5c-ab48-7df0abd67444}/100': 'PKEY_Image_ResolutionUnit',\n    '{1a701bf6-478c-4361-83ab-3701bb053c58}/100': 'PKEY_Photo_Brightness',\n    '{1a9ba605-8e7c-4d11-ad7d-a50ada18ba1b}/2': 'PKEY_Message_Participants',\n    '{1b5439e7-eba1-4af8-bdd7-7af1d4549493}/100': 'PKEY_RecordedTV_StationName',\n    '{1b97738a-fdfc-462f-9d93-1957e08be90c}/100': 'PKEY_Photo_FNumberNumerator',\n    '{1ce0d6bc-536c-4600-b0dd-7e0c66b350d5}/8': 'PKEY_History_SelectionCount',\n    '{1ce0d6bc-536c-4600-b0dd-7e0c66b350d5}/9': (\n        'PKEY_History_TargetUrlHostName'),\n    '{1d6179a6-a876-4031-b013-3347b2b64dc8}/100': (\n        'PKEY_Photo_FocalPlaneYResolutionDenominator'),\n    '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/0': 'PKEY_AudioEndPoint_Type',\n    '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/1': (\n        'PKEY_AudioEndpoint_Ext_UiClsid'),\n    '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/2': (\n        'PKEY_AudioEndpoint_Association'),\n    '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/3': (\n        'PKEY_AudioEndpoint_PhysicalSpeakers'),\n    '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/4': 'PKEY_AudioEndpoint_GUID',\n    '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/5': (\n        'PKEY_AudioEndpoint_Disable_SysFx'),\n    '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/6': (\n        'PKEY_AudioEndpoint_FullRangeSpeakers'),\n    '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/7': (\n        'PKEY_AudioEndpoint_Supports_EventDriven_Mode'),\n    '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/8': (\n        'PKEY_AudioEndpoint_JackSubType'),\n    '{1e005ee6-bf27-428b-b01c-79676acd2870}/100': 'PKEY_Document_Division',\n    '{1e3ee840-bc2b-476c-8237-2acd1a839b22}/3': 'PKEY_Kind',\n    '{1e3ee840-bc2b-476c-8237-2acd1a839b22}/6': 'PKEY_FullText',\n    '{1e81a3f8-a30f-4247-b9ee-1d0368a9425c}/2': 'PKEY_DataObjectFormat',\n    '{1f856a9f-6900-4aba-9505-2d5f1b4d66cb}/100': 'PKEY_Message_ToDoFlags',\n    '{1f8844e1-24ad-4508-9dfd-5326a415ce02}/100': (\n        'PKEY_Image_CompressedBitsPerPixelDenominator'),\n    '{22704da4-c6b2-4a99-8e56-f16df8c92599}/100': 'PKEY_GPS_VersionID',\n    '{2425166f-5642-4864-992f-98fd98f294c3}/100': (\n        'PKEY_IdentityProvider_Picture'),\n    '{2579e5d0-1116-4084-bd9a-9b4f7cb4df5e}/100': 'PKEY_Audio_PeakValue',\n    '{257e44e2-9031-4323-ac38-85c552871b2e}/100': (\n        'PKEY_Photo_ExposureTimeNumerator'),\n    '{2598d2fb-5569-4367-95df-5cd3a177e1a5}/100': 'PKEY_PropGroup_Origin',\n    '{259abffc-50a7-47ce-af08-68c9a7d73366}/10': 'PKEY_DeviceClass_NoUseClass',\n    '{259abffc-50a7-47ce-af08-68c9a7d73366}/11': (\n        'PKEY_DeviceClass_DefaultService'),\n    '{259abffc-50a7-47ce-af08-68c9a7d73366}/12': 'PKEY_DeviceClass_IconPath',\n    '{259abffc-50a7-47ce-af08-68c9a7d73366}/2': 'PKEY_DeviceClass_Name',\n    '{259abffc-50a7-47ce-af08-68c9a7d73366}/3': 'PKEY_DeviceClass_ClassName',\n    '{259abffc-50a7-47ce-af08-68c9a7d73366}/4': 'PKEY_DeviceClass_Icon',\n    '{259abffc-50a7-47ce-af08-68c9a7d73366}/5': (\n        'PKEY_DeviceClass_ClassInstaller'),\n    '{259abffc-50a7-47ce-af08-68c9a7d73366}/6': (\n        'PKEY_DeviceClass_PropPageProvider'),\n    '{259abffc-50a7-47ce-af08-68c9a7d73366}/7': (\n        'PKEY_DeviceClass_NoInstallClass'),\n    '{259abffc-50a7-47ce-af08-68c9a7d73366}/8': (\n        'PKEY_DeviceClass_NoDisplayClass'),\n    '{259abffc-50a7-47ce-af08-68c9a7d73366}/9': (\n        'PKEY_DeviceClass_SilentInstall'),\n    '{26dc287c-6e3d-4bd3-b2b0-6a26ba2e346d}/2': 'PKEY_StatusBarViewItemCount',\n    '{26dc287c-6e3d-4bd3-b2b0-6a26ba2e346d}/3': (\n        'PKEY_StatusBarSelectedItemCount'),\n    '{276d7bb0-5b34-4fb0-aa4b-158ed12a1809}/100': 'PKEY_Document_ClientID',\n    '{2804d469-788f-48aa-8570-71b9c187e138}/100': 'PKEY_PropGroup_Audio',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/0': 'PKEY_FindData',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/11': 'PKEY_ItemType',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/12': 'PKEY_FileCount',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/14': 'PKEY_TotalFileSize',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/2': 'PKEY_DescriptionID',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/24': 'PKEY_ParsingName',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/25': 'PKEY_SFGAOFlags',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/29': 'PKEY_ContainedItems',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/30': 'PKEY_ParsingPath',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/33': 'PKEY_IsSendToTarget',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/37': 'PKEY_ItemSubType',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/5': 'PKEY_ComputerName',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/6': 'PKEY_NamespaceCLSID',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/8': 'PKEY_ItemPathDisplayNarrow',\n    '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/9': 'PKEY_PerceivedType',\n    '{293ca35a-09aa-4dd2-b180-1fe245728a52}/100': 'PKEY_Calendar_Duration',\n    '{2a785ba9-8d23-4ded-82e6-60a350c86a10}/100': 'PKEY_Photo_Contrast',\n    '{2b1b801e-c0c1-4987-9ec5-72fa89814787}/100': 'PKEY_Identity_PrimarySid',\n    '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/1': (\n        'PKEY_DeviceInterface_Bluetooth_DeviceAddress'),\n    '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/11': (\n        'PKEY_DeviceInterface_Bluetooth_LastConnectedTime'),\n    '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/12': (\n        'PKEY_Devices_Aep_Bluetooth_LastSeenTime'),\n    '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/2': (\n        'PKEY_DeviceInterface_Bluetooth_ServiceGuid'),\n    '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/3': (\n        'PKEY_DeviceInterface_Bluetooth_Flags'),\n    '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/4': (\n        'PKEY_DeviceInterface_Bluetooth_Manufacturer'),\n    '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/5': (\n        'PKEY_DeviceInterface_Bluetooth_ModelNumber'),\n    '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/6': (\n        'PKEY_DeviceInterface_Bluetooth_VendorId'),\n    '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/7': (\n        'PKEY_DeviceInterface_Bluetooth_VendorId'),\n    '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/8': (\n        'PKEY_DeviceInterface_Bluetooth_ProductId'),\n    '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/9': (\n        'PKEY_DeviceInterface_Bluetooth_ProductVersion'),\n    '{2bda47da-08c6-4fe1-80bc-a72fc517c5d0}/100': (\n        'PKEY_GPS_DestDistanceNumerator'),\n    '{2be9260a-2012-4742-a555-f41b638b7dcb}/2': (\n        'PKEY_Devices_Notifications_NewMessage'),\n    '{2c53c813-fb63-4e22-a1ab-0b331ca1e273}/100': (\n        'PKEY_RecordedTV_NetworkAffiliation'),\n    '{2ca2dae6-eddc-407d-bef1-773942abfa95}/100': 'PKEY_GPS_MapDatum',\n    '{2cbaa8f5-d81f-47ca-b17a-f8d822300131}/100': 'PKEY_DateAcquired',\n    '{2dad1eb7-816d-40d3-9ec3-c9773be2aade}/100': 'PKEY_GPS_AltitudeNumerator',\n    '{2e4b640d-5019-46d8-8881-55414cc5caa0}/100': 'PKEY_Media_DateEncoded',\n    '{305bc615-dca1-44a5-9fd4-10c0ba79412e}/100': (\n        'PKEY_Photo_FocalLengthDenominator'),\n    '{3143bf7c-80a8-4854-8880-e2e40189bdd0}/100': (\n        'PKEY_Message_AttachmentContents'),\n    '{315b9c8d-80a9-4ef9-ae16-8e746da51d70}/100': 'PKEY_Calendar_IsRecurring',\n    '{318a6b45-087f-4dc2-b8cc-05359551fc9e}/100': 'PKEY_Photo_RelatedSoundFile',\n    '{31b37743-7c5e-4005-93e6-e953f92b82e9}/2': (\n        'PKEY_Devices_WiFiDirectServices_ServiceAddress'),\n    '{31b37743-7c5e-4005-93e6-e953f92b82e9}/3': (\n        'PKEY_Devices_WiFiDirectServices_ServiceName'),\n    '{31b37743-7c5e-4005-93e6-e953f92b82e9}/4': (\n        'PKEY_Devices_WiFiDirectServices_ServiceInformation'),\n    '{31b37743-7c5e-4005-93e6-e953f92b82e9}/5': (\n        'PKEY_Devices_WiFiDirectServices_AdvertisementId'),\n    '{31b37743-7c5e-4005-93e6-e953f92b82e9}/6': (\n        'PKEY_Devices_WiFiDirectServices_ServiceConfigMethods'),\n    '{31b37743-7c5e-4005-93e6-e953f92b82e9}/7': (\n        'PKEY_Devices_WiFiDirectServices_RequestServiceInformation'),\n    '{32ce38b2-2c9a-41b1-9bc5-b3784394aa44}/2': (\n        'PKEY_EdgeGesture_DisableTouchWhenFullscreen'),\n    '{33dcf22b-28d5-464c-8035-1ee9efd25278}/100': 'PKEY_GPS_LongitudeRef',\n    '{341796f1-1df9-4b1c-a564-91bdefa43877}/100': (\n        'PKEY_Photo_PhotometricInterpretation'),\n    '{346c8bd1-2e6a-4c45-89a4-61b78e8e700f}/100': 'PKEY_IsIncomplete',\n    '{35dbe6fe-44c3-4400-aaae-d2c799c407e8}/100': 'PKEY_GPS_TrackRef',\n    '{3602c812-0f3b-45f0-85ad-603468d69423}/100': 'PKEY_GPS_Date',\n    '{3633de59-6825-4381-a49b-9f6ba13a1471}/2': 'PKEY_Devices_PlaybackState',\n    '{3633de59-6825-4381-a49b-9f6ba13a1471}/3': 'PKEY_Devices_PlaybackTitle',\n    '{3633de59-6825-4381-a49b-9f6ba13a1471}/4': (\n        'PKEY_Devices_RemainingDuration'),\n    '{3633de59-6825-4381-a49b-9f6ba13a1471}/5': (\n        'PKEY_Devices_PlaybackPositionPercent'),\n    '{364028da-d895-41fe-a584-302b1bb70a76}/100': (\n        'PKEY_Contact_DisplayBusinessPhoneNumbers'),\n    '{364b6fa9-37ab-482a-be2b-ae02f60d4318}/100': (\n        'PKEY_Image_CompressedBitsPerPixel'),\n    '{38965063-edc8-4268-8491-b7723172cf29}/100': 'PKEY_Contact_EmailAddress2',\n    '{38d43380-d418-4830-84d5-46935a81c5c6}/32': (\n        'PKEY_Security_AllowedEnterpriseDataProtectionIdentities'),\n    '{39a7f922-477c-48de-8bc8-b28441e342e3}/100': 'PKEY_Project',\n    '{39b77f4f-a104-4863-b395-2db2ad8f7bc1}/100': (\n        'PKEY_Contact_ConnectedServiceDisplayName'),\n    '{3a372292-7fca-49a7-99d5-e47bb2d4e7ab}/100': (\n        'PKEY_GPS_DestLatitudeDenominator'),\n    '{3b2ce006-5e61-4fde-bab8-9b8aac9b26df}/5': 'PKEY_Devices_Aep_ProtocolId',\n    '{3b2ce006-5e61-4fde-bab8-9b8aac9b26df}/8': 'PKEY_Devices_Aep_AepId',\n    '{3c8cee58-d4f0-4cf9-b756-4e5d24447bcd}/100': 'PKEY_Contact_Gender',\n    '{3c8cee58-d4f0-4cf9-b756-4e5d24447bcd}/101': 'PKEY_Contact_GenderValue',\n    '{3f08e66f-2f44-4bb9-a682-ac35d2562322}/100': 'PKEY_Image_CompressionText',\n    '{3f8472b5-e0af-4db2-8071-c53fe76ae7ce}/100': 'PKEY_DueDate',\n    '{402b5934-ec5a-48c3-93e6-85e86a2d934e}/100': (\n        'PKEY_Contact_BusinessAddressCity'),\n    '{41cf5ae0-f75a-4806-bd87-59c7d9248eb9}/100': 'PKEY_FileName',\n    '{425d69e5-48ad-4900-8d80-6eb6b8d0ac86}/100': (\n        'PKEY_GPS_DestLongitudeDenominator'),\n    '{428040ac-a177-4c8a-9760-f6f761227f9a}/100': (\n        'PKEY_Communication_DateItemExpires'),\n    '{42864dfd-9da4-4f77-bded-4aad7b256735}/100': (\n        'PKEY_Photo_GainControlDenominator'),\n    '{4321918b-f69e-470d-a5de-4d88c75ad24b}/19': (\n        'PKEY_DeviceClass_UpperFilters'),\n    '{4321918b-f69e-470d-a5de-4d88c75ad24b}/20': (\n        'PKEY_DeviceClass_LowerFilters'),\n    '{4321918b-f69e-470d-a5de-4d88c75ad24b}/25': 'PKEY_DeviceClass_Security',\n    '{4321918b-f69e-470d-a5de-4d88c75ad24b}/26': 'PKEY_DeviceClass_SecuritySDS',\n    '{4321918b-f69e-470d-a5de-4d88c75ad24b}/27': 'PKEY_DeviceClass_DevType',\n    '{4321918b-f69e-470d-a5de-4d88c75ad24b}/28': 'PKEY_DeviceClass_Exclusive',\n    '{4321918b-f69e-470d-a5de-4d88c75ad24b}/29': (\n        'PKEY_DeviceClass_Characteristics'),\n    '{4340a6c5-93fa-4706-972c-7b648008a5a7}/10': 'PKEY_Device_Siblings',\n    '{4340a6c5-93fa-4706-972c-7b648008a5a7}/2': 'PKEY_Device_DevNodeStatus',\n    '{4340a6c5-93fa-4706-972c-7b648008a5a7}/3': 'PKEY_Device_ProblemCode',\n    '{4340a6c5-93fa-4706-972c-7b648008a5a7}/4': 'PKEY_Device_EjectionRelations',\n    '{4340a6c5-93fa-4706-972c-7b648008a5a7}/5': 'PKEY_Device_RemovalRelations',\n    '{4340a6c5-93fa-4706-972c-7b648008a5a7}/6': 'PKEY_Device_PowerRelations',\n    '{4340a6c5-93fa-4706-972c-7b648008a5a7}/7': 'PKEY_Device_BusRelations',\n    '{4340a6c5-93fa-4706-972c-7b648008a5a7}/8': 'PKEY_Device_Parent',\n    '{4340a6c5-93fa-4706-972c-7b648008a5a7}/9': 'PKEY_Device_Children',\n    '{436f2667-14e2-4feb-b30a-146c53b5b674}/100': 'PKEY_Link_Arguments',\n    '{43f8d7b7-a444-4f87-9383-52271c9b915c}/100': 'PKEY_DateArchived',\n    '{446d16b1-8dad-4870-a748-402ea43d788c}/100': 'PKEY_ThumbnailCacheId',\n    '{446d16b1-8dad-4870-a748-402ea43d788c}/104': 'PKEY_VolumeId',\n    '{446f787f-10c4-41cb-a6c4-4d0343551597}/100': (\n        'PKEY_Contact_BusinessAddressState'),\n    '{45eae747-8e2a-40ae-8cbf-ca52aba6152a}/100': 'PKEY_FlagColorText',\n    '{4679c1b5-844d-4590-baf5-f322231f1b81}/100': 'PKEY_GPS_LongitudeDecimal',\n    '{467ee575-1f25-4557-ad4e-b8b58b0d9c15}/100': 'PKEY_GPS_Satellites',\n    '{4684fe97-8765-4842-9c13-f006447b178c}/100': (\n        'PKEY_RecordedTV_OriginalBroadcastDate'),\n    '{46ac629d-75ea-4515-867f-6dc4321c5844}/100': 'PKEY_GPS_AltitudeRef',\n    '{46b4e8de-cdb2-440d-885c-1658eb65b914}/100': 'PKEY_Note_ColorText',\n    '{47166b16-364f-4aa0-9f31-e2ab3df449c3}/100': 'PKEY_GPS_DOPNumerator',\n    '{4776cafa-bce4-4cb1-a23e-265e76d8eb11}/100': 'PKEY_Note_Color',\n    '{47a96261-cb4c-4807-8ad3-40b9d9dbc6bc}/100': 'PKEY_GPS_DestLongitude',\n    '{48fd6ec8-8a12-4cdf-a03e-4ec5a511edde}/100': 'PKEY_StartDate',\n    '{49237325-a95a-4f67-b211-816b2d45d2e0}/100': 'PKEY_Photo_Saturation',\n    '{49691c90-7e17-101a-a91c-08002b2ecda9}/21': (\n        'PKEY_Search_QueryPropertyHits'),\n    '{49691c90-7e17-101a-a91c-08002b2ecda9}/3': 'PKEY_Search_Rank',\n    '{49691c90-7e17-101a-a91c-08002b2ecda9}/4': 'PKEY_Search_HitCount',\n    '{49691c90-7e17-101a-a91c-08002b2ecda9}/5': 'PKEY_Search_EntryID',\n    '{49691c90-7e17-101a-a91c-08002b2ecda9}/9': 'PKEY_ItemUrl',\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/10': 'PKEY_Devices_BatteryLife',\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/11': 'PKEY_Devices_ChargingState',\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/12': 'PKEY_Devices_StorageCapacity',\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/13': (\n        'PKEY_Devices_StorageFreeSpace'),\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/14': (\n        'PKEY_Devices_StorageFreeSpacePercent'),\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/2': 'PKEY_Devices_SignalStrength',\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/22': (\n        'PKEY_Devices_BatteryPlusCharging'),\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/23': (\n        'PKEY_Devices_BatteryPlusChargingText'),\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/3': 'PKEY_Devices_TextMessages',\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/4': 'PKEY_Devices_NewPictures',\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/5': 'PKEY_Devices_MissedCalls',\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/6': 'PKEY_Devices_Voicemail',\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/7': 'PKEY_Devices_NetworkName',\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/8': 'PKEY_Devices_NetworkType',\n    '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/9': 'PKEY_Devices_Roaming',\n    '{49d1091f-082e-493f-b23f-d2308aa9668c}/100': 'PKEY_PropList_NonPersonal',\n    '{4c6bf15c-4c03-4aac-91f5-64c0f852bcf4}/2': (\n        'PKEY_DeviceInterface_Serial_UsbVendorId'),\n    '{4c6bf15c-4c03-4aac-91f5-64c0f852bcf4}/3': (\n        'PKEY_DeviceInterface_Serial_UsbProductId'),\n    '{4c6bf15c-4c03-4aac-91f5-64c0f852bcf4}/4': (\n        'PKEY_DeviceInterface_Serial_PortName'),\n    '{4d1ebee8-0803-4774-9842-b77db50265e9}/2': 'PKEY_Storage_Portable',\n    '{4d1ebee8-0803-4774-9842-b77db50265e9}/3': 'PKEY_Storage_RemovableMedia',\n    '{4d1ebee8-0803-4774-9842-b77db50265e9}/4': 'PKEY_Storage_SystemCritical',\n    '{4fc5077e-b686-44be-93e3-86cafe368ccd}/1': 'PKEY_PNPX_Installable',\n    '{4fc5077e-b686-44be-93e3-86cafe368ccd}/2': 'PKEY_PNPX_Associated',\n    '{4fc5077e-b686-44be-93e3-86cafe368ccd}/3': 'PKEY_PNPX_CompatibleTypes',\n    '{4fc5077e-b686-44be-93e3-86cafe368ccd}/4': 'PKEY_PNPX_InstallState',\n    '{4fffe4d0-914f-4ac4-8d6f-c9c61de169b1}/100': (\n        'PKEY_Photo_FocalPlaneYResolution'),\n    '{502cfeab-47eb-459c-b960-e6d8728f7701}/100': 'PKEY_ZoneIdentifier',\n    '{502cfeab-47eb-459c-b960-e6d8728f7701}/101': (\n        'PKEY_LastWriterPackageFamilyName'),\n    '{502cfeab-47eb-459c-b960-e6d8728f7701}/102': 'PKEY_AppZoneIdentifier',\n    '{5068bcdf-d697-4d85-8c53-1f1cdab01763}/100': (\n        'PKEY_Contact_DisplayHomePhoneNumbers'),\n    '{508161fa-313b-43d5-83a1-c1accf68622c}/100': 'PKEY_Contact_OtherAddress',\n    '{51236583-0c4a-4fe8-b81f-166aec13f510}/100': (\n        'PKEY_Devices_AppPackageFamilyName'),\n    '{51236583-0c4a-4fe8-b81f-166aec13f510}/123': 'PKEY_Devices_GlyphIcon',\n    '{51ec3f47-dd50-421d-8769-334f50424b1e}/100': 'PKEY_Photo_SharpnessText',\n    '{53da57cf-62c0-45c4-81de-7610bcefd7f5}/100': (\n        'PKEY_Calendar_ShowTimeAsText'),\n    '{540b947e-8b40-45bc-a8a2-6a0b894cbda2}/1': 'PKEY_Numa_Proximity_Domain',\n    '{540b947e-8b40-45bc-a8a2-6a0b894cbda2}/5': 'PKEY_Devices_Present',\n    '{540b947e-8b40-45bc-a8a2-6a0b894cbda2}/6': 'PKEY_Devices_DeviceHasProblem',\n    '{540b947e-8b40-45bc-a8a2-6a0b894cbda2}/9': (\n        'PKEY_Devices_PhysicalDeviceLocation'),\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/10': 'PKEY_CONFIGUI_TOOLTIPS',\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/11': 'PKEY_CONFIGUI_ICON',\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/12': 'PKEY_CONFIGUI_MENUITEM_NOUI',\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/13': 'PKEY_CONFIGUI_MENUITEM',\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/2': 'PKEY_CONFIGUI_INSTANCEID',\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/3': 'PKEY_CONFIGUI_CLSID',\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/4': 'PKEY_CONFIGUI_CONTENTTYPE',\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/5': 'PKEY_CONFIGUI_CAPABILITIES',\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/6': (\n        'PKEY_CONFIGUI_SUPPORTED_ARCHITECTURE'),\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/7': 'PKEY_CONFIGUI_IS_GLOBAL',\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/8': 'PKEY_CONFIGUI_NAME',\n    '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/9': 'PKEY_CONFIGUI_DESCRIPTION',\n    '{55e98597-ad16-42e0-b624-21599a199838}/100': (\n        'PKEY_Photo_ExposureTimeDenominator'),\n    '{560c36c0-503a-11cf-baa1-00004c752a9a}/2': 'PKEY_Search_AutoSummary',\n    '{560c36c0-503a-11cf-baa1-00004c752a9a}/3': (\n        'PKEY_Search_QueryFocusedSummary'),\n    '{560c36c0-503a-11cf-baa1-00004c752a9a}/4': (\n        'PKEY_Search_QueryFocusedSummaryWithFallback'),\n    '{56310920-2491-4919-99ce-eadb06fafdb2}/100': (\n        'PKEY_Contact_BusinessHomePage'),\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/100': 'PKEY_Music_AlbumID',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/11': 'PKEY_Music_Genre',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/12': 'PKEY_Music_Lyrics',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/13': 'PKEY_Music_AlbumArtist',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/2': 'PKEY_Music_Artist',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/33': (\n        'PKEY_Music_ContentGroupDescription'),\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/34': 'PKEY_Music_InitialKey',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/35': 'PKEY_Music_BeatsPerMinute',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/36': 'PKEY_Music_Conductor',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/37': 'PKEY_Music_PartOfSet',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/38': 'PKEY_Media_SubTitle',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/39': 'PKEY_Music_Mood',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/4': 'PKEY_Music_AlbumTitle',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/5': 'PKEY_Media_Year',\n    '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/7': 'PKEY_Music_TrackNumber',\n    '{56c90e9d-9d46-4963-886f-2e1cd9a694ef}/100': (\n        'PKEY_Contact_HomeEmailAddresses'),\n    '{59569556-0a08-4212-95b9-fae2ad6413db}/2': (\n        'PKEY_Devices_Notifications_NewVoicemail'),\n    '{59d49e61-840f-4aa9-a939-e2099b7f6399}/100': 'PKEY_GPS_ProcessingMethod',\n    '{59dde9f2-5253-40ea-9a8b-479e96c6249a}/100': 'PKEY_Photo_ContrastText',\n    '{5bf396d4-5eb2-466f-bde9-2fb3f2361d6e}/100': 'PKEY_Calendar_ShowTimeAs',\n    '{5cbf2787-48cf-4208-b90e-ee5e5d420294}/2': 'PKEY_Link_TargetUrl',\n    '{5cbf2787-48cf-4208-b90e-ee5e5d420294}/21': 'PKEY_Link_Description',\n    '{5cbf2787-48cf-4208-b90e-ee5e5d420294}/23': 'PKEY_Link_DateVisited',\n    '{5cbf2787-48cf-4208-b90e-ee5e5d420294}/7': 'PKEY_History_VisitCount',\n    '{5cda5fc8-33ee-4ff3-9094-ae7bd8868c4d}/100': 'PKEY_IsDeleted',\n    '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/10': (\n        'PKEY_DefaultSaveLocationDisplay'),\n    '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/2': 'PKEY_IsPinnedToNameSpaceTree',\n    '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/3': 'PKEY_IsDefaultSaveLocation',\n    '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/4': 'PKEY_IsSearchOnlyItem',\n    '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/5': (\n        'PKEY_IsDefaultNonOwnerSaveLocation'),\n    '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/6': 'PKEY_OwnerSID',\n    '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/8': 'PKEY_IsLocationSupported',\n    '{5da84765-e3ff-4278-86b0-a27967fbdd03}/100': 'PKEY_IsFlagged',\n    '{5dc2253f-5e11-4adf-9cfe-910dd01e3e70}/100': 'PKEY_Contact_Hobbies',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/10': 'PKEY_Hardware_DriverProvider',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/11': 'PKEY_Hardware_DriverDate',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/2': 'PKEY_Hardware_Name',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/3': 'PKEY_Hardware_Icon',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/4096': 'PKEY_Hardware_Status',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/4097': 'PKEY_Hardware_Devinst',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/4098': 'PKEY_Hardware_Image',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/4099': 'PKEY_Hardware_Function',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/4100': (\n        'PKEY_Hardware_ShellAttributes'),\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/5': (\n        'PKEY_Hardware_DisplayAttribute'),\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/6': 'PKEY_Hardware_Manufacturer',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/7': 'PKEY_Hardware_Model',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/8': 'PKEY_Hardware_SerialNumber',\n    '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/9': 'PKEY_Hardware_DriverVersion',\n    '{5f5aff6a-37e5-4780-97ea-80c7565cf535}/34': (\n        'PKEY_Security_EncryptionOwners'),\n    '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/10': (\n        'PKEY_Devices_Aep_Bluetooth_Cod_Services_Audio'),\n    '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/11': (\n        'PKEY_Devices_Aep_Bluetooth_Cod_Services_Telephony'),\n    '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/12': (\n        'PKEY_Devices_Aep_Bluetooth_Cod_Services_Information'),\n    '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/2': (\n        'PKEY_Devices_Aep_Bluetooth_Cod_Major'),\n    '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/3': (\n        'PKEY_Devices_Aep_Bluetooth_Cod_Minor'),\n    '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/4': (\n        'PKEY_Devices_Aep_Bluetooth_Cod_Services_LimitedDiscovery'),\n    '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/5': (\n        'PKEY_Devices_Aep_Bluetooth_Cod_Services_Positioning'),\n    '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/6': (\n        'PKEY_Devices_Aep_Bluetooth_Cod_Services_Networking'),\n    '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/7': (\n        'PKEY_Devices_Aep_Bluetooth_Cod_Services_Rendering'),\n    '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/8': (\n        'PKEY_Devices_Aep_Bluetooth_Cod_Services_Capturing'),\n    '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/9': (\n        'PKEY_Devices_Aep_Bluetooth_Cod_Services_ObjectXfer'),\n    '{61478c08-b600-4a84-bbe4-e99c45f0a072}/100': 'PKEY_Photo_SaturationText',\n    '{61872cf7-6b5e-4b4b-ac2d-59da84459248}/100': 'PKEY_PropGroup_Media',\n    '{6336b95e-c7a7-426d-86fd-7ae3d39c84b4}/100': 'PKEY_Photo_WhiteBalanceText',\n    '{635e9051-50a5-4ba2-b9db-4ed056c77296}/100': 'PKEY_Contact_FullName',\n    '{63c25b20-96be-488f-8788-c09c407ad812}/100': (\n        'PKEY_Contact_PrimaryAddressStreet'),\n    '{6444048f-4c8b-11d1-8b70-080036b11a03}/12': 'PKEY_Media_FrameCount',\n    '{6444048f-4c8b-11d1-8b70-080036b11a03}/13': 'PKEY_Image_Dimensions',\n    '{6444048f-4c8b-11d1-8b70-080036b11a03}/3': 'PKEY_Image_HorizontalSize',\n    '{6444048f-4c8b-11d1-8b70-080036b11a03}/4': 'PKEY_Image_VerticalSize',\n    '{6444048f-4c8b-11d1-8b70-080036b11a03}/5': (\n        'PKEY_Image_HorizontalResolution'),\n    '{6444048f-4c8b-11d1-8b70-080036b11a03}/6': 'PKEY_Image_VerticalResolution',\n    '{6444048f-4c8b-11d1-8b70-080036b11a03}/7': 'PKEY_Image_BitDepth',\n    '{64440490-4c8b-11d1-8b70-080036b11a03}/10': 'PKEY_Audio_Compression',\n    '{64440490-4c8b-11d1-8b70-080036b11a03}/2': 'PKEY_Audio_Format',\n    '{64440490-4c8b-11d1-8b70-080036b11a03}/3': 'PKEY_Media_Duration',\n    '{64440490-4c8b-11d1-8b70-080036b11a03}/4': 'PKEY_Audio_EncodingBitrate',\n    '{64440490-4c8b-11d1-8b70-080036b11a03}/5': 'PKEY_Audio_SampleRate',\n    '{64440490-4c8b-11d1-8b70-080036b11a03}/6': 'PKEY_Audio_SampleSize',\n    '{64440490-4c8b-11d1-8b70-080036b11a03}/7': 'PKEY_Audio_ChannelCount',\n    '{64440490-4c8b-11d1-8b70-080036b11a03}/8': 'PKEY_Audio_StreamNumber',\n    '{64440490-4c8b-11d1-8b70-080036b11a03}/9': 'PKEY_Audio_StreamName',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/10': 'PKEY_Video_Compression',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/100': 'PKEY_Video_IsSpherical',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/11': 'PKEY_Video_StreamNumber',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/2': 'PKEY_Video_StreamName',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/3': 'PKEY_Video_FrameWidth',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/4': 'PKEY_Video_FrameHeight',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/42': (\n        'PKEY_Video_HorizontalAspectRatio'),\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/43': 'PKEY_Video_TotalBitrate',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/44': 'PKEY_Video_FourCC',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/45': (\n        'PKEY_Video_VerticalAspectRatio'),\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/46': 'PKEY_Video_TranscodedForSync',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/6': 'PKEY_Video_FrameRate',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/8': 'PKEY_Video_EncodingBitrate',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/9': 'PKEY_Video_SampleSize',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/98': 'PKEY_Video_IsStereo',\n    '{64440491-4c8b-11d1-8b70-080036b11a03}/99': 'PKEY_Video_Orientation',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/100': 'PKEY_Media_EpisodeNumber',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/101': 'PKEY_Media_SeasonNumber',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/11': 'PKEY_Copyright',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/12': 'PKEY_ShareUserRating',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/13': 'PKEY_Media_ClassPrimaryID',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/14': 'PKEY_Media_ClassSecondaryID',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/15': 'PKEY_Media_DVDID',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/16': 'PKEY_Media_MCDI',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/17': (\n        'PKEY_Media_MetadataContentProvider'),\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/18': (\n        'PKEY_Media_ContentDistributor'),\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/19': 'PKEY_Music_Composer',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/20': 'PKEY_Video_Director',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/21': 'PKEY_ParentalRating',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/22': 'PKEY_Media_Producer',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/23': 'PKEY_Media_Writer',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/24': 'PKEY_Media_CollectionGroupID',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/25': 'PKEY_Media_CollectionID',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/26': 'PKEY_Media_ContentID',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/27': (\n        'PKEY_Media_CreatorApplication'),\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/28': (\n        'PKEY_Media_CreatorApplicationVersion'),\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/30': 'PKEY_Media_Publisher',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/31': 'PKEY_Music_Period',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/32': 'PKEY_Media_AuthorUrl',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/33': 'PKEY_Media_PromotionUrl',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/34': 'PKEY_Media_UserWebUrl',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/35': (\n        'PKEY_Media_UniqueFileIdentifier'),\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/36': 'PKEY_Media_EncodedBy',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/37': 'PKEY_Media_EncodingSettings',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/38': 'PKEY_Media_ProtectionType',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/39': 'PKEY_Media_ProviderRating',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/40': 'PKEY_Media_ProviderStyle',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/41': 'PKEY_Media_UserNoAutoInfo',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/42': 'PKEY_Media_SeriesName',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/47': (\n        'PKEY_Media_ThumbnailLargePath'),\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/48': 'PKEY_Media_ThumbnailLargeUri',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/49': (\n        'PKEY_Media_ThumbnailSmallPath'),\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/50': 'PKEY_Media_ThumbnailSmallUri',\n    '{64440492-4c8b-11d1-8b70-080036b11a03}/9': 'PKEY_Rating',\n    '{644d37b4-e1b3-4bad-b099-7e7c04966aca}/100': 'PKEY_Contact_EmailAddress3',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12288': 'PKEY_Devices_FriendlyName',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12289': 'PKEY_PNPX_FirmwareVersion',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12290': 'PKEY_PNPX_SerialNumber',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12292': 'PKEY_PNPX_DeviceCategory',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12293': (\n        'PKEY_PNPX_DeviceCategory_Desc'),\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12294': 'PKEY_PNPX_PhysicalAddress',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12295': (\n        'PKEY_PNPX_NetworkInterfaceLuid'),\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12296': (\n        'PKEY_PNPX_NetworkInterfaceGuid'),\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12297': 'PKEY_Devices_IpAddress',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12304': (\n        'PKEY_PNPX_Category_Desc_NonPlural'),\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/16384': (\n        'PKEY_Devices_ServiceAddress'),\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/16385': 'PKEY_Devices_ServiceId',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/16386': 'PKEY_PNPX_ServiceTypes',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/20480': 'PKEY_PNPX_DomainName',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/20481': 'PKEY_PNPX_MachineName',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/20482': 'PKEY_PNPX_ShareName',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/24576': 'PKEY_SSDP_AltLocationInfo',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/24577': 'PKEY_SSDP_DevLifeTime',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/24578': (\n        'PKEY_SSDP_NetworkInterface'),\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/28672': 'PKEY_PNPX_Removable',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/28673': 'PKEY_PNPX_SecureChannel',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/28674': (\n        'PKEY_PNPX_CompactSignature'),\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/28688': 'PKEY_PNPX_IPBusEnumerated',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4096': 'PKEY_PNPX_GlobalIdentity',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4097': 'PKEY_PNPX_Types',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4098': 'PKEY_PNPX_Scopes',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4099': 'PKEY_PNPX_XAddrs',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4100': 'PKEY_PNPX_MetadataVersion',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4101': 'PKEY_PNPX_ID',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4102': 'PKEY_PNPX_RemoteAddress',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4103': 'PKEY_PNPX_RootProxy',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8192': (\n        'PKEY_DeviceDisplay_Manufacturer'),\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8193': 'PKEY_PNPX_ManufacturerUrl',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8194': (\n        'PKEY_DeviceDisplay_ModelName'),\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8195': 'PKEY_Devices_ModelNumber',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8196': 'PKEY_PNPX_ModelUrl',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8197': 'PKEY_PNPX_Upc',\n    '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8198': (\n        'PKEY_Devices_PresentationUrl'),\n    '{65a98875-3c80-40ab-abbc-efdaf77dbee2}/100': 'PKEY_AcquisitionID',\n    '{660e04d6-81ab-4977-a09f-82313113ab26}/100': 'PKEY_Contact_HomeFaxNumber',\n    '{6614ef48-4efe-4424-9eda-c79f404edf3e}/2': (\n        'PKEY_Devices_Notifications_MissedCall'),\n    '{668cdfa5-7a1b-4323-ae4b-e527393a1d81}/100': 'PKEY_SourceItem',\n    '{67df94de-0ca7-4d6f-b792-053a3e4f03cf}/100': 'PKEY_FlagColor',\n    '{6845cc72-1b71-48c3-af86-b09171a19b14}/3': (\n        'PKEY_Devices_DialProtocol_InstalledApplications'),\n    '{68dd6094-7216-40f1-a029-43fe7127043f}/100': 'PKEY_PropGroup_Music',\n    '{6a15e5a0-0a1e-4cd7-bb8c-d2f1b0c929bc}/100': (\n        'PKEY_Contact_BusinessTelephone'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/10': (\n        'PKEY_Devices_AepContainer_SupportsRendering'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/11': (\n        'PKEY_Devices_AepContainer_SupportsCapturing'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/12': (\n        'PKEY_Devices_AepContainer_SupportsObjectTransfer'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/13': (\n        'PKEY_Devices_AepContainer_SupportsTelephony'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/14': (\n        'PKEY_Devices_AepContainer_SupportsInformation'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/2': (\n        'PKEY_Devices_AepContainer_SupportsAudio'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/3': (\n        'PKEY_Devices_AepContainer_SupportsVideo'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/4': (\n        'PKEY_Devices_AepContainer_SupportsImages'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/5': (\n        'PKEY_Devices_AepContainer_SupportedUriSchemes'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/6': (\n        'PKEY_Devices_AepContainer_DialProtocol_InstalledApplications'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/7': (\n        'PKEY_Devices_AepContainer_SupportsLimitedDiscovery'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/8': (\n        'PKEY_Devices_AepContainer_SupportsPositioning'),\n    '{6af55d45-38db-4495-acb0-d4728a3b8314}/9': (\n        'PKEY_Devices_AepContainer_SupportsNetworking'),\n    '{6afe7437-9bcd-49c7-80fe-4a5c65fa5874}/104': 'PKEY_Music_DiscNumber',\n    '{6b223b6a-162e-4aa9-b39f-05d678fc6d77}/100': (\n        'PKEY_Music_SynchronizedLyrics'),\n    '{6b8b68f6-200b-47ea-8d25-d8050f57339f}/100': 'PKEY_Photo_FlashText',\n    '{6b8da074-3b5c-43bc-886f-0a2cdce00b6f}/100': 'PKEY_ItemName',\n    '{6bdd1fc6-810f-11d0-bec7-08002be2092f}/2': 'PKEY_Devices_WiaDeviceType',\n    '{6d217f6d-3f6a-4825-b470-5f03ca2fbe9b}/100': 'PKEY_Photo_ProgramMode',\n    '{6d24888f-4718-4bda-afed-ea0fb4386cd8}/100': 'PKEY_OfflineStatus',\n    '{6d6d5d49-265d-4688-9f4e-1fdd33e7cc83}/100': 'PKEY_Identity_InternetSid',\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/12': (\n        'PKEY_RecordedTV_IsClosedCaptioningAvailable'),\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/13': (\n        'PKEY_RecordedTV_IsRepeatBroadcast'),\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/14': 'PKEY_RecordedTV_IsSAP',\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/15': (\n        'PKEY_RecordedTV_DateContentExpires'),\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/16': (\n        'PKEY_RecordedTV_IsATSCContent'),\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/17': 'PKEY_RecordedTV_IsDTVContent',\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/18': 'PKEY_RecordedTV_IsHDContent',\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/2': 'PKEY_RecordedTV_EpisodeName',\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/3': (\n        'PKEY_RecordedTV_ProgramDescription'),\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/4': 'PKEY_RecordedTV_Credits',\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/5': (\n        'PKEY_RecordedTV_StationCallSign'),\n    '{6d748de2-8d38-4cc3-ac60-f009b057c557}/7': 'PKEY_RecordedTV_ChannelNumber',\n    '{6e682923-7f7b-4f0c-a337-cfca296687bf}/100': (\n        'PKEY_Contact_OtherAddressCity'),\n    '{6ebe6946-2321-440a-90f0-c043efd32476}/100': (\n        'PKEY_Photo_BrightnessDenominator'),\n    '{6fa20de6-d11c-4d9d-a154-64317628c12d}/100': 'PKEY_ExpandoProperties',\n    '{702926f4-44a6-43e1-ae71-45627116893b}/100': 'PKEY_GPS_TrackNumerator',\n    '{713d1703-a2e2-49f5-9214-56472ef3da5c}/2': (\n        'PKEY_DeviceClass_ClassCoInstallers'),\n    '{71724756-3e74-4432-9b59-e7b2f668a593}/2': (\n        'PKEY_Devices_AepService_FriendlyName'),\n    '{71724756-3e74-4432-9b59-e7b2f668a593}/3': (\n        'PKEY_Devices_AepService_ServiceClassId'),\n    '{71724756-3e74-4432-9b59-e7b2f668a593}/4': (\n        'PKEY_Devices_AepService_ContainerId'),\n    '{71b377d6-e570-425f-a170-809fae73e54e}/100': (\n        'PKEY_Contact_OtherAddressState'),\n    '{7268af55-1ce4-4f6e-a41f-b6e4ef10e4a9}/100': 'PKEY_Contact_Profession',\n    '{72fab781-acda-43e5-b155-b2434f85e678}/100': 'PKEY_DateCompleted',\n    '{72fc5ba4-24f9-4011-9f3f-add27afad818}/100': 'PKEY_Calendar_ReminderTime',\n    '{730fb6dd-cf7c-426b-a03f-bd166cc9ee24}/100': (\n        'PKEY_Contact_BusinessAddress'),\n    '{738bf284-1d87-420b-92cf-5834bf6ef9ed}/100': (\n        'PKEY_Photo_ExposureBiasNumerator'),\n    '{744c8242-4df5-456c-ab9e-014efb9021e3}/100': (\n        'PKEY_Calendar_OrganizerAddress'),\n    '{745baf0e-e5c1-4cfb-8a1b-d031a0a52393}/100': (\n        'PKEY_Photo_DigitalZoomDenominator'),\n    '{74a7de49-fa11-4d3d-a006-db7e08675916}/100': 'PKEY_Identity_ProviderID',\n    '{76c09943-7c33-49e3-9e7e-cdba872cfada}/100': 'PKEY_GPS_Track',\n    '{776b6b3b-1e3d-4b0c-9a0e-8fbaf2a8492a}/100': (\n        'PKEY_Photo_FocalLengthNumerator'),\n    '{78342dcb-e358-4145-ae9a-6bfe4e0f9f51}/100': (\n        'PKEY_GPS_AltitudeDenominator'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/100': (\n        'PKEY_DeviceDisplay_DeviceFunctionSubRank'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/101': (\n        'PKEY_DeviceDisplay_AlwaysShowDeviceAsConnected'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/256': (\n        'PKEY_Devices_DeviceInstanceId'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/51': 'PKEY_DeviceDisplay_Address',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/52': 'PKEY_Devices_DiscoveryMethod',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/53': (\n        'PKEY_DeviceDisplay_IsEncrypted'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/54': (\n        'PKEY_DeviceDisplay_IsAuthenticated'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/55': 'PKEY_Devices_IsConnected',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/56': 'PKEY_Devices_Paired',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/57': 'PKEY_DeviceDisplay_Icon',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/65': 'PKEY_DeviceDisplay_Version',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/66': 'PKEY_DeviceDisplay_Last_Seen',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/67': (\n        'PKEY_DeviceDisplay_Last_Connected'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/68': (\n        'PKEY_DeviceDisplay_IsShowInDisconnectedState'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/70': (\n        'PKEY_DeviceDisplay_IsLocalMachine'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/71': 'PKEY_Devices_MetadataPath',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/72': (\n        'PKEY_DeviceDisplay_IsMetadataSearchInProgress'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/73': (\n        'PKEY_DeviceDisplay_MetadataChecksum'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/74': (\n        'PKEY_DeviceDisplay_IsNotInterestingForDisplay'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/76': (\n        'PKEY_DeviceDisplay_LaunchDeviceStageOnDeviceConnect'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/77': (\n        'PKEY_DeviceDisplay_LaunchDeviceStageFromExplorer'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/78': (\n        'PKEY_DeviceDisplay_BaselineExperienceId'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/79': (\n        'PKEY_DeviceDisplay_IsDeviceUniquelyIdentifiable'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/80': (\n        'PKEY_DeviceDisplay_AssociationArray'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/81': (\n        'PKEY_DeviceDisplay_DeviceDescription1'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/82': (\n        'PKEY_DeviceDisplay_DeviceDescription2'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/83': (\n        'PKEY_DeviceDisplay_IsNotWorkingProperly'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/84': 'PKEY_Devices_IsSharedDevice',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/85': (\n        'PKEY_Devices_IsNetworkConnected'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/86': (\n        'PKEY_DeviceDisplay_IsDefaultDevice'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/87': (\n        'PKEY_DeviceDisplay_MetadataCabinet'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/88': (\n        'PKEY_DeviceDisplay_RequiresPairingElevation'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/89': (\n        'PKEY_DeviceDisplay_ExperienceId'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/90': 'PKEY_Devices_CategoryIds',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/91': (\n        'PKEY_DeviceDisplay_Category_Desc_Singular'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/92': 'PKEY_Devices_CategoryPlural',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/93': (\n        'PKEY_DeviceDisplay_Category_Icon'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/94': 'PKEY_Devices_CategoryGroup',\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/95': (\n        'PKEY_DeviceDisplay_CategoryGroup_Icon'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/97': (\n        'PKEY_DeviceDisplay_PrimaryCategory'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/98': (\n        'PKEY_DeviceDisplay_UnpairUninstall'),\n    '{78c34fc8-104a-4aca-9ea4-524d52996e57}/99': (\n        'PKEY_DeviceDisplay_RequiresUninstallElevation'),\n    '{7996efb2-29c1-4898-be83-4a3646e06fac}/0': 'PKEY_Endpoint_Enable_LFX_AEC',\n    '{79d94e82-4d79-45aa-821a-74858b4e4ca6}/2': (\n        'PKEY_Devices_AepService_IoT_ServiceInterfaces'),\n    '{7a7d76f4-b630-4bd7-95ff-37cc51a975c9}/2': 'PKEY_Link_TargetExtension',\n    '{7abcf4f8-7c3f-4988-ac91-8d2c2e97eca5}/100': (\n        'PKEY_GPS_DestBearingDenominator'),\n    '{7b03b546-fa4f-4a52-a2fe-03d5311e5865}/100': (\n        'PKEY_Search_ExtendedProperties'),\n    '{7b9f6399-0a3f-4b12-89bd-4adc51c918af}/100': (\n        'PKEY_Contact_HomeAddressPostOfficeBox'),\n    '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/10': 'PKEY_Sync_Status',\n    '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/13': 'PKEY_Sync_Comments',\n    '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/2': 'PKEY_Sync_HandlerCollectionID',\n    '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/23': 'PKEY_Sync_ProgressPercentage',\n    '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/24': 'PKEY_Sync_State',\n    '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/3': 'PKEY_Sync_HandlerID',\n    '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/6': 'PKEY_Sync_ItemID',\n    '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/8': 'PKEY_Sync_HandlerType',\n    '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/9': 'PKEY_Sync_HandlerTypeLabel',\n    '{7d122d5a-ae5e-4335-8841-d71e7ce72f53}/100': 'PKEY_GPS_SpeedDenominator',\n    '{7d683fc9-d155-45a8-bb1f-89d19bcb792f}/100': 'PKEY_Identity_DisplayName',\n    '{7ddaaad1-ccc8-41ae-b750-b2cb8031aea2}/100': 'PKEY_GPS_LatitudeNumerator',\n    '{7f73d4e1-91e3-4490-9fba-5e86680a5748}/0': 'PKEY_Endpoint_Enable_GFX',\n    '{7fd7259d-16b4-4135-9f97-7c96ecd2fa9e}/100': 'PKEY_PropGroup_Message',\n    '{7fe3aa27-2648-42f3-89b0-454e5cb150c3}/100': 'PKEY_Photo_ProgramModeText',\n    '{80497100-8c73-48b9-aad9-ce387e19c56e}/2': 'PKEY_Device_Reported',\n    '{80497100-8c73-48b9-aad9-ce387e19c56e}/3': 'PKEY_Device_Legacy',\n    '{807b653a-9e91-43ef-8f97-11ce04ee20c5}/100': 'PKEY_Communication_Suffix',\n    '{80d81ea6-7473-4b0c-8216-efc11a2c4c8b}/2': 'PKEY_Devices_ModelId',\n    '{80f41eb8-afc4-4208-aa5f-cce21a627281}/100': (\n        'PKEY_Contact_ConnectedServiceIdentities'),\n    '{813f4124-34e6-4d17-ab3e-6b1f3c2247a1}/100': 'PKEY_Photo_MakerNoteOffset',\n    '{818d3b4c-2bbf-40e9-a438-9361b0ffc427}/0': (\n        'PKEY_Endpoint_Enable_LFX_BEAMFORMING'),\n    '{821437d6-9eab-4765-a589-3b1cbbd22a61}/100': (\n        'PKEY_Photo_PhotometricInterpretationText'),\n    '{827edb4f-5b73-44a7-891d-fdffabea35ca}/100': 'PKEY_GPS_Altitude',\n    '{83a6347e-6fe4-4f40-ba9c-c4865240d1f4}/100': (\n        'PKEY_Communication_FollowupIconIndex'),\n    '{83da6326-97a6-4088-9453-a1923f573b29}/9': (\n        'PKEY_DeviceDisplay_InstallInProgress'),\n    '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/10': 'PKEY_PROVIDER_TOOLTIPS',\n    '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/11': 'PKEY_PROVIDER_ICON',\n    '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/2': 'PKEY_PROVIDER_INSTANCEID',\n    '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/3': 'PKEY_PROVIDER_CLSID',\n    '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/4': 'PKEY_PROVIDER_CONFIGUI',\n    '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/5': 'PKEY_PROVIDER_CONTENTTYPE',\n    '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/6': 'PKEY_PROVIDER_CAPABILITIES',\n    '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/7': (\n        'PKEY_PROVIDER_SUPPORTED_ARCHITECTURE'),\n    '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/8': 'PKEY_PROVIDER_NAME',\n    '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/9': 'PKEY_PROVIDER_DESCRIPTION',\n    '{841e4f90-ff59-4d16-8947-e81bbffab36d}/16': 'PKEY_Software_DateLastUsed',\n    '{847c66de-b8d6-4af9-abc3-6f4f926bc039}/14': (\n        'PKEY_DeviceInterface_PrinterDriverDirectory'),\n    '{84d8f337-981d-44b3-9615-c7596dba17e3}/100': 'PKEY_Contact_EmailAddresses',\n    '{8589e481-6040-473d-b171-7fa89c2708ed}/100': (\n        'PKEY_Contact_CompanyMainTelephone'),\n    '{8619a4b6-9f4d-4429-8c0f-b996ca59e335}/100': (\n        'PKEY_Communication_SecurityFlags'),\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/11': 'PKEY_Tile_LongDisplayName',\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/12': (\n        'PKEY_Tile_Square150x150LogoPath'),\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/13': (\n        'PKEY_Tile_Wide310x150LogoPath'),\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/14': 'PKEY_Tile_Flags',\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/15': 'PKEY_Tile_BadgeLogoPath',\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/16': 'PKEY_Tile_SuiteDisplayName',\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/17': 'PKEY_Tile_SuiteSortName',\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/18': (\n        'PKEY_Tile_DisplayNameLanguage'),\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/19': (\n        'PKEY_Tile_Square310x310LogoPath'),\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/2': 'PKEY_Tile_SmallLogoPath',\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/20': (\n        'PKEY_Tile_Square70x70LogoPath'),\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/21': 'PKEY_Tile_FencePost',\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/22': 'PKEY_Tile_InstallProgress',\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/23': 'PKEY_Tile_EncodedTargetPath',\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/4': 'PKEY_Tile_Background',\n    '{86d40b4d-9069-443c-819a-2a54090dccec}/5': 'PKEY_Tile_Foreground',\n    '{8727cfff-4868-4ec6-ad5b-81b98521d1ab}/100': 'PKEY_GPS_Latitude',\n    '{8807cae6-7db6-4f10-8ee4-435eaa1392bc}/1': 'PKEY_Pairing_ListItemText',\n    '{8807cae6-7db6-4f10-8ee4-435eaa1392bc}/16': (\n        'PKEY_Pairing_IsWifiOnlyDevice'),\n    '{8807cae6-7db6-4f10-8ee4-435eaa1392bc}/2': (\n        'PKEY_Pairing_ListItemDescription'),\n    '{8807cae6-7db6-4f10-8ee4-435eaa1392bc}/3': 'PKEY_Pairing_ListItemIcon',\n    '{8807cae6-7db6-4f10-8ee4-435eaa1392bc}/4': 'PKEY_Pairing_ListItemDefault',\n    '{880f70a2-6082-47ac-8aab-a739d1a300c3}/151': 'PKEY_Devices_SharedTooltip',\n    '{880f70a2-6082-47ac-8aab-a739d1a300c3}/152': (\n        'PKEY_Devices_NetworkedTooltip'),\n    '{880f70a2-6082-47ac-8aab-a739d1a300c3}/153': 'PKEY_Devices_DefaultTooltip',\n    '{88190b80-4684-11da-a26a-0002b3988e81}/1': 'PKEY_WCN_Version',\n    '{88190b81-4684-11da-a26a-0002b3988e81}/2': 'PKEY_WCN_RequestType',\n    '{88190b82-4684-11da-a26a-0002b3988e81}/3': 'PKEY_WCN_AuthType',\n    '{88190b83-4684-11da-a26a-0002b3988e81}/4': 'PKEY_WCN_EncryptType',\n    '{88190b84-4684-11da-a26a-0002b3988e81}/5': 'PKEY_WCN_ConnType',\n    '{88190b85-4684-11da-a26a-0002b3988e81}/6': 'PKEY_WCN_ConfigMethods',\n    '{88190b86-4684-11da-a26a-0002b3988e81}/7': 'PKEY_WCN_DeviceType',\n    '{88190b87-4684-11da-a26a-0002b3988e81}/8': 'PKEY_WCN_RfBand',\n    '{88190b88-4684-11da-a26a-0002b3988e81}/9': 'PKEY_WCN_AssocState',\n    '{88190b89-4684-11da-a26a-0002b3988e81}/10': 'PKEY_WCN_ConfigError',\n    '{88190b89-4684-11da-a26a-0002b3988e81}/11': 'PKEY_WCN_ConfigState',\n    '{88190b89-4684-11da-a26a-0002b3988e81}/12': 'PKEY_WCN_DevicePasswordId',\n    '{88190b89-4684-11da-a26a-0002b3988e81}/13': 'PKEY_WCN_OSVersion',\n    '{88190b8a-4684-11da-a26a-0002b3988e81}/14': 'PKEY_WCN_VendorExtension',\n    '{88190b8b-4684-11da-a26a-0002b3988e81}/15': 'PKEY_WCN_RegistrarType',\n    '{88190b8b-4684-11da-a26a-0002b3988e81}/16': 'PKEY_WCN_DeviceType_Category',\n    '{88190b8b-4684-11da-a26a-0002b3988e81}/17': (\n        'PKEY_WCN_DeviceType_SubCategoryOUI'),\n    '{88190b8b-4684-11da-a26a-0002b3988e81}/18': (\n        'PKEY_WCN_DeviceType_SubCategory'),\n    '{88190b8b-4684-11da-a26a-0002b3988e81}/32': 'PKEY_WCN_SSID',\n    '{8859a284-de7e-4642-99ba-d431d044b1ec}/100': (\n        'PKEY_PropGroup_MediaAdvanced'),\n    '{8943b373-388c-4395-b557-bc6dbaffafdb}/2': (\n        'PKEY_Devices_AudioDevice_RawProcessingSupported'),\n    '{8943b373-388c-4395-b557-bc6dbaffafdb}/3': (\n        'PKEY_Devices_AudioDevice_Microphone_SensitivityInDbfs'),\n    '{8943b373-388c-4395-b557-bc6dbaffafdb}/4': (\n        'PKEY_Devices_AudioDevice_Microphone_SignalToNoiseRatioInDb'),\n    '{8943b373-388c-4395-b557-bc6dbaffafdb}/5': (\n        'PKEY_Devices_AudioDevice_Microphone_SensitivityInDbfs2'),\n    '{8969b275-9475-4e00-a887-ff93b8b41e44}/100': 'PKEY_PropGroup_Description',\n    '{897b3694-fe9e-43e6-8066-260f590c0100}/2': (\n        'PKEY_Contact_JA_CompanyNamePhonetic'),\n    '{897b3694-fe9e-43e6-8066-260f590c0100}/3': (\n        'PKEY_Contact_JA_FirstNamePhonetic'),\n    '{897b3694-fe9e-43e6-8066-260f590c0100}/4': (\n        'PKEY_Contact_JA_LastNamePhonetic'),\n    '{8a2f99f9-3c37-465d-a8d7-69777a246d0c}/2': 'PKEY_Link_FeedItemLocalId',\n    '{8a2f99f9-3c37-465d-a8d7-69777a246d0c}/5': 'PKEY_Link_TargetUrlHostName',\n    '{8a2f99f9-3c37-465d-a8d7-69777a246d0c}/6': 'PKEY_Link_TargetUrlPath',\n    '{8af4961c-f526-43e5-aa81-db768219178d}/100': (\n        'PKEY_Photo_SubjectDistanceNumerator'),\n    '{8afcc170-8a46-4b53-9eee-90bae7151e62}/100': (\n        'PKEY_Contact_HomeAddressPostalCode'),\n    '{8b26ea41-058f-43f6-aecc-4035681ce977}/100': (\n        'PKEY_Contact_OtherAddressPostOfficeBox'),\n    '{8c3b93a4-baed-1a83-9a32-102ee313f6eb}/100': 'PKEY_Identity_Blob',\n    '{8c7ed206-3f8a-4827-b3ab-ae9e1faefc6c}/2': 'PKEY_Devices_ContainerId',\n    '{8c7ed206-3f8a-4827-b3ab-ae9e1faefc6c}/4': (\n        'PKEY_Devices_InLocalMachineContainer'),\n    '{8e531030-b960-4346-ae0d-66bc9a86fb94}/100': (\n        'PKEY_Communication_Direction'),\n    '{8e8ecf7c-b7b8-4eb8-a63f-0ee715c96f9e}/100': (\n        'PKEY_Photo_GainControlNumerator'),\n    '{8f167568-0aae-4322-8ed9-6055b7b0e398}/100': (\n        'PKEY_Contact_OtherAddressCountry'),\n    '{8f367200-c270-457c-b1d4-e07c5bcd90c7}/100': 'PKEY_Contact_LastName',\n    '{8fdc6dea-b929-412b-ba90-397a257465fe}/100': 'PKEY_Contact_CarTelephone',\n    '{900a403b-097b-4b95-8ae2-071fdaeeb118}/100': 'PKEY_PropGroup_Advanced',\n    '{90197ca7-fd8f-4e8c-9da3-b57e1e609295}/100': 'PKEY_RatingText',\n    '{908696c7-8f87-44f2-80ed-a8c1c6894575}/2': 'PKEY_LibraryLocationsCount',\n    '{9098f33c-9a7d-48a8-8de5-2e1227a64e91}/100': (\n        'PKEY_Message_ProofInProgress'),\n    '{90e5e14e-648b-4826-b2aa-acaf790e3513}/10': 'PKEY_IsEncrypted',\n    '{91eff6f3-2e27-42ca-933e-7c999fbe310b}/100': (\n        'PKEY_Contact_BusinessFaxNumber'),\n    '{93112f89-c28b-492f-8a9d-4be2062cee8a}/100': (\n        'PKEY_Photo_ExposureIndexDenominator'),\n    '{95beb1fc-326d-4644-b396-cd3ed90e6ddf}/100': 'PKEY_Journal_EntryType',\n    '{95c656c1-2abf-4148-9ed3-9ec602e3b7cd}/100': (\n        'PKEY_Contact_OtherAddressPostalCode'),\n    '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/2': (\n        'PKEY_DeviceInterface_WinUsb_UsbVendorId'),\n    '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/3': (\n        'PKEY_DeviceInterface_WinUsb_UsbProductId'),\n    '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/4': (\n        'PKEY_DeviceInterface_WinUsb_UsbClass'),\n    '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/5': (\n        'PKEY_DeviceInterface_WinUsb_UsbSubClass'),\n    '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/6': (\n        'PKEY_DeviceInterface_WinUsb_UsbProtocol'),\n    '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/7': (\n        'PKEY_DeviceInterface_WinUsb_DeviceInterfaceClasses'),\n    '{9660c283-fc3a-4a08-a096-eed3aac46da2}/100': 'PKEY_Contact_DataSuppliers',\n    '{967b5af8-995a-46ed-9e11-35b3c5b9782d}/100': 'PKEY_Photo_ExposureIndex',\n    '{972e333e-ac7e-49f1-8adf-a70d07a9bcab}/100': 'PKEY_GPS_AreaInformation',\n    '{9744311e-7951-4b2e-b6f0-ecb293cac119}/5': (\n        'PKEY_Devices_AepService_Bluetooth_CacheMode'),\n    '{9744311e-7951-4b2e-b6f0-ecb293cac119}/6': (\n        'PKEY_Devices_AepService_Bluetooth_GattService_Device'),\n    '{9744311e-7951-4b2e-b6f0-ecb293cac119}/7': (\n        'PKEY_Devices_AepService_Bluetooth_RfcommService_CacheMode'),\n    '{9744311e-7951-4b2e-b6f0-ecb293cac119}/8': (\n        'PKEY_Devices_AepService_Bluetooth_RfcommService_Device'),\n    '{97b0ad89-df49-49cc-834e-660974fd755b}/100': 'PKEY_Contact_Label',\n    '{98f98354-617a-46b8-8560-5b1b64bf1f89}/100': 'PKEY_Contact_HomeAddress',\n    '{995ef0b0-7eb3-4a8b-b9ce-068bb3f4af69}/1': (\n        'PKEY_Devices_Aep_Bluetooth_Le_Appearance'),\n    '{995ef0b0-7eb3-4a8b-b9ce-068bb3f4af69}/4': (\n        'PKEY_Devices_Aep_Bluetooth_Le_AddressType'),\n    '{995ef0b0-7eb3-4a8b-b9ce-068bb3f4af69}/5': (\n        'PKEY_Devices_Aep_Bluetooth_Le_Appearance_Category'),\n    '{995ef0b0-7eb3-4a8b-b9ce-068bb3f4af69}/6': (\n        'PKEY_Devices_Aep_Bluetooth_Le_Appearance_Subcategory'),\n    '{995ef0b0-7eb3-4a8b-b9ce-068bb3f4af69}/8': (\n        'PKEY_Devices_Aep_Bluetooth_Le_IsConnectable'),\n    '{9973d2b5-bfd8-438a-ba94-5349b293181a}/100': 'PKEY_PropGroup_Calendar',\n    '{9a8ebb75-6458-4e82-bacb-35c0095b03bb}/100': (\n        'PKEY_Photo_TranscodedForSync'),\n    '{9a93244d-a7ad-4ff8-9b99-45ee4cc09af6}/100': (\n        'PKEY_Contact_AssistantTelephone'),\n    '{9a9bc088-4f6d-469e-9919-e705412040f9}/100': 'PKEY_Message_IsFwdOrReply',\n    '{9ab84393-2a0f-4b75-bb22-7279786977cb}/100': 'PKEY_GPS_DestBearingRef',\n    '{9ad5badb-cea7-4470-a03d-b84e51b9949e}/100': 'PKEY_Contact_Anniversary',\n    '{9aebae7a-9644-487d-a92c-657585ed751a}/100': (\n        'PKEY_Media_SubscriptionContentId'),\n    '{9b174b34-40ff-11d2-a27e-00c04fc30871}/4': 'PKEY_FileOwner',\n    '{9b174b35-40ff-11d2-a27e-00c04fc30871}/10': 'PKEY_Volume_IsRoot',\n    '{9b174b35-40ff-11d2-a27e-00c04fc30871}/2': 'PKEY_FreeSpace',\n    '{9b174b35-40ff-11d2-a27e-00c04fc30871}/3': 'PKEY_Capacity',\n    '{9b174b35-40ff-11d2-a27e-00c04fc30871}/4': 'PKEY_Volume_FileSystem',\n    '{9b174b35-40ff-11d2-a27e-00c04fc30871}/5': 'PKEY_PercentFull',\n    '{9b174b35-40ff-11d2-a27e-00c04fc30871}/7': (\n        'PKEY_Computer_DecoratedFreeSpace'),\n    '{9bc2c99b-ac71-4127-9d1c-2596d0d7dcb7}/100': (\n        'PKEY_GPS_DestDistanceDenominator'),\n    '{9c1fcf74-2d97-41ba-b4ae-cb2e3661a6e4}/5': 'PKEY_Priority',\n    '{9c1fcf74-2d97-41ba-b4ae-cb2e3661a6e4}/8': 'PKEY_Message_HasAttachments',\n    '{9cb0c358-9d7a-46b1-b466-dcc6f1a3d93d}/100': (\n        'PKEY_Contact_DisplayMobilePhoneNumbers'),\n    '{9d1d7cc5-5c39-451c-86b3-928e2d18cc47}/100': 'PKEY_GPS_DestLatitude',\n    '{9d2408b6-3167-422b-82b0-f583b7a7cfe3}/100': 'PKEY_Contact_SpouseName',\n    '{9e7d118f-b314-45a0-8cfb-d654b917c9e9}/100': (\n        'PKEY_Photo_BrightnessNumerator'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/10': (\n        'PKEY_AppUserModel_BestShortcut'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/11': 'PKEY_AppUserModel_IsDualMode',\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/12': (\n        'PKEY_AppUserModel_StartPinOption'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/13': 'PKEY_AppUserModel_Relevance',\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/14': (\n        'PKEY_AppUserModel_HostEnvironment'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/15': (\n        'PKEY_AppUserModel_PackageInstallPath'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/16': (\n        'PKEY_AppUserModel_RecordState'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/17': (\n        'PKEY_AppUserModel_PackageFamilyName'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/18': (\n        'PKEY_AppUserModel_InstalledBy'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/19': 'PKEY_AppUserModel_ParentID',\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/2': (\n        'PKEY_AppUserModel_RelaunchCommand'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/20': (\n        'PKEY_AppUserModel_ActivationContext'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/21': (\n        'PKEY_AppUserModel_PackageFullName'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/22': (\n        'PKEY_AppUserModel_PackageRelativeApplicationID'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/23': (\n        'PKEY_AppUserModel_ExcludedFromLauncher'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/25': 'PKEY_AppUserModel_RunFlags',\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/26': (\n        'PKEY_AppUserModel_ToastActivatorCLSID'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/27': (\n        'PKEY_AppUserModel_DestListProvidedTitle'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/28': (\n        'PKEY_AppUserModel_DestListProvidedDescription'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/29': (\n        'PKEY_AppUserModel_DestListLogoUri'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/3': (\n        'PKEY_AppUserModel_RelaunchIconResource'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/30': (\n        'PKEY_AppUserModel_DestListProvidedGroupName'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/4': (\n        'PKEY_AppUserModel_RelaunchDisplayNameResource'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/5': 'PKEY_AppUserModel_ID',\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/6': (\n        'PKEY_AppUserModel_IsDestListSeparator'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/7': (\n        'PKEY_AppUserModel_IsDestListLink'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/8': (\n        'PKEY_AppUserModel_ExcludeFromShowInNewInstall'),\n    '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/9': (\n        'PKEY_AppUserModel_PreventPinning'),\n    '{a00742a1-cd8c-4b37-95ab-70755587767a}/3': (\n        'PKEY_DeviceInterface_PrinterEnumerationFlag'),\n    '{a015ed5d-aaea-4d58-8a86-3c586920ea0b}/100': 'PKEY_GPS_MeasureMode',\n    '{a06992b3-8caf-4ed7-a547-b259e32ac9fc}/100': 'PKEY_Search_Store',\n    '{a09f084e-ad41-489f-8076-aa5be3082bca}/100': 'PKEY_SimpleRating',\n    '{a0be94c5-50ba-487b-bd35-0654be8881ed}/100': 'PKEY_GPS_DOPDenominator',\n    '{a0e00ee1-f0c7-4d41-b8e7-26a7bd8d38b0}/2': (\n        'PKEY_Devices_Notifications_StorageFull'),\n    '{a0e00ee1-f0c7-4d41-b8e7-26a7bd8d38b0}/3': (\n        'PKEY_Devices_Notification_StorageFullLinkText'),\n    '{a0e74609-b84d-4f49-b860-462bd9971f98}/100': (\n        'PKEY_Photo_FocalLengthInFilm'),\n    '{a1829ea2-27eb-459e-935d-b2fad7b07762}/2': (\n        'PKEY_Devices_MicrophoneArray_Geometry'),\n    '{a19fb7a9-024b-4371-a8bf-4d29c3e4e9c9}/100': (\n        'PKEY_Contact_ConnectedServiceSupportedActions'),\n    '{a26f4afc-7346-4299-be47-eb1ae613139f}/100': 'PKEY_Identity',\n    '{a26f4afc-7346-4299-be47-eb1ae613139f}/16': (\n        'PKEY_Identity_KeyProviderName'),\n    '{a26f4afc-7346-4299-be47-eb1ae613139f}/17': (\n        'PKEY_Identity_KeyProviderContext'),\n    '{a2e541c5-4440-4ba8-867e-75cfc06828cd}/100': (\n        'PKEY_Photo_FocalPlaneYResolutionNumerator'),\n    '{a3250282-fb6d-48d5-9a89-dbcace75cccf}/100': (\n        'PKEY_GPS_DestLongitudeNumerator'),\n    '{a35996ab-11cf-4935-8b61-a6761081ecdf}/12': (\n        'PKEY_Devices_Aep_DeviceAddress'),\n    '{a35996ab-11cf-4935-8b61-a6761081ecdf}/16': 'PKEY_Devices_Aep_IsPaired',\n    '{a35996ab-11cf-4935-8b61-a6761081ecdf}/17': 'PKEY_Devices_Aep_Category',\n    '{a35996ab-11cf-4935-8b61-a6761081ecdf}/3': 'PKEY_Devices_Aep_ModelName',\n    '{a35996ab-11cf-4935-8b61-a6761081ecdf}/4': 'PKEY_Devices_Aep_ModelId',\n    '{a35996ab-11cf-4935-8b61-a6761081ecdf}/5': 'PKEY_Devices_Aep_Manufacturer',\n    '{a35996ab-11cf-4935-8b61-a6761081ecdf}/6': (\n        'PKEY_Devices_Aep_SignalStrength'),\n    '{a35996ab-11cf-4935-8b61-a6761081ecdf}/7': 'PKEY_Devices_Aep_IsConnected',\n    '{a35996ab-11cf-4935-8b61-a6761081ecdf}/9': 'PKEY_Devices_Aep_IsPresent',\n    '{a399aac7-c265-474e-b073-ffce57721716}/2': (\n        'PKEY_Devices_AepService_Bluetooth_ServiceGuid'),\n    '{a3b29791-7713-4e1d-bb40-17db85f01831}/100': 'PKEY_ImportanceText',\n    '{a4108708-09df-4377-9dfc-6d99986d5a67}/100': 'PKEY_Identity_IsMeIdentity',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/10': 'PKEY_Devices_ClassGuid',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/11': 'PKEY_Device_Driver',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/12': 'PKEY_Device_ConfigFlags',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/13': (\n        'PKEY_Devices_DeviceManufacturer'),\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/14': 'PKEY_Device_FriendlyName',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/15': 'PKEY_Device_LocationInfo',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/16': 'PKEY_Device_PDOName',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/17': (\n        'PKEY_Devices_DeviceCapabilities'),\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/18': 'PKEY_Device_UINumber',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/19': 'PKEY_Device_UpperFilters',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/2': 'PKEY_AudioEndPoint_Interface',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/20': 'PKEY_Device_LowerFilters',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/21': 'PKEY_Device_BusTypeGuid',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/22': 'PKEY_Device_LegacyBusType',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/23': 'PKEY_Device_BusNumber',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/24': 'PKEY_Device_EnumeratorName',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/25': 'PKEY_Device_Security',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/26': 'PKEY_Device_SecuritySDS',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/27': 'PKEY_Device_DevType',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/28': 'PKEY_Device_Exclusive',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/29': 'PKEY_Device_Characteristics',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/3': 'PKEY_Devices_HardwareIds',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/30': 'PKEY_Device_Address',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/31': (\n        'PKEY_Device_UINumberDescFormat'),\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/32': 'PKEY_Device_PowerData',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/33': 'PKEY_Device_RemovalPolicy',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/34': (\n        'PKEY_Device_RemovalPolicyDefault'),\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/35': (\n        'PKEY_Device_RemovalPolicyOverride'),\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/36': 'PKEY_Device_InstallState',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/37': 'PKEY_Devices_LocationPaths',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/4': 'PKEY_Device_CompatibleIds',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/6': 'PKEY_Device_Service',\n    '{a45c254e-df1c-4efd-8020-67d146a850e0}/9': 'PKEY_Device_Class',\n    '{a4aaa5b7-1ad0-445f-811a-0f8f6e67f6b5}/100': 'PKEY_GPS_ImgDirectionRef',\n    '{a5477f61-7a82-4eca-9dde-98b69b2479b3}/100': (\n        'PKEY_RecordedTV_RecordingTime'),\n    '{a6744477-c237-475b-a075-54f34498292a}/100': (\n        'PKEY_Communication_TaskStatusText'),\n    '{a6f360d2-55f9-48de-b909-620e090a647c}/100': 'PKEY_IsFlaggedComplete',\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/101': (\n        'PKEY_Contact_HomeAddress1Street'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/102': (\n        'PKEY_Contact_HomeAddress1Locality'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/103': (\n        'PKEY_Contact_HomeAddress1Region'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/104': (\n        'PKEY_Contact_HomeAddress1Country'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/105': (\n        'PKEY_Contact_HomeAddress1PostalCode'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/106': (\n        'PKEY_Contact_HomeAddress2Street'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/107': (\n        'PKEY_Contact_HomeAddress2Locality'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/108': (\n        'PKEY_Contact_HomeAddress2Region'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/109': (\n        'PKEY_Contact_HomeAddress2Country'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/110': (\n        'PKEY_Contact_HomeAddress2PostalCode'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/111': (\n        'PKEY_Contact_HomeAddress3Street'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/112': (\n        'PKEY_Contact_HomeAddress3Locality'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/113': (\n        'PKEY_Contact_HomeAddress3Region'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/114': (\n        'PKEY_Contact_HomeAddress3Country'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/115': (\n        'PKEY_Contact_HomeAddress3PostalCode'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/116': (\n        'PKEY_Contact_BusinessAddress1Street'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/117': (\n        'PKEY_Contact_BusinessAddress1Locality'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/118': (\n        'PKEY_Contact_BusinessAddress1Region'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/119': (\n        'PKEY_Contact_BusinessAddress1Country'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/120': (\n        'PKEY_Contact_BusinessAddress1PostalCode'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/121': (\n        'PKEY_Contact_BusinessAddress2Street'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/122': (\n        'PKEY_Contact_BusinessAddress2Locality'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/123': (\n        'PKEY_Contact_BusinessAddress2Region'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/124': (\n        'PKEY_Contact_BusinessAddress2Country'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/125': (\n        'PKEY_Contact_BusinessAddress2PostalCode'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/126': (\n        'PKEY_Contact_BusinessAddress3Street'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/127': (\n        'PKEY_Contact_BusinessAddress3Locality'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/128': (\n        'PKEY_Contact_BusinessAddress3Region'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/129': (\n        'PKEY_Contact_BusinessAddress3Country'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/130': (\n        'PKEY_Contact_BusinessAddress3PostalCode'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/131': (\n        'PKEY_Contact_OtherAddress1Street'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/132': (\n        'PKEY_Contact_OtherAddress1Locality'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/133': (\n        'PKEY_Contact_OtherAddress1Region'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/134': (\n        'PKEY_Contact_OtherAddress1Country'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/135': (\n        'PKEY_Contact_OtherAddress1PostalCode'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/136': (\n        'PKEY_Contact_OtherAddress2Street'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/137': (\n        'PKEY_Contact_OtherAddress2Locality'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/138': (\n        'PKEY_Contact_OtherAddress2Region'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/139': (\n        'PKEY_Contact_OtherAddress2Country'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/140': (\n        'PKEY_Contact_OtherAddress2PostalCode'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/141': (\n        'PKEY_Contact_OtherAddress3Street'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/142': (\n        'PKEY_Contact_OtherAddress3Locality'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/143': (\n        'PKEY_Contact_OtherAddress3Region'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/144': (\n        'PKEY_Contact_OtherAddress3Country'),\n    '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/145': (\n        'PKEY_Contact_OtherAddress3PostalCode'),\n    '{a7fe0840-1344-46f0-8d37-52ed712a4bf9}/100': (\n        'PKEY_ParentalRatingsOrganization'),\n    '{a82d9ee7-ca67-4312-965e-226bcea85023}/100': 'PKEY_Message_Flags',\n    '{a8a74b92-361b-4e9a-b722-7c4a7330a312}/100': 'PKEY_Identity_ProviderData',\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/10': (\n        'PKEY_Device_DriverPropPageProvider'),\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/11': (\n        'PKEY_Device_DriverCoInstallers'),\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/12': (\n        'PKEY_Device_ResourcePickerTags'),\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/13': (\n        'PKEY_Device_ResourcePickerExceptions'),\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/14': 'PKEY_Device_DriverRank',\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/15': 'PKEY_Device_DriverLogoLevel',\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/17': 'PKEY_Device_NoConnectSound',\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/18': (\n        'PKEY_Device_GenericDriverInstalled'),\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/2': 'PKEY_Device_DriverDate',\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/3': 'PKEY_Device_DriverVersion',\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/4': 'PKEY_Device_DriverDesc',\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/5': 'PKEY_Device_DriverInfPath',\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/6': 'PKEY_Device_DriverInfSection',\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/7': (\n        'PKEY_Device_DriverInfSectionExt'),\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/8': 'PKEY_Device_MatchingDeviceId',\n    '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/9': 'PKEY_Device_DriverProvider',\n    '{a93eae04-6804-4f24-ac81-09b266452118}/100': 'PKEY_GPS_DestDistance',\n    '{a94688b6-7d9f-4570-a648-e3dfc0ab2b3f}/100': 'PKEY_OfflineAvailability',\n    '{a988f78b-07b6-4f47-9c9f-25409534cdee}/0': 'PKEY_Endpoint_Enable_LFX',\n    '{a9ea193c-c511-498a-a06b-58e2776dcc28}/100': 'PKEY_Photo_OrientationText',\n    '{aaa660f9-9865-458e-b484-01bc7fe3973e}/100': 'PKEY_Calendar_OrganizerName',\n    '{aabaf6c9-e0c5-4719-8585-57b103e584fe}/100': (\n        'PKEY_Photo_FlashManufacturer'),\n    '{aaf16bac-2b55-45e6-9f6d-415eb94910df}/100': (\n        'PKEY_Contact_TTYTDDTelephone'),\n    '{aaf4ee25-bd3b-4dd7-bfc4-47f77bb00f6d}/100': 'PKEY_GPS_Differential',\n    '{ab205e50-04b7-461c-a18c-2f233836e627}/100': (\n        'PKEY_Photo_ExposureBiasDenominator'),\n    '{acc9ce3d-c213-4942-8b48-6d0820f21c6d}/100': 'PKEY_GPS_SpeedNumerator',\n    '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/2': 'PKEY_DRM_IsProtected',\n    '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/3': 'PKEY_DRM_Description',\n    '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/4': 'PKEY_DRM_PlayCount',\n    '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/5': 'PKEY_DRM_DatePlayStarts',\n    '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/6': 'PKEY_DRM_DatePlayExpires',\n    '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/7': 'PKEY_DRM_IsDisabled',\n    '{afc47170-14f5-498c-8f30-b0d19be449c6}/11': (\n        'PKEY_DeviceInterface_PrinterDriverName'),\n    '{afd97640-86a3-4210-b67c-289c41aabe55}/2': (\n        'PKEY_Devices_SafeRemovalRequired'),\n    '{b0b87314-fcf6-4feb-8dff-a50da6af561c}/100': (\n        'PKEY_Contact_BusinessAddressCountry'),\n    '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/2': 'PKEY_FilePlaceholderStatus',\n    '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/3': (\n        'PKEY_StorageProviderFileIdentifier'),\n    '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/4': (\n        'PKEY_StorageProviderFileVersion'),\n    '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/5': (\n        'PKEY_StorageProviderFileChecksum'),\n    '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/6': (\n        'PKEY_StorageProviderFileVersionWaterline'),\n    '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/7': (\n        'PKEY_StorageProviderCallerVersionInformation'),\n    '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/8': 'PKEY_StorageProviderFileFlags',\n    '{b33af30b-f552-4584-936c-cb93e5cda29f}/100': (\n        'PKEY_Calendar_RequiredAttendeeNames'),\n    '{b3f8fa53-0004-438e-9003-51a46e139bfc}/5': 'PKEY_SupportFormat_OEMFormat',\n    '{b3f8fa53-0004-438e-9003-51a46e139bfc}/6': 'PKEY_Endpoint_Name',\n    '{b5c84c9e-5927-46b5-a3cc-933c21b78469}/100': (\n        'PKEY_Contact_ConnectedServiceName'),\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/10': 'PKEY_DisplayName',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/12': 'PKEY_Size',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/13': 'PKEY_FileAttributes',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/14': 'PKEY_DateModified',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/15': 'PKEY_DateCreated',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/16': 'PKEY_DateAccessed',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/18': 'PKEY_FileAllocationSize',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/19': 'PKEY_Search_Contents',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/2': 'PKEY_ItemFolderNameDisplay',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/21': 'PKEY_FileFRN',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/23': 'PKEY_ItemNameSortOverride',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/24': (\n        'PKEY_ItemNameDisplayWithoutExtension'),\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/25': 'PKEY_FolderNameDisplay',\n    '{b725f130-47ef-101a-a5f1-02608c9eebac}/4': 'PKEY_ItemTypeText',\n    '{b7b4d61c-5a64-4187-a52e-b1539f359099}/2': (\n        'PKEY_Devices_WinPhone8CameraFlags'),\n    '{b812f15d-c2d8-4bbf-bacd-79744346113f}/100': 'PKEY_Photo_TagViewAggregate',\n    '{b96eff7b-35ca-4a35-8607-29e3a54c46ea}/100': 'PKEY_IdentityProvider_Name',\n    '{b9b4b3fc-2b51-4a42-b5d8-324146afcf25}/2': 'PKEY_Link_TargetParsingPath',\n    '{b9b4b3fc-2b51-4a42-b5d8-324146afcf25}/3': 'PKEY_Link_Status',\n    '{b9b4b3fc-2b51-4a42-b5d8-324146afcf25}/5': 'PKEY_Link_Comment',\n    '{b9b4b3fc-2b51-4a42-b5d8-324146afcf25}/8': 'PKEY_Link_TargetSFGAOFlags',\n    '{ba3b1da9-86ee-4b5d-a2a4-a271a429f0cf}/100': (\n        'PKEY_GPS_DestBearingNumerator'),\n    '{bc4e71ce-17f9-48d5-bee9-021df0ea5409}/100': (\n        'PKEY_Contact_BusinessAddressPostOfficeBox'),\n    '{bccc8a3c-8cef-42e5-9b1c-c69079398bc7}/100': 'PKEY_Message_ToDoTitle',\n    '{bceee283-35df-4d53-826a-f36a3eefc6be}/100': 'PKEY_Search_ContainerHash',\n    '{be1a72c6-9a1d-46b7-afe7-afaf8cef4999}/100': (\n        'PKEY_Communication_TaskStatus'),\n    '{be6e176c-4534-4d2c-ace5-31dedac1606b}/100': (\n        'PKEY_GPS_LongitudeDenominator'),\n    '{bebe0920-7671-4c54-a3eb-49fddfc191ee}/100': 'PKEY_PropGroup_Video',\n    '{bf53d1c3-49e0-4f7f-8567-5a821d8ac542}/100': (\n        'PKEY_Contact_CallbackTelephone'),\n    '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/10': 'PKEY_Devices_Dnssd_Ttl',\n    '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/11': (\n        'PKEY_Devices_Dnssd_NetworkAdapterId'),\n    '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/12': (\n        'PKEY_Devices_Dnssd_PortNumber'),\n    '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/2': (\n        'PKEY_Devices_Dnssd_ServiceName'),\n    '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/3': 'PKEY_Devices_Dnssd_Domain',\n    '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/4': (\n        'PKEY_Devices_Dnssd_InstanceName'),\n    '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/5': 'PKEY_Devices_Dnssd_FullName',\n    '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/6': (\n        'PKEY_Devices_Dnssd_TextAttributes'),\n    '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/7': 'PKEY_Devices_Dnssd_HostName',\n    '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/8': 'PKEY_Devices_Dnssd_Weight',\n    '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/9': 'PKEY_Devices_Dnssd_Priority',\n    '{bfee9149-e3e2-49a7-a862-c05988145cec}/100': 'PKEY_Calendar_IsOnline',\n    '{c06238b2-0bf9-4279-a723-25856715cb9d}/100': 'PKEY_Photo_GainControlText',\n    '{c07b4199-e1df-4493-b1e1-de5946fb58f8}/100': 'PKEY_Address_Country',\n    '{c07b4199-e1df-4493-b1e1-de5946fb58f8}/101': 'PKEY_Address_CountryCode',\n    '{c07b4199-e1df-4493-b1e1-de5946fb58f8}/102': 'PKEY_Address_Region',\n    '{c07b4199-e1df-4493-b1e1-de5946fb58f8}/103': 'PKEY_Address_RegionCode',\n    '{c07b4199-e1df-4493-b1e1-de5946fb58f8}/104': 'PKEY_Address_Town',\n    '{c0ac206a-827e-4650-95ae-77e2bb74fcc9}/100': 'PKEY_Contact_MailingAddress',\n    '{c107e191-a459-44c5-9ae6-b952ad4b906d}/100': (\n        'PKEY_Photo_MaxApertureNumerator'),\n    '{c2ea046e-033c-4e91-bd5b-d4942f6bbe49}/2': 'PKEY_CreatorAppId',\n    '{c2ea046e-033c-4e91-bd5b-d4942f6bbe49}/3': 'PKEY_CreatorOpenWithUIOptions',\n    '{c4322503-78ca-49c6-9acc-a68e2afd7b6b}/100': 'PKEY_Identity_UserName',\n    '{c449d5cb-9ea4-4809-82e8-af9d59ded6d1}/100': 'PKEY_Music_IsCompilation',\n    '{c4c07f2b-8524-4e66-ae3a-a6235f103beb}/2': (\n        'PKEY_Devices_Notification_LowBattery'),\n    '{c4c4dbb2-b593-466b-bbda-d03d27d5e43a}/100': 'PKEY_GPS_Longitude',\n    '{c554493c-c1f7-40c1-a76c-ef8c0614003e}/100': 'PKEY_Contact_TelexNumber',\n    '{c66d4b3c-e888-47cc-b99f-9dca3ee34dea}/100': 'PKEY_GPS_DestBearing',\n    '{c75faa05-96fd-49e7-9cb4-9f601082d553}/100': 'PKEY_EndDate',\n    '{c77724d4-601f-46c5-9b89-c53f93bceb77}/100': (\n        'PKEY_Photo_MaxApertureDenominator'),\n    '{c89a23d0-7d6d-4eb8-87d4-776a82d493e5}/100': (\n        'PKEY_Contact_HomeAddressState'),\n    '{c8d1920c-01f6-40c0-ac86-2f3a4ad00770}/100': 'PKEY_GPS_TrackDenominator',\n    '{c8ea94f0-a9e3-4969-a94b-9c62a95324e0}/100': (\n        'PKEY_Contact_PrimaryAddressCity'),\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/10': (\n        'PKEY_PropList_FileOperationPrompt'),\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/11': 'PKEY_PropList_ConflictPrompt',\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/13': (\n        'PKEY_PropList_ContentViewModeForBrowse'),\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/14': (\n        'PKEY_PropList_ContentViewModeForSearch'),\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/17': 'PKEY_InfoTipText',\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/2': 'PKEY_PropList_FullDetails',\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/3': 'PKEY_PropList_TileInfo',\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/4': 'PKEY_PropList_InfoTip',\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/5': 'PKEY_PropList_QuickTip',\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/500': (\n        'PKEY_LayoutPattern_ContentViewModeForBrowse'),\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/501': (\n        'PKEY_LayoutPattern_ContentViewModeForSearch'),\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/6': 'PKEY_PropList_PreviewTitle',\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/8': 'PKEY_PropList_PreviewDetails',\n    '{c9944a21-a406-48fe-8225-aec7e24c211b}/9': (\n        'PKEY_PropList_ExtendedTileInfo'),\n    '{c9c141a9-1b4c-4f17-a9d1-f298538cadb8}/2': (\n        'PKEY_Devices_AepService_ServiceId'),\n    '{c9c141a9-1b4c-4f17-a9d1-f298538cadb8}/5': (\n        'PKEY_Devices_AepService_ProtocolId'),\n    '{c9c141a9-1b4c-4f17-a9d1-f298538cadb8}/6': 'PKEY_Devices_AepService_AepId',\n    '{c9c141a9-1b4c-4f17-a9d1-f298538cadb8}/7': (\n        'PKEY_Devices_AepService_ParentAepIsPaired'),\n    '{c9c34f84-2241-4401-b607-bd20ed75ae7f}/100': (\n        'PKEY_Communication_HeaderItem'),\n    '{cbf38310-4a17-4310-a1eb-247f0b67593b}/2': (\n        'PKEY_DeviceInterface_Hid_UsagePage'),\n    '{cbf38310-4a17-4310-a1eb-247f0b67593b}/3': (\n        'PKEY_DeviceInterface_Hid_UsageId'),\n    '{cbf38310-4a17-4310-a1eb-247f0b67593b}/4': (\n        'PKEY_DeviceInterface_Hid_IsReadOnly'),\n    '{cbf38310-4a17-4310-a1eb-247f0b67593b}/5': (\n        'PKEY_DeviceInterface_Hid_VendorId'),\n    '{cbf38310-4a17-4310-a1eb-247f0b67593b}/6': (\n        'PKEY_DeviceInterface_Hid_ProductId'),\n    '{cbf38310-4a17-4310-a1eb-247f0b67593b}/7': (\n        'PKEY_DeviceInterface_Hid_VersionNumber'),\n    '{cc301630-b192-4c22-b372-9f4c6d338e07}/100': 'PKEY_PropGroup_General',\n    '{cc6f4f24-6083-4bd4-8754-674d0de87ab8}/100': 'PKEY_Contact_EmailName',\n    '{cd102c9c-5540-4a88-a6f6-64e4981c8cd1}/100': 'PKEY_Contact_AssistantName',\n    '{cd9ed458-08ce-418f-a70e-f912c7bb9c5c}/103': 'PKEY_Message_MessageClass',\n    '{cdbfc167-337e-41d8-af7c-8c09205429c7}/100': (\n        'PKEY_ApplicationDefinedProperties'),\n    '{cdedcf30-8919-44df-8f4c-4eb2ffdb8d89}/100': (\n        'PKEY_Photo_ExposureIndexNumerator'),\n    '{ce50c159-2fb8-41fd-be68-d3e042e274bc}/2': 'PKEY_Sync_HandlerName',\n    '{ce50c159-2fb8-41fd-be68-d3e042e274bc}/3': 'PKEY_Sync_ItemName',\n    '{ce50c159-2fb8-41fd-be68-d3e042e274bc}/4': 'PKEY_Sync_ConflictDescription',\n    '{ce50c159-2fb8-41fd-be68-d3e042e274bc}/6': (\n        'PKEY_Sync_ConflictFirstLocation'),\n    '{ce50c159-2fb8-41fd-be68-d3e042e274bc}/7': (\n        'PKEY_Sync_ConflictSecondLocation'),\n    '{cea820b9-ce61-4885-a128-005d9087c192}/100': 'PKEY_GPS_DestLatitudeRef',\n    '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/2': 'PKEY_DrvPkg_Model',\n    '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/3': 'PKEY_DrvPkg_VendorWebSite',\n    '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/4': (\n        'PKEY_DrvPkg_DetailedDescription'),\n    '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/5': 'PKEY_DrvPkg_DocumentationLink',\n    '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/6': 'PKEY_DrvPkg_Icon',\n    '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/7': 'PKEY_DrvPkg_BrandingIcon',\n    '{cfa31b45-525d-4998-bb44-3f7d81542fa4}/100': 'PKEY_Media_DlnaProfileID',\n    '{cfc08d97-c6f7-4484-89dd-ebef4356fe76}/100': (\n        'PKEY_Photo_FocalPlaneXResolution'),\n    '{d042d2a1-927e-40b5-a503-6edbd42a517e}/100': (\n        'PKEY_Contact_PhoneNumbersCanonical'),\n    '{d04e05a6-594b-4fb6-a80d-01af5eed7d1d}/0': 'PKEY_SYSFX_Association',\n    '{d04e05a6-594b-4fb6-a80d-01af5eed7d1d}/1': 'PKEY_SYSFX_PreMixClsid',\n    '{d04e05a6-594b-4fb6-a80d-01af5eed7d1d}/2': 'PKEY_SYSFX_PostMixClsid',\n    '{d04e05a6-594b-4fb6-a80d-01af5eed7d1d}/3': 'PKEY_SYSFX_UiClsid',\n    '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/10': 'PKEY_Devices_PrimaryCategory',\n    '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/2': 'PKEY_Devices_InterfacePaths',\n    '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/257': 'PKEY_Devices_Status1',\n    '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/258': 'PKEY_Devices_Status2',\n    '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/259': 'PKEY_Devices_Status',\n    '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/3': 'PKEY_Devices_FunctionPaths',\n    '{d0a04f0a-462a-48a4-bb2f-3706e88dbd7d}/100': 'PKEY_ItemAuthors',\n    '{d0c7f054-3f72-4725-8527-129a577cb269}/100': 'PKEY_SensitivityText',\n    '{d0dab0ba-368a-4050-a882-6c010fd19a4f}/100': 'PKEY_PropGroup_Content',\n    '{d21a7148-d32c-4624-8900-277210f79c0f}/100': (\n        'PKEY_Image_CompressedBitsPerPixelNumerator'),\n    '{d35f743a-eb2e-47f2-a286-844132cb1427}/100': 'PKEY_Photo_EXIFVersion',\n    '{d37d52c6-261c-4303-82b3-08b926ac6f12}/100': (\n        'PKEY_Task_BillingInformation'),\n    '{d4729704-8ef1-43ef-9024-2bd381187fd5}/100': 'PKEY_Contact_Children',\n    '{d4bf61b3-442e-4ada-882d-fa7b70c832d9}/6': (\n        'PKEY_Devices_Aep_PointOfService_ConnectionTypes'),\n    '{d4d0aa16-9948-41a4-aa85-d97ff9646993}/100': 'PKEY_ItemParticipants',\n    '{d55bae5a-3892-417a-a649-c6ac5aaaeab3}/100': (\n        'PKEY_Calendar_OptionalAttendeeAddresses'),\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/10': (\n        'PKEY_Document_MultimediaClipCount'),\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/14': 'PKEY_Document_Manager',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/15': 'PKEY_Company',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/2': 'PKEY_Category',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/26': 'PKEY_ContentType',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/27': 'PKEY_ContentStatus',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/28': 'PKEY_Language',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/29': 'PKEY_Document_Version',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/3': (\n        'PKEY_Document_PresentationFormat'),\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/4': 'PKEY_Document_ByteCount',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/5': 'PKEY_Document_LineCount',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/6': 'PKEY_Document_ParagraphCount',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/7': 'PKEY_Document_SlideCount',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/8': 'PKEY_Document_NoteCount',\n    '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/9': (\n        'PKEY_Document_HiddenSlideCount'),\n    '{d6304e01-f8f5-4f45-8b15-d024a6296789}/100': 'PKEY_Contact_PagerTelephone',\n    '{d68dbd8a-3374-4b81-9972-3ec30682db3d}/100': 'PKEY_Contact_IMAddress',\n    '{d6942081-d53b-443d-ad47-5e059d9cd27a}/2': 'PKEY_Shell_SFGAOFlagsStrings',\n    '{d6942081-d53b-443d-ad47-5e059d9cd27a}/3': (\n        'PKEY_Link_TargetSFGAOFlagsStrings'),\n    '{d6b5b883-18bd-4b4d-b2ec-9e38affeda82}/2': (\n        'PKEY_Devices_SmartCards_ReaderKind'),\n    '{d7313ff1-a77a-401c-8c99-3dbdd68add36}/100': 'PKEY_ItemNamePrefix',\n    '{d7750ee0-c6a4-48ec-b53e-b87b52e6d073}/100': 'PKEY_ImageParsingName',\n    '{d7b61c70-6323-49cd-a5fc-c84277162c97}/100': (\n        'PKEY_Photo_FlashEnergyDenominator'),\n    '{d98be98b-b86b-4095-bf52-9d23b2e0a752}/100': 'PKEY_PriorityText',\n    '{da520e51-f4e9-4739-ac82-02e0a95c9030}/100': (\n        'PKEY_Identity_QualifiedUserName'),\n    '{da5d0862-6e76-4e1b-babd-70021bd25494}/100': 'PKEY_GPS_Speed',\n    '{dabd30ed-0043-4789-a7f8-d013a4736622}/100': (\n        'PKEY_ItemFolderPathDisplayNarrow'),\n    '{dc54fd2e-189d-4871-aa01-08c2f57a4abc}/100': 'PKEY_FlagStatusText',\n    '{dc5877c7-225f-45f7-bac7-e81334b6130a}/100': (\n        'PKEY_GPS_ImgDirectionNumerator'),\n    '{dc8f80bd-af1e-4289-85b6-3dfc1b493992}/100': 'PKEY_Message_ConversationID',\n    '{dc8f80bd-af1e-4289-85b6-3dfc1b493992}/101': (\n        'PKEY_Message_ConversationIndex'),\n    '{dccb10af-b4e2-4b88-95f9-031b4d5ab490}/100': (\n        'PKEY_Photo_FocalPlaneXResolutionNumerator'),\n    '{ddd1460f-c0bf-4553-8ce4-10433c908fb0}/100': (\n        'PKEY_Contact_BusinessAddressStreet'),\n    '{de00de32-547e-4981-ad4b-542f2e9007d8}/100': 'PKEY_PropGroup_Camera',\n    '{de35258c-c695-4cbc-b982-38b0ad24ced0}/2': 'PKEY_Shell_OmitFromView',\n    '{de41cc29-6971-4290-b472-f59f2e2f31e2}/100': 'PKEY_Media_DateReleased',\n    '{de5ef3c7-46e1-484e-9999-62c5308394c1}/100': (\n        'PKEY_Contact_PrimaryAddressPostOfficeBox'),\n    '{de621b8f-e125-43a3-a32d-5665446d632a}/25': (\n        'PKEY_Security_EncryptionOwners'),\n    '{dea7c82c-1d89-4a66-9427-a4e3debabcb1}/100': 'PKEY_Journal_Contacts',\n    '{debda43a-37b3-4383-91e7-4498da2995ab}/1': 'PKEY_WNET_Scope',\n    '{debda43a-37b3-4383-91e7-4498da2995ab}/2': 'PKEY_WNET_Type',\n    '{debda43a-37b3-4383-91e7-4498da2995ab}/3': 'PKEY_WNET_DisplayType',\n    '{debda43a-37b3-4383-91e7-4498da2995ab}/4': 'PKEY_WNET_Usage',\n    '{debda43a-37b3-4383-91e7-4498da2995ab}/5': 'PKEY_WNET_LocalName',\n    '{debda43a-37b3-4383-91e7-4498da2995ab}/6': 'PKEY_WNET_RemoteName',\n    '{debda43a-37b3-4383-91e7-4498da2995ab}/7': 'PKEY_WNET_Comment',\n    '{debda43a-37b3-4383-91e7-4498da2995ab}/8': 'PKEY_WNET_Provider',\n    '{deeb2db5-0696-4ce0-94fe-a01f77a45fb5}/102': (\n        'PKEY_Music_ArtistSortOverride'),\n    '{df975fd3-250a-4004-858f-34e29a3e37aa}/100': 'PKEY_PropGroup_Contact',\n    '{dfb9a04d-362f-4ca3-b30b-0254b17b5b84}/100': 'PKEY_ParsingBindContext',\n    '{e08805c8-e395-40df-80d2-54f0d6c43154}/100': 'PKEY_Document_DocumentID',\n    '{e1277516-2b5f-4869-89b1-2e585bd38b7a}/100': 'PKEY_Photo_LensModel',\n    '{e13d8975-81c7-4948-ae3f-37cae11e8ff7}/100': (\n        'PKEY_Photo_ShutterSpeedDenominator'),\n    '{e1a9a38b-6685-46bd-875e-570dc7ad7320}/100': (\n        'PKEY_Photo_ApertureDenominator'),\n    '{e1d4a09e-d758-4cd1-b6ec-34a8b5a73f80}/100': (\n        'PKEY_Contact_BusinessAddressPostalCode'),\n    '{e3690a87-0fa8-4a2a-9a9f-fce8827055ac}/100': 'PKEY_PropGroup_Image',\n    '{e3a7d2c1-80fc-4b40-8f34-30ea111bdc2e}/100': 'PKEY_PropGroup_FileSystem',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/10': 'PKEY_IsRead',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/11': 'PKEY_Importance',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/12': 'PKEY_FlagStatus',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/13': 'PKEY_Message_FromAddress',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/14': 'PKEY_Message_FromName',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/15': 'PKEY_Message_Store',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/16': 'PKEY_Message_ToAddress',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/17': 'PKEY_Message_ToName',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/18': 'PKEY_Contact_WebPage',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/19': 'PKEY_Message_DateSent',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/2': 'PKEY_Message_BccAddress',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/20': 'PKEY_Message_DateReceived',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/21': 'PKEY_Message_AttachmentNames',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/3': 'PKEY_Message_BccName',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/4': 'PKEY_Message_CcAddress',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/5': 'PKEY_Message_CcName',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/6': 'PKEY_ItemFolderPathDisplay',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/7': 'PKEY_ItemPathDisplay',\n    '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/9': (\n        'PKEY_Communication_AccountName'),\n    '{e4870e26-3cc5-4cd2-ba46-ca0a9a70ed04}/3': 'PKEY_AudioEngine_OEMFormat',\n    '{e4f10a3c-49e6-405d-8288-a23bd4eeaa6c}/100': 'PKEY_FileExtension',\n    '{e53d799d-0f3f-466e-b2ff-74634a3cb7a4}/100': (\n        'PKEY_Contact_PrimaryAddressCountry'),\n    '{e55fc3b0-2b60-4220-918e-b21e8bf16016}/100': 'PKEY_Identity_UniqueID',\n    '{e6822fee-8c17-4d62-823c-8e9cfcbd1d5c}/100': (\n        'PKEY_Audio_IsVariableBitRate'),\n    '{e6ddcaf7-29c5-4f0a-9a68-d19412ec7090}/100': 'PKEY_Photo_LensManufacturer',\n    '{e7b33238-6584-4170-a5c0-ac25efd9da56}/100': 'PKEY_PropGroup_RecordedTV',\n    '{e7c3fb29-caa7-4f47-8c8b-be59b330d4c5}/2': 'PKEY_Devices_Aep_ContainerId',\n    '{e7c3fb29-caa7-4f47-8c8b-be59b330d4c5}/3': 'PKEY_Devices_Aep_CanPair',\n    '{e8309b6e-084c-49b4-b1fc-90a80331b638}/100': 'PKEY_Photo_PeopleNames',\n    '{e92a2496-223b-4463-a4e3-30eabba79d80}/100': (\n        'PKEY_Photo_FNumberDenominator'),\n    '{eaee7f1d-6a33-44d1-9441-5f46def23198}/9': 'PKEY_Device_BIOSVersion',\n    '{ec0b4191-ab0b-4c66-90b6-c6637cdebbab}/100': (\n        'PKEY_Communication_PolicyTag'),\n    '{ecf4b6f6-d5a6-433c-bb92-4076650fc890}/100': (\n        'PKEY_GPS_DestLatitudeNumerator'),\n    '{ecf7f4c9-544f-4d6d-9d98-8ad79adaf453}/100': 'PKEY_GPS_SpeedRef',\n    '{ed4df2d3-8695-450b-856f-f5c1c53acb66}/100': 'PKEY_GPS_DestDistanceRef',\n    '{ee3d3d8a-5381-4cfa-b13b-aaf66b5f4ec9}/100': 'PKEY_Photo_WhiteBalance',\n    '{eec7b761-6f94-41b1-949f-c729720dd13c}/12': (\n        'PKEY_DeviceInterface_PrinterPortName'),\n    '{ef1167eb-cbfc-4341-a568-a7c91a68982c}/2': (\n        'PKEY_Devices_WiFi_InterfaceGuid'),\n    '{ef884c5b-2bfe-41bb-aae5-76eedf4f9902}/100': 'PKEY_IsShared',\n    '{ef884c5b-2bfe-41bb-aae5-76eedf4f9902}/200': 'PKEY_SharedWith',\n    '{ef884c5b-2bfe-41bb-aae5-76eedf4f9902}/300': 'PKEY_SharingStatus',\n    '{f04bef95-c585-4197-a2b7-df46fdc9ee6d}/100': 'PKEY_KindText',\n    '{f0f7984d-222e-4ad2-82ab-1dd8ea40e57e}/300': 'PKEY_TitleSortOverride',\n    '{f1176dfe-7138-4640-8b4c-ae375dc70a6d}/100': (\n        'PKEY_Contact_PrimaryAddressState'),\n    '{f18dedf3-337f-42c0-9e03-cee08708a8c3}/100': (\n        'PKEY_Identity_LogonStatusString'),\n    '{f19f064d-082c-4e27-bc73-6882a1bb8e4c}/0': 'PKEY_AudioEngine_DeviceFormat',\n    '{f1a24aa7-9ca7-40f6-89ec-97def9ffe8db}/100': 'PKEY_Contact_FileAsName',\n    '{f1fdb4af-f78c-466c-bb05-56e92db0b8ec}/103': (\n        'PKEY_Music_AlbumArtistSortOverride'),\n    '{f21d9941-81f0-471a-adee-4e74b49217ed}/100': 'PKEY_ProviderItemID',\n    '{f2275480-f782-4291-bd94-f13693513aec}/0': 'PKEY_PropList_XPDetailsPanel',\n    '{f23f425c-71a1-4fa8-922f-678ea4a60408}/100': 'PKEY_IsAttachment',\n    '{f271c659-7e5e-471f-ba25-7f77b286f836}/100': (\n        'PKEY_Contact_BusinessEmailAddresses'),\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/10': (\n        'PKEY_Document_TotalEditingTime'),\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/11': 'PKEY_Document_DatePrinted',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/12': 'PKEY_Document_DateCreated',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/13': 'PKEY_Document_DateSaved',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/14': 'PKEY_Document_PageCount',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/15': 'PKEY_Document_WordCount',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/16': 'PKEY_Document_CharacterCount',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/17': 'PKEY_Thumbnail',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/18': 'PKEY_ApplicationName',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/19': 'PKEY_Document_Security',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/2': 'PKEY_Title',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/24': 'PKEY_HighKeywords',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/25': 'PKEY_LowKeywords',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/26': 'PKEY_MediumKeywords',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/27': 'PKEY_ThumbnailStream',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/3': 'PKEY_Subject',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/4': 'PKEY_Author',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/5': 'PKEY_Keywords',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/6': 'PKEY_Comment',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/7': 'PKEY_Document_Template',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/8': 'PKEY_Document_LastAuthor',\n    '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/9': 'PKEY_Document_RevisionNumber',\n    '{f334115e-da1b-4509-9b3d-119504dc7abb}/100': 'PKEY_Document_Contributor',\n    '{f3713ada-90e3-4e11-aae5-fdc17685b9be}/100': 'PKEY_PropGroup_GPS',\n    '{f3d8f40d-50cb-44a2-9718-40cb9119495d}/100': 'PKEY_Contact_Initials',\n    '{f6272d18-cecc-40b1-b26a-3911717aa7bd}/100': 'PKEY_Calendar_Location',\n    '{f628fd8c-7ba8-465a-a65b-c5aa79263a9e}/100': 'PKEY_Photo_MeteringModeText',\n    '{f7db74b4-4287-4103-afba-f1b13dcd75cf}/100': 'PKEY_ItemDate',\n    '{f85bf840-a925-4bc2-b0c4-8e36b598679e}/100': 'PKEY_Photo_DigitalZoom',\n    '{f8d3f6ac-4874-42cb-be59-ab454b30716a}/100': 'PKEY_Sensitivity',\n    '{f8fa7fa3-d12b-4785-8a4e-691a94f7a3e7}/100': 'PKEY_Contact_EmailAddress',\n    '{fa303353-b659-4052-85e9-bcac79549b84}/100': 'PKEY_Photo_MakerNote',\n    '{fa304789-00c7-4d80-904a-1e4dcc7265aa}/100': 'PKEY_Photo_GainControl',\n    '{fb1de864-e06d-47f4-82a6-8a0aef44493c}/2': (\n        'PKEY_Devices_AudioDevice_SpeechProcessingSupported'),\n    '{fb3842cd-9e2a-4f83-8fcc-4b0761139ae9}/2': (\n        'PKEY_DeviceInterface_Proximity_SupportsNfc'),\n    '{fb8d2d7b-90d1-4e34-bf60-6eac09922bbf}/2': 'PKEY_Winx_Hash',\n    '{fc6976db-8349-4970-ae97-b3c5316a08f0}/100': 'PKEY_Photo_Sharpness',\n    '{fc9f7306-ff8f-4d49-9fb6-3ffe5c0951ec}/100': 'PKEY_Contact_Department',\n    '{fcad3d3d-0858-400f-aaa3-2f66cce2a6bc}/100': (\n        'PKEY_Photo_FlashEnergyNumerator'),\n    '{fcc16823-baed-4f24-9b32-a0982117f7fa}/100': (\n        'PKEY_Identity_PrimaryEmailAddress'),\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/100': (\n        'PKEY_FileOfflineAvailabilityStatus'),\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/101': 'PKEY_FolderKind',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/103': 'PKEY_SyncTransferStatus',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/104': 'PKEY_TransferPosition',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/105': 'PKEY_TransferSize',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/106': 'PKEY_TransferOrder',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/107': 'PKEY_LastSyncError',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/108': 'PKEY_StorageProviderId',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/109': 'PKEY_StorageProviderError',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/110': 'PKEY_StorageProviderStatus',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/111': (\n        'PKEY_StorageProviderShareStatuses'),\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/112': (\n        'PKEY_StorageProviderFileRemoteUri'),\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/113': (\n        'PKEY_CachedFileUpdaterContentIdForStream'),\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/114': (\n        'PKEY_CachedFileUpdaterContentIdForConflictResolution'),\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/115': 'PKEY_RemoteConflictingFile',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/117': (\n        'PKEY_StorageProviderSharingStatus'),\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/128': 'PKEY_LastSyncWarning',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/131': 'PKEY_ContentUri',\n    '{fceff153-e839-4cf3-a9e7-ea22832094b8}/132': 'PKEY_ContentId',\n    '{fd122953-fa93-4ef7-92c3-04c946b2f7c8}/100': 'PKEY_Music_DisplayArtist',\n    '{fdf84370-031a-4add-9e91-0d775f1c6605}/100': 'PKEY_MileageInformation',\n    '{fe83bb35-4d1a-42e2-916b-06f3e1af719e}/100': 'PKEY_Photo_FlashModel',\n    '{fec690b7-5f30-4646-ae47-4caafba884a3}/100': (\n        'PKEY_Photo_ExposureProgramText'),\n    '{ff1167eb-cbfc-4341-a568-a7c91a68982c}/2': (\n        'PKEY_Devices_Wwan_InterfaceGuid'),\n    '{ff962609-b7d6-4999-862d-95180d529aea}/100': (\n        'PKEY_Contact_OtherAddressStreet'),\n    '{ffae9db7-1c8d-43ff-818c-84403aa3732d}/100': (\n        'PKEY_SourcePackageFamilyName')}\n"
  },
  {
    "path": "winregrc/shellfolders.py",
    "content": "\"\"\"Windows Shell folder collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass WindowsShellFolder:\n  \"\"\"Windows Shell folder.\n\n  Attributes:\n    alternate_names (list[str]): alternate names.\n    class_name (str): class name (CLSID).\n    identifier (str): identifier (GUID).\n    name (str): name.\n    localized_string (str): localized string of the name.\n  \"\"\"\n\n  def __init__(self, identifier=None, localized_string=None):\n    \"\"\"Initializes a Windows Shell folder.\n\n    Args:\n      identifier (Optional[str]): identifier (GUID).\n      localized_string (Optional[str]): localized string of the name.\n    \"\"\"\n    super().__init__()\n    self.alternate_names = []\n    self.class_name = None\n    self.identifier = identifier\n    self.localized_string = localized_string\n    self.name = None\n\n\nclass ShellFoldersCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows Shell folder collector.\"\"\"\n\n  _CLASS_IDENTIFIERS_KEY_PATH = 'HKEY_LOCAL_MACHINE\\\\Software\\\\Classes\\\\CLSID'\n\n  def __init__(self, debug=False):\n    \"\"\"Initializes a Windows Registry key and value collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n    \"\"\"\n    super().__init__(debug=debug)\n    self._ascii_codepage = 'cp1252'\n\n  def _CollectShellFolders(self, class_identifiers_key):\n    \"\"\"Collects Windows Shell folders.\n\n    Args:\n      class_identifiers_key (dfwinreg.WinRegistry): CLSID Windows Registry.\n\n    Yields:\n      ShellFolder: a Windows Shell folder.\n    \"\"\"\n    for class_identifier_key in class_identifiers_key.GetSubkeys():\n      shell_folder_identifier = class_identifier_key.name.lower()\n\n      shell_folder_key = class_identifier_key.GetSubkeyByName('ShellFolder')\n      if shell_folder_key:\n        name = self._GetShellFolderName(class_identifier_key)\n\n        value = class_identifier_key.GetValueByName('LocalizedString')\n        if value:\n          # The value data type does not have to be a string therefore try to\n          # decode the data as an UTF-16 little-endian string and strip\n          # the trailing end-of-string character\n          localized_string = value.data.decode('utf-16-le').rstrip('\\x00')\n        else:\n          localized_string = None\n\n        shell_folder = WindowsShellFolder(\n            identifier=shell_folder_identifier,\n            localized_string=localized_string)\n        if name and name.startswith('CLSID_'):\n          shell_folder.class_name = name\n        else:\n          shell_folder.name = name\n\n        yield shell_folder\n\n  def _GetShellFolderName(self, class_identifier_key):\n    \"\"\"Retrieves the shell folder name.\n\n    Args:\n      class_identifier_key (dfwinreg.RegistryKey): class identifier Windows\n          Registry key.\n\n    Returns:\n      str: shell folder name or None if not available.\n    \"\"\"\n    value = class_identifier_key.GetValueByName('')\n    if not value or not value.data:\n      return None\n\n    # First try to decode the value data as an UTF-16 little-endian string with\n    # end-of-string character\n    try:\n      return value.data.decode('utf-16-le').rstrip('\\x00')\n    except UnicodeDecodeError:\n      pass\n\n    # Next try to decode the value data as an ASCII string with a specific\n    # codepage and end-of-string character.\n    try:\n      return value.data.decode(self._ascii_codepage).rstrip('\\x00')\n    except UnicodeDecodeError:\n      pass\n\n    return None\n\n  def Collect(self, registry):\n    \"\"\"Collects Windows Shell folders.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Yields:\n      WindowsShellFolder: a Windows Shell folder.\n    \"\"\"\n    # TODO: Add support for per-user shell folders\n\n    class_identifiers_key = registry.GetKeyByPath(\n        self._CLASS_IDENTIFIERS_KEY_PATH)\n    if class_identifiers_key:\n      yield from self._CollectShellFolders(class_identifiers_key)\n"
  },
  {
    "path": "winregrc/srum_extensions.py",
    "content": "\"\"\"System Resource Usage Monitor (SRUM) extension collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass SRUMExtension:\n  \"\"\"System Resource Usage Monitor (SRUM) extension.\n\n  Attributes:\n    dll_name (str): DLL name.\n    guid (str): identifier.\n  \"\"\"\n\n  def __init__(self, guid, dll_name):\n    \"\"\"Initializes a System Resource Usage Monitor (SRUM) extension.\n\n    Args:\n      guid (str): identifier.\n      dll_name (str): DLL name.\n    \"\"\"\n    super().__init__()\n    self.guid = guid\n    self.dll_name = dll_name\n\n\nclass SRUMExtensionsCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows System Resource Usage Monitor (SRUM) extension collector.\"\"\"\n\n  _SRUM_EXTENSIONS_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\'\n      'SRUM\\\\Extensions')\n\n  def Collect(self, registry, output_writer):\n    \"\"\"Collects the SRUM extensions.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n      output_writer (OutputWriter): output writer.\n\n    Returns:\n      bool: True if the SRUM extensions key was found, False if not.\n    \"\"\"\n    srum_extensions_key = registry.GetKeyByPath(self._SRUM_EXTENSIONS_KEY_PATH)\n    if not srum_extensions_key:\n      return False\n\n    for subkey in srum_extensions_key.GetSubkeys():\n      guid = subkey.name.upper()\n      dll_name = self._GetValueFromKey(subkey, 'DllName')\n\n      srum_extension = SRUMExtension(guid, dll_name)\n      output_writer.WriteSRUMExtension(srum_extension)\n\n    return True\n"
  },
  {
    "path": "winregrc/sysinfo.py",
    "content": "\"\"\"System information collector.\"\"\"\n\nfrom dfdatetime import posix_time as dfdatetime_posix_time\nfrom dfdatetime import semantic_time as dfdatetime_semantic_time\n\nfrom winregrc import interface\n\n\nclass SystemInformation:\n  \"\"\"System information.\n\n  Attributes:\n    csd_version (str): CSD version.\n    current_build_number (str): current build number.\n    current_type (str): current type.\n    current_version (str): current version.\n    installation_date (dfdatetime.DateTimeValues): installation date and time.\n    path_name (str): path name.\n    product_identifier (str): product identifier.\n    product_name (str): product name.\n    registered_organization (str): registered organization.\n    registered_owner (str): registered owner.\n    system_root (str): system root path.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes system information.\"\"\"\n    super().__init__()\n    self.csd_version = None\n    self.current_build_number = None\n    self.current_type = None\n    self.current_version = None\n    self.installation_date = None\n    self.path_name = None\n    self.product_identifier = None\n    self.product_name = None\n    self.registered_organization = None\n    self.registered_owner = None\n    self.system_root = None\n\n\nclass SystemInfoCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"System information collector.\n\n  Attributes:\n    system_information (SystemInformation): system information.\n  \"\"\"\n\n  _CURRENT_VERSION_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows NT\\\\CurrentVersion')\n\n  _STRING_VALUES = {\n      'CSDVersion': 'csd_version',\n      'CurrentBuildNumber': 'current_build_number',\n      'CurrentType': 'current_type',\n      'CurrentVersion': 'current_version',\n      'PathName': 'path_name',\n      'ProductId': 'product_identifier',\n      'ProductName': 'product_name',\n      'RegisteredOrganization': 'registered_organization',\n      'RegisteredOwner': 'registered_owner',\n      'SystemRoot': 'system_root'}\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a system information collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__(debug=debug)\n    self._output_writer = output_writer\n    self.system_information = None\n\n  def _ParseInstallDate(self, registry_value):\n    \"\"\"Parses the InstallDate value.\n\n    Args:\n      registry_value (dfwinreg.WinRegistryValue): Windows Registry value.\n\n    Returns:\n      dfdatetime.PosixTime: installation date and time or None if not available.\n    \"\"\"\n    if not registry_value:\n      return None\n\n    timestamp = registry_value.GetDataAsObject()\n    if not timestamp:\n      return dfdatetime_semantic_time.SemanticTime(string='Not set')\n\n    return dfdatetime_posix_time.PosixTime(timestamp=timestamp)\n\n  def Collect(self, registry):  # pylint: disable=arguments-differ\n    \"\"\"Collects system information.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      bool: True if the system information key was found, False if not.\n    \"\"\"\n    current_version_key = registry.GetKeyByPath(\n        self._CURRENT_VERSION_KEY_PATH)\n    if not current_version_key:\n      return False\n\n    self.system_information = SystemInformation()\n\n    for value_name, attribute_name in self._STRING_VALUES.items():\n      value_string = self._GetValueFromKey(current_version_key, value_name)\n      setattr(self.system_information, attribute_name, value_string)\n\n    registry_value = current_version_key.GetValueByName('InstallDate')\n    self.system_information.installation_date = self._ParseInstallDate(\n        registry_value)\n\n    return True\n"
  },
  {
    "path": "winregrc/syskey.py",
    "content": "\"\"\"System key (syskey) collector.\"\"\"\n\nimport codecs\n\nfrom winregrc import interface\n\n\nclass SystemKey:\n  \"\"\"System key.\n\n  Attributes:\n    boot_key (bytes): boot key.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes a system key.\"\"\"\n    super().__init__()\n    self.boot_key = None\n\n\nclass SystemKeyCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"System key collector.\n\n  Attributes:\n    system_key (SystemKey): system key.\n  \"\"\"\n\n  _LSA_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\System\\\\CurrentControlSet\\\\Control\\\\Lsa')\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a system key collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__(debug=debug)\n    self._output_writer = output_writer\n    self.system_key = None\n\n  def _GetBootKey(self, registry):\n    \"\"\"Retrieves the boot key.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      bytes: boot key or None if not found.\n    \"\"\"\n    try:\n      lsa_key = registry.GetKeyByPath(self._LSA_KEY_PATH)\n    except RuntimeError:\n      lsa_key = None\n\n    if not lsa_key:\n      return None\n\n    lsa_jd_key = lsa_key.GetSubkeyByName('JD')\n    lsa_skew1_key = lsa_key.GetSubkeyByName('Skew1')\n    lsa_gbg_key = lsa_key.GetSubkeyByName('GBG')\n    lsa_data_key = lsa_key.GetSubkeyByName('Data')\n\n    if None in (lsa_jd_key, lsa_skew1_key, lsa_gbg_key, lsa_data_key):\n      return None\n\n    lsa_jd_class_name = lsa_jd_key.class_name\n    lsa_skew1_class_name = lsa_skew1_key.class_name\n    lsa_gbg_class_name = lsa_gbg_key.class_name\n    lsa_data_class_name = lsa_data_key.class_name\n\n    if None in (\n        lsa_jd_class_name, lsa_skew1_class_name, lsa_gbg_class_name,\n        lsa_data_class_name):\n      return None\n\n    class_name_string = ''.join([\n        lsa_jd_class_name, lsa_skew1_class_name, lsa_gbg_class_name,\n        lsa_data_class_name])\n\n    scrambled_key = codecs.decode(class_name_string, 'hex')\n    key = bytearray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])\n\n    for index, scrambled_index in enumerate([\n        8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7]):\n      key[index] = scrambled_key[scrambled_index]\n\n    return bytes(key)\n\n  def Collect(self, registry):  # pylint: disable=arguments-differ\n    \"\"\"Collects system information.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      bool: True if the system key was found, False if not.\n    \"\"\"\n    boot_key = self._GetBootKey(registry)\n    if not boot_key:\n      return False\n\n    self.system_key = SystemKey()\n    self.system_key.boot_key = boot_key\n\n    return True\n"
  },
  {
    "path": "winregrc/task_cache.py",
    "content": "\"\"\"Task Cache collector.\"\"\"\n\nimport logging\n\nfrom dfdatetime import filetime as dfdatetime_filetime\nfrom dfdatetime import semantic_time as dfdatetime_semantic_time\n\nfrom dtfabric import errors as dtfabric_errors\n\nfrom winregrc import data_format\nfrom winregrc import errors\nfrom winregrc import interface\n\n\nclass CachedTask:\n  \"\"\"Cached task.\n\n  Attributes:\n    identifier (str): identifier.\n    last_registered_time (dfdatetime.DateTimeValues): last registered\n        date and time.\n    launch_time (dfdatetime.DateTimeValues): launch date and time.\n    name (str): name.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes a cached task.\"\"\"\n    super().__init__()\n    self.identifier = None\n    self.last_registered_time = None\n    self.launch_time = None\n    self.name = None\n\n\nclass TaskCacheDataParser(data_format.BinaryDataFormat):\n  \"\"\"Task Cache data parser.\"\"\"\n\n  _DEFINITION_FILE = 'task_cache.yaml'\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a Task Cache data parser.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__()\n    self._debug = debug\n    self._output_writer = output_writer\n\n  def _ParseFiletime(self, filetime):\n    \"\"\"Parses a FILETIME timestamp value.\n\n    Args:\n      filetime (int): a FILETIME timestamp value.\n\n    Returns:\n      dfdatetime.DateTimeValues: date and time values.\n    \"\"\"\n    if filetime == 0:\n      return dfdatetime_semantic_time.SemanticTime(string='Not set')\n\n    if filetime == 0x7fffffffffffffff:\n      return dfdatetime_semantic_time.SemanticTime(string='Never')\n\n    return dfdatetime_filetime.Filetime(timestamp=filetime)\n\n  def ParseDynamicInfo(self, value_data, cached_task):\n    \"\"\"Parses the DynamicInfo value data.\n\n    Args:\n      value_data (bytes): DynamicInfo value data.\n      cached_task (CachedTask): cached task.\n\n    Raises:\n      ParseError: if the value data could not be parsed.\n    \"\"\"\n    if self._debug:\n      self._output_writer.WriteDebugData('DynamicInfo value data:', value_data)\n\n    value_data_size = len(value_data)\n\n    if value_data_size == 28:\n      data_type_map = self._GetDataTypeMap('dynamic_info_record')\n    elif value_data_size == 36:\n      data_type_map = self._GetDataTypeMap('dynamic_info2_record')\n    else:\n      data_type_map = None\n\n    if not data_type_map:\n      raise errors.ParseError(\n          f'Unsupported value data size: {value_data_size:d}.')\n\n    try:\n      dynamic_info = data_type_map.MapByteStream(value_data)\n    except (\n        dtfabric_errors.ByteStreamTooSmallError,\n        dtfabric_errors.MappingError) as exception:\n      raise errors.ParseError(exception)\n\n    cached_task.last_registered_time = self._ParseFiletime(\n        dynamic_info.last_registered_time)\n    cached_task.launch_time = self._ParseFiletime(\n        dynamic_info.launch_time)\n\n    if self._debug:\n      self._output_writer.WriteValue(\n          'Unknown1', f'0x{dynamic_info.unknown1:08x}')\n\n      # Note this is likely either the last registered time or\n      # the update time.\n      self._DebugPrintFiletimeValue(\n          'Last registered time', dynamic_info.last_registered_time)\n\n      # Note this is likely the launch time.\n      self._DebugPrintFiletimeValue('Launch time', dynamic_info.launch_time)\n\n      self._output_writer.WriteValue(\n          'Unknown2', f'0x{dynamic_info.unknown2:08x}')\n\n      self._output_writer.WriteValue(\n          'Unknown3', f'0x{dynamic_info.unknown3:08x}')\n\n      if dynamic_info.unknown_time is not None:\n        self._DebugPrintFiletimeValue('Unknown time', dynamic_info.unknown_time)\n\n      self._output_writer.WriteText('')\n\n\nclass TaskCacheCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Task Cache collector.\n\n  Attributes:\n    cached_tasks (list[CachedTask]): cached tasks.\n  \"\"\"\n\n  _TASK_CACHE_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\'\n      'Schedule\\\\TaskCache')\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a Task Cache collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__(debug=debug)\n    self._parser = TaskCacheDataParser(debug=debug, output_writer=output_writer)\n    self._output_writer = output_writer\n    self.cached_tasks = []\n\n  def _GetIdValue(self, registry_key):\n    \"\"\"Retrieves the Id value from Task Cache Tree key.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n\n    Yields:\n      tuple[dfwinreg.WinRegistryKey, dfwinreg.WinRegistryValue]: Windows\n          Registry key and value.\n    \"\"\"\n    id_value = registry_key.GetValueByName('Id')\n    if id_value:\n      yield registry_key, id_value\n\n    for subkey in registry_key.GetSubkeys():\n      for value_key, id_value in self._GetIdValue(subkey):\n        yield value_key, id_value\n\n  def Collect(self, registry):  # pylint: disable=arguments-differ\n    \"\"\"Collects the Task Cache.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      bool: True if the Task Cache key was found, False if not.\n    \"\"\"\n    dynamic_info_size_error_reported = False\n\n    task_cache_key = registry.GetKeyByPath(self._TASK_CACHE_KEY_PATH)\n    if not task_cache_key:\n      return False\n\n    tasks_key = task_cache_key.GetSubkeyByName('Tasks')\n    tree_key = task_cache_key.GetSubkeyByName('Tree')\n\n    if not tasks_key or not tree_key:\n      return False\n\n    task_guids = {}\n    for subkey in tree_key.GetSubkeys():\n      for value_key, id_value in self._GetIdValue(subkey):\n        # TODO: improve this check to a regex.\n        # The GUID is in the form {%GUID%} and stored an UTF-16 little-endian\n        # string and should be 78 bytes in size.\n\n        id_value_data_size = len(id_value.data)\n        if id_value_data_size != 78:\n          logging.error('Unsupported Id value data size: {0:s}.')\n          continue\n\n        guid_string = id_value.GetDataAsObject()\n        task_guids[guid_string] = value_key.name\n\n    for subkey in tasks_key.GetSubkeys():\n      dynamic_info_value = subkey.GetValueByName('DynamicInfo')\n      if not dynamic_info_value:\n        continue\n\n      cached_task = CachedTask()\n      cached_task.identifier = subkey.name\n      cached_task.name = task_guids.get(subkey.name, subkey.name)\n\n      if self._debug:\n        if (task_cache_key.last_written_time and\n            task_cache_key.last_written_time.timestamp):\n          self._output_writer.WriteFiletimeValue(\n              'Last written time', task_cache_key.last_written_time.timestamp)\n\n        self._output_writer.WriteValue('Task', cached_task.name)\n        self._output_writer.WriteValue('Identifier', cached_task.identifier)\n        self._output_writer.WriteText('')\n\n      try:\n        self._parser.ParseDynamicInfo(dynamic_info_value.data, cached_task)\n      except errors.ParseError as exception:\n        if not dynamic_info_size_error_reported:\n          logging.error(exception)\n          dynamic_info_size_error_reported = True\n        continue\n\n      self.cached_tasks.append(cached_task)\n\n    return True\n"
  },
  {
    "path": "winregrc/task_cache.yaml",
    "content": "# dtFabric format specification.\n---\nname: task_cache\ntype: format\ndescription: Task Scheduler Cache format\n---\nname: uint32\ntype: integer\nattributes:\n  format: unsigned\n  size: 4\n  units: bytes\n---\nname: uint64\ntype: integer\nattributes:\n  format: unsigned\n  size: 8\n  units: bytes\n---\nname: dynamic_info_record\ntype: structure\nattributes:\n  byte_order: little-endian\nmembers:\n- name: unknown1\n  data_type: uint32\n- name: last_registered_time\n  data_type: uint64\n- name: launch_time\n  data_type: uint64\n- name: unknown2\n  data_type: uint32\n- name: unknown3\n  data_type: uint32\n---\nname: dynamic_info2_record\ntype: structure\nattributes:\n  byte_order: little-endian\nmembers:\n- name: unknown1\n  data_type: uint32\n- name: last_registered_time\n  data_type: uint64\n- name: launch_time\n  data_type: uint64\n- name: unknown2\n  data_type: uint32\n- name: unknown3\n  data_type: uint32\n- name: unknown_time\n  data_type: uint64\n"
  },
  {
    "path": "winregrc/time_zone_information.yaml",
    "content": "# dtFabric format specification.\n---\nname: time_zone_information\ntype: format\ndescription: Time Zone Information (TZI) format\n---\nname: uint16\ntype: integer\nattributes:\n  format: unsigned\n  size: 2\n  units: bytes\n---\nname: int32\ntype: integer\nattributes:\n  format: signed\n  size: 4\n  units: bytes\n---\nname: system_time\ntype: structure\nmembers:\n- name: year\n  data_type: uint16\n- name: month\n  data_type: uint16\n- name: weekday\n  data_type: uint16\n- name: day_of_month\n  data_type: uint16\n- name: hours\n  data_type: uint16\n- name: minutes\n  data_type: uint16\n- name: seconds\n  data_type: uint16\n- name: milliseconds\n  data_type: uint16\n---\nname: tzi_record\ntype: structure\ndescription: Time Zone Information (TZI)\naliases: ['TIME_ZONE_INFORMATION', '_REG_TZI_FORMAT']\nattributes:\n  byte_order: little-endian\nmembers:\n- name: bias\n  aliases: ['Bias']\n  data_type: int32\n- name: standard_bias\n  aliases: ['StandardBias']\n  data_type: int32\n- name: daylight_bias\n  aliases: ['DaylightBias']\n  data_type: int32\n- name: standard_date\n  aliases: ['StandardDate']\n  data_type: system_time\n- name: daylight_date\n  aliases: ['DaylightDate']\n  data_type: system_time\n"
  },
  {
    "path": "winregrc/time_zones.py",
    "content": "\"\"\"Windows time zones collector.\"\"\"\n\nfrom winregrc import data_format\nfrom winregrc import errors\nfrom winregrc import interface\n\n\nclass TimeZone:\n  \"\"\"Time zone.\n\n  Attributes:\n    localized_name (str): localized name.\n    name (str): name.\n    offset (int): time zone offset in number of minutes from UTC.\n  \"\"\"\n\n  def __init__(self, name):\n    \"\"\"Initializes a time zone.\n\n    Args:\n      name (str): name.\n    \"\"\"\n    super().__init__()\n    self.localized_name = None\n    self.name = name\n    self.offset = 0\n\n\nclass TimeZoneInformationDataParser(data_format.BinaryDataFormat):\n  \"\"\"Time Zone Information (TZI) data parser.\"\"\"\n\n  _DEBUG_INFO_TZI_RECORD = [\n      ('bias', 'Bias', '_FormatIntegerAsDecimal'),\n      ('standard_bias', 'Standard bias', '_FormatIntegerAsDecimal'),\n      ('daylight_bias', 'Daylight bias', '_FormatIntegerAsDecimal'),\n      ('standard_date', 'Standard date', '_FormatSystemTime'),\n      ('daylight_date', 'Daylight date', '_FormatSystemTime')]\n\n  _DEFINITION_FILE = 'time_zone_information.yaml'\n\n  _MONTHS = [\n      '', 'January', 'February', 'March', 'April', 'May', 'June', 'July',\n      'August', 'September', 'October', 'November', 'December']\n\n  _OCCURANCE = ['', '1st', '2nd', '3rd', '4th', 'last']\n\n  _WEEKDAYS = [\n      'Sunday', 'Monday', 'Tuesday', 'Wednessday', 'Thursday', 'Friday',\n      'Saturday']\n\n  def _FormatSystemTime(self, systemtime):\n    \"\"\"Formats a SYSTEMTIME structure.\n\n    Args:\n      systemtime (system_time): SYSTEMTIME structure.\n\n    Returns:\n      str: formatted SYSTEMTIME structure.\n    \"\"\"\n    if systemtime.month and systemtime.day_of_month:\n      occurance = self._OCCURANCE[systemtime.day_of_month]\n      weekday = self._WEEKDAYS[systemtime.weekday]\n      month = self._MONTHS[systemtime.month]\n\n      if not systemtime.year:\n        return (f'{occurance:s} {weekday:s} of {month:s} at '\n                f'{systemtime.hours:02d}:{systemtime.minutes:02d}')\n\n      return (f'{occurance:s} {weekday:s} of {month:s} in {systemtime.year:s} '\n              f'at {systemtime.hours:02d}:{systemtime.minutes:02d}')\n\n    return 'Not set'\n\n  def ParseTZIValue(self, value_data, time_zone):\n    \"\"\"Parses the TZI value data.\n\n    Args:\n      value_data (bytes): TZI value data.\n      time_zone (TimeZone): time zone.\n\n    Raises:\n      ParseError: if the value data could not be parsed.\n    \"\"\"\n    data_type_map = self._GetDataTypeMap('tzi_record')\n\n    try:\n      tzi_record = self._ReadStructureFromByteStream(\n          value_data, 0, data_type_map, 'TZI record')\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse TZI record value with error: {exception!s}')\n\n    if self._debug:\n      self._DebugPrintStructureObject(tzi_record, self._DEBUG_INFO_TZI_RECORD)\n\n    if tzi_record.standard_bias:\n      time_zone.offset = tzi_record.standard_bias\n    else:\n      time_zone.offset = tzi_record.bias\n\n\nclass TimeZonesCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows time zones collector.\"\"\"\n\n  _TIME_ZONES_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\'\n      'Time Zones')\n\n  def Collect(self, registry, output_writer):\n    \"\"\"Collects the time zones.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n      output_writer (OutputWriter): output writer.\n\n    Returns:\n      bool: True if the time zones key was found, False if not.\n    \"\"\"\n    time_zones_key = registry.GetKeyByPath(self._TIME_ZONES_KEY_PATH)\n    if not time_zones_key:\n      return False\n\n    time_zone_information_parser = TimeZoneInformationDataParser(\n        debug=self._debug, output_writer=output_writer)\n\n    for subkey in time_zones_key.GetSubkeys():\n      time_zone = TimeZone(subkey.name)\n\n      if self._debug and output_writer:\n        output_writer.DebugPrintValue('Name', subkey.name)\n\n        string = self._GetValueFromKey(subkey, 'Display')\n        if string is not None:\n          output_writer.DebugPrintValue('Display', string)\n\n        string = self._GetValueFromKey(subkey, 'Dlt')\n        if string is not None:\n          output_writer.DebugPrintValue('Dlt', string)\n\n        string = self._GetValueFromKey(subkey, 'Std')\n        if string is not None:\n          output_writer.DebugPrintValue('Std', string)\n\n        string = self._GetValueFromKey(subkey, 'MapID')\n        if string is not None:\n          output_writer.DebugPrintValue('MapID', string)\n\n        string = self._GetValueFromKey(subkey, 'MUI_Display')\n        if string is not None:\n          output_writer.DebugPrintValue('MUI_Display', string)\n\n        string = self._GetValueFromKey(subkey, 'MUI_Dlt')\n        if string is not None:\n          output_writer.DebugPrintValue('MUI_Dlt', string)\n\n        string = self._GetValueFromKey(subkey, 'MUI_Std')\n        if string is not None:\n          output_writer.DebugPrintValue('MUI_Std', string)\n\n        data = self._GetValueDataFromKey(subkey, 'Index')\n        if data is not None:\n          output_writer.DebugPrintData('Index', data)\n\n      data = self._GetValueDataFromKey(subkey, 'TZI')\n      if self._debug and output_writer and data is not None:\n        output_writer.DebugPrintData('TZI', data)\n\n      time_zone_information_parser.ParseTZIValue(data, time_zone)\n\n      if self._debug and output_writer:\n        output_writer.DebugPrintText('\\n')\n\n      output_writer.WriteTimeZone(time_zone)\n\n    return True\n"
  },
  {
    "path": "winregrc/type_libraries.py",
    "content": "\"\"\"Windows type libraries collector.\"\"\"\n\nfrom winregrc import interface\n\n\nclass TypeLibrary:\n  \"\"\"Type library.\n\n  Attributes:\n    description (str): description.\n    identifier (str): identifier.\n    typelib_filename (str): typelib_filename.\n    version (str): version.\n  \"\"\"\n\n  def __init__(self, identifier, version, description, typelib_filename):\n    \"\"\"Initializes a type library.\n\n    Args:\n      identifier (str): identifier.\n      version (str): version.\n      description (str): description.\n      typelib_filename (str): typelib_filename.\n    \"\"\"\n    super().__init__()\n    self.description = description\n    self.identifier = identifier\n    self.typelib_filename = typelib_filename\n    self.version = version\n\n\nclass TypeLibrariesCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows type libraries collector.\n\n  Attributes:\n    type_libraries (list[TypeLibrary]): type libraries.\n  \"\"\"\n\n  _TYPE_LIBRARIES_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\Software\\\\Classes\\\\TypeLib')\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a Windows type libraries collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__(debug=debug)\n    self._output_writer = output_writer\n    self.type_libraries = []\n\n  def Collect(self, registry):  # pylint: disable=arguments-differ\n    \"\"\"Collects the type libraries.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      bool: True if the type libraries key was found, False if not.\n    \"\"\"\n    type_libraries_key = registry.GetKeyByPath(\n        self._TYPE_LIBRARIES_KEY_PATH)\n    if not type_libraries_key:\n      return False\n\n    for type_library_key in type_libraries_key.GetSubkeys():\n      identifier = type_library_key.name.lower()\n\n      for subkey in type_library_key.GetSubkeys():\n        if subkey.name in ('FLAGS', 'HELPDIR'):\n          continue\n\n        description = self._GetValueFromKey(subkey, '')\n\n        language_key = None\n        for lcid in ('0', '409'):\n          language_key = subkey.GetSubkeyByName(lcid)\n          if language_key:\n            break\n\n        if not language_key:\n          for language_key in subkey.GetSubkeys():\n            if language_key.name not in ('FLAGS', 'HELPDIR'):\n              break\n\n        platform_key = None\n        if language_key:\n          for platform in ('win32', ):\n            platform_key = language_key.GetSubkeyByName(platform)\n            if platform_key:\n              break\n\n          if not platform_key:\n            platform_key = language_key.GetSubkeyByIndex(0)\n\n        typelib_filename = self._GetValueFromKey(platform_key, '')\n\n        type_library = TypeLibrary(\n            identifier, subkey.name, description, typelib_filename)\n        self.type_libraries.append(type_library)\n\n    return True\n"
  },
  {
    "path": "winregrc/usbstor.py",
    "content": "\"\"\"Windows USB storage device collector.\"\"\"\n\nfrom dfdatetime import filetime as dfdatetime_filetime\nfrom dfdatetime import semantic_time as dfdatetime_semantic_time\n\nfrom winregrc import data_format\nfrom winregrc import errors\n\n\nclass USBStorageDeviceProperty:\n  \"\"\"USB storage device property.\n\n  Attributes:\n    identifier (str): identifier of the property.\n    property_set (str): identifier of the property set.\n    value (object): property value.\n    value_type (int): property value type.\n  \"\"\"\n\n  def __init__(self, property_set, identifier):\n    \"\"\"Initializes an USB storage device property.\n\n    Args:\n      property_set (str): identifier of the property set.\n      identifier (str): identifier of the property.\n    \"\"\"\n    super().__init__()\n    self.identifier = identifier\n    self.property_set = property_set\n    self.value = None\n    self.value_type = None\n\n\nclass USBStorageDevice:\n  \"\"\"USB storage device.\n\n  Attributes:\n    device_type (str): type of USB device.\n    display_name (str): display name of the USB device.\n    key_path (str): Windows Registry key path.\n    product (str): product of the USB device.\n    properties (list[USBStorageDeviceProperty]): properties.\n    revision (str): revision number of the USB device.\n    vendor (str): vendor of the USB device.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes an USB storage device.\"\"\"\n    super().__init__()\n    self.device_type = None\n    self.display_name = None\n    self.key_path = None\n    self.product = None\n    self.properties = []\n    self.revision = None\n    self.vendor = None\n\n\nclass USBStorageDeviceCollector(data_format.BinaryDataFormat):\n  \"\"\"Windows USB storage device collector.\"\"\"\n\n  _DEFINITION_FILE = 'usbstor.yaml'\n\n  _USBSTOR_KEY_PATH = (\n      'HKEY_LOCAL_MACHINE\\\\System\\\\CurrentControlSet\\\\Enum\\\\USBSTOR')\n\n  def _CollectUSBStorageDevices(self, usbstor_key):\n    \"\"\"Collects USB storage devices.\n\n    Args:\n      usbstor_key (dfwinreg.WinRegistryKey): USB storage Windows Registry key.\n\n    Yields:\n      USBStorageDevice: an USB storage device.\n    \"\"\"\n    for device_key in usbstor_key.GetSubkeys():\n      yield self._ParseDeviceKey(device_key)\n\n  def _GetPropertyValueData(self, property_value_key, value_type):\n    \"\"\"Retrieves a property value data.\n\n    Args:\n      property_value_key (dfwinreg.WinRegistryKey): property value Windows\n          Registry key.\n      value_type (int): value type.\n\n    Returns:\n      object: property value data.\n\n    Raises:\n      ParseError: if the property value data cannot be determined.\n    \"\"\"\n    binary_data = self._GetValueDataFromKey(property_value_key, 'Data')\n\n    if value_type == 0x00000007:\n      data_type_map = self._GetDataTypeMap('uint32le')\n    elif value_type == 0x00000010:\n      data_type_map = self._GetDataTypeMap('uint64le')\n    elif value_type == 0x00000012:\n      data_type_map = self._GetDataTypeMap('utf16le_string')\n    else:\n      raise errors.ParseError(f'Unsupported value type: 0x{value_type:08x}')\n\n    try:\n      value_data = self._ReadStructureFromByteStream(\n          binary_data, 0, data_type_map, 'data')\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse value: Data with error: {exception!s}')\n\n    if value_type == 0x00000010:\n      value_data = self._ParseFiletime(value_data)\n\n    return value_data\n\n  def _GetPropertyValueType(self, property_value_key):\n    \"\"\"Retrieves a property value type.\n\n    Args:\n      property_value_key (dfwinreg.WinRegistryKey): property value Windows\n          Registry key.\n\n    Returns:\n      int: property value type.\n\n    Raises:\n      ParseError: if the property value type cannot be determined.\n    \"\"\"\n    binary_data = self._GetValueDataFromKey(property_value_key, 'Type')\n\n    data_type_map = self._GetDataTypeMap('uint32le')\n\n    try:\n      return self._ReadStructureFromByteStream(\n          binary_data, 0, data_type_map, 'type')\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse value: Type with error: {exception!s}')\n\n  def _GetStringValueFromKey(\n      self, registry_key, value_name, default_value=None):\n    \"\"\"Retrieves a string value from a Registry value.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n      value_name (str): name of the value.\n      default_value (Optional[str]): default value.\n\n    Returns:\n      str: value or the default value if not available.\n    \"\"\"\n    if not registry_key:\n      return default_value\n\n    registry_value = registry_key.GetValueByName(value_name)\n    if not registry_value:\n      return default_value\n\n    if not registry_value.DataIsString():\n      return default_value\n\n    return registry_value.GetDataAsObject()\n\n  def _GetValueDataFromKey(self, registry_key, value_name):\n    \"\"\"Retrieves the value data from a Registry value.\n\n    Args:\n      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.\n      value_name (str): name of the value.\n\n    Returns:\n      bytes: value data or None if not available.\n    \"\"\"\n    if not registry_key:\n      return None\n\n    registry_value = registry_key.GetValueByName(value_name)\n    if not registry_value:\n      return None\n\n    return registry_value.data\n\n  def _ParseDeviceKey(self, device_key):\n    \"\"\"Parses an USB storage device key.\n\n    Args:\n      device_key (dfwinreg.WinRegistryKey): USB storage device Windows Registry\n          key.\n\n    Returns:\n      USBStorageDevice: an USB storage device.\n    \"\"\"\n    name_values = device_key.name.split('&')\n    device_type = None\n    product = None\n    revision = None\n    vendor = None\n\n    number_of_name_values = len(name_values)\n    if number_of_name_values >= 1:\n      device_type = name_values[0]\n    if number_of_name_values >= 2:\n      vendor = name_values[1]\n    if number_of_name_values >= 3:\n      product = name_values[2]\n    if number_of_name_values >= 4:\n      revision = name_values[3]\n\n    for device_instance_key in device_key.GetSubkeys():\n      properties = []\n      properties_key = device_instance_key.GetSubkeyByName('Properties')\n      if properties_key:\n        for property_set_key in properties_key.GetSubkeys():\n          for property_key in property_set_key.GetSubkeys():\n            for property_value_key in property_key.GetSubkeys():\n              storage_device_property = USBStorageDeviceProperty(\n                  property_set_key.name, property_key.name)\n\n              storage_device_property.value_type = self._GetPropertyValueType(\n                  property_value_key)\n              storage_device_property.value = self._GetPropertyValueData(\n                  property_value_key, storage_device_property.value_type)\n\n              properties.append(storage_device_property)\n\n      storage_device = USBStorageDevice()\n      storage_device.device_type = device_type\n      storage_device.display_name = self._GetStringValueFromKey(\n          device_instance_key, 'FriendlyName')\n      storage_device.key_path = device_instance_key.path\n      storage_device.product = product\n      storage_device.properties = properties\n      storage_device.revision = revision\n      storage_device.vendor = vendor\n\n    return storage_device\n\n  def _ParseFiletime(self, filetime):\n    \"\"\"Parses a FILETIME timestamp value.\n\n    Args:\n      filetime (int): a FILETIME timestamp value.\n\n    Returns:\n      dfdatetime.DateTimeValues: date and time values.\n    \"\"\"\n    if filetime == 0:\n      return dfdatetime_semantic_time.SemanticTime(string='Not set')\n\n    if filetime == 0x7fffffffffffffff:\n      return dfdatetime_semantic_time.SemanticTime(string='Never')\n\n    return dfdatetime_filetime.Filetime(timestamp=filetime)\n\n  def Collect(self, registry):\n    \"\"\"Collects USB storage devices.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Yields:\n      USBStorageDevice: an USB storage device.\n    \"\"\"\n    usbstor_key = registry.GetKeyByPath(self._USBSTOR_KEY_PATH)\n    if usbstor_key:\n      yield from self._CollectUSBStorageDevices(usbstor_key)\n"
  },
  {
    "path": "winregrc/usbstor.yaml",
    "content": "# dtFabric format specification.\n---\nname: usbstor\ntype: format\ndescription: USB storage device formats.\n---\nname: uint32le\ntype: integer\nattributes:\n  byte_order: little-endian\n  format: unsigned\n  size: 4\n  units: bytes\n---\nname: uint64le\ntype: integer\nattributes:\n  byte_order: little-endian\n  format: unsigned\n  size: 8\n  units: bytes\n---\nname: wchar16\ntype: character\nattributes:\n  size: 2\n  units: bytes\n---\nname: utf16le_string\ntype: string\nencoding: utf-16-le\nelement_data_type: wchar16\nelements_terminator: \"\\x00\\x00\"\n"
  },
  {
    "path": "winregrc/userassist.py",
    "content": "\"\"\"Windows UserAssist information collector.\"\"\"\n\nimport codecs\nimport logging\n\nfrom winregrc import data_format\nfrom winregrc import errors\nfrom winregrc import interface\n\n\nclass UserAssistEntry:\n  \"\"\"UserAssist entry.\n\n  Attributes:\n    guid (str): GUID.\n    name (str): name.\n    value_name (str): name of the Windows Registry value.\n  \"\"\"\n\n  def __init__(self, guid=None, name=None, value_name=None):\n    \"\"\"Initializes an UserAssist entry.\n\n    Args:\n      guid (Optional[str]): GUID.\n      name (Optional[str]): name.\n      value_name (Optional[str]): name of the Windows Registry value.\n    \"\"\"\n    super().__init__()\n    self.guid = guid\n    self.name = name\n    self.value_name = value_name\n\n\nclass UserAssistDataParser(data_format.BinaryDataFormat):\n  \"\"\"UserAssist data parser.\"\"\"\n\n  _DEFINITION_FILE = 'userassist.yaml'\n\n  # pylint: disable=missing-type-doc\n  def _DebugPrintEntry(self, format_version, user_assist_entry):\n    \"\"\"Prints UserAssist entry value debug information.\n\n    Args:\n      format_version (int): format version.\n      user_assist_entry (user_assist_entry_v3|user_assist_entry_v5):\n          UserAssist entry.\n    \"\"\"\n    self._DebugPrintValue('Unknown1', f'0x{user_assist_entry.unknown1:08x}')\n\n    self._DebugPrintDecimalValue(\n        'Number of executions', user_assist_entry.number_of_executions)\n\n    if format_version == 5:\n      self._DebugPrintDecimalValue(\n          'Application focus count',\n          user_assist_entry.application_focus_count)\n\n      self._DebugPrintDecimalValue(\n          'Application focus duration',\n          user_assist_entry.application_focus_duration)\n\n      self._DebugPrintValue('Unknown2', f'{user_assist_entry.unknown2:.2f}')\n      self._DebugPrintValue('Unknown3', f'{user_assist_entry.unknown3:.2f}')\n      self._DebugPrintValue('Unknown4', f'{user_assist_entry.unknown4:.2f}')\n      self._DebugPrintValue('Unknown5', f'{user_assist_entry.unknown5:.2f}')\n      self._DebugPrintValue('Unknown6', f'{user_assist_entry.unknown6:.2f}')\n      self._DebugPrintValue('Unknown7', f'{user_assist_entry.unknown7:.2f}')\n      self._DebugPrintValue('Unknown8', f'{user_assist_entry.unknown8:.2f}')\n      self._DebugPrintValue('Unknown9', f'{user_assist_entry.unknown9:.2f}')\n      self._DebugPrintValue('Unknown10', f'{user_assist_entry.unknown10:.2f}')\n      self._DebugPrintValue('Unknown11', f'{user_assist_entry.unknown11:.2f}')\n      self._DebugPrintValue('Unknown12', f'0x{user_assist_entry.unknown12:08x}')\n\n    self._DebugPrintFiletimeValue(\n        'Last execution time', user_assist_entry.last_execution_time)\n\n    if format_version == 5:\n      self._DebugPrintValue('Unknown13', '0x{user_assist_entry.unknown13:08x}')\n\n    self._DebugPrintText('\\n')\n\n  # pylint: disable=missing-return-type-doc\n  def ParseEntry(self, format_version, entry_data):\n    \"\"\"Parses an UserAssist entry.\n\n    Args:\n      format_version (int): format version.\n      entry_data (bytes): entry data.\n\n    Returns:\n      user_assist_entry_v3|user_assist_entry_v5: UserAssist entry.\n\n    Raises:\n      ParseError: if the value data could not be parsed.\n    \"\"\"\n    if format_version == 3:\n      data_type_map = self._GetDataTypeMap('user_assist_entry_v3')\n      expected_entry_data_size = 16\n    elif format_version == 5:\n      data_type_map = self._GetDataTypeMap('user_assist_entry_v5')\n      expected_entry_data_size = 72\n    else:\n      data_type_map = None\n      expected_entry_data_size = 0\n\n    if expected_entry_data_size != len(entry_data):\n      entry_data_size = len(entry_data)\n      raise errors.ParseError((\n          f'Version: {format_version:d} size mismatch (calculated: '\n          f'{expected_entry_data_size:d}, stored: {entry_data_size:d}).'))\n\n    try:\n      user_assist_entry = self._ReadStructureFromByteStream(\n          entry_data, 0, data_type_map, 'UserAssist entry')\n    except (ValueError, errors.ParseError) as exception:\n      raise errors.ParseError(\n          f'Unable to parse UserAssist entry value with error: {exception!s}')\n\n    if self._debug:\n      self._DebugPrintEntry(format_version, user_assist_entry)\n\n    return user_assist_entry\n\n\nclass UserAssistCollector(interface.WindowsRegistryKeyCollector):\n  \"\"\"Windows UserAssist information collector.\n\n  Returns:\n    user_assist_entries (list[UserAssistEntry]): UserAssist entries.\n  \"\"\"\n\n  _USER_ASSIST_KEY = (\n      'HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\'\n      'Explorer\\\\UserAssist')\n\n  def __init__(self, debug=False, output_writer=None):\n    \"\"\"Initializes a Windows UserAssist information collector.\n\n    Args:\n      debug (Optional[bool]): True if debug information should be printed.\n      output_writer (Optional[OutputWriter]): output writer.\n    \"\"\"\n    super().__init__(debug=debug)\n    self._output_writer = output_writer\n    self._parser = UserAssistDataParser(\n        debug=debug, output_writer=output_writer)\n    self.user_assist_entries = []\n\n  def _CollectUserAssistFromKey(self, guid_subkey):\n    \"\"\"Collects the UserAssist information from a GUID sub key.\n\n    Args:\n      guid_subkey (dfwinreg.WinRegistryKey): UserAssist GUID Registry key.\n    \"\"\"\n    version_value = guid_subkey.GetValueByName('Version')\n    if not version_value:\n      logging.warning(f'Missing Version value in sub key: {guid_subkey.name:s}')\n      return\n\n    format_version = version_value.GetDataAsObject()\n\n    if self._debug:\n      self._output_writer.WriteValue('GUID', guid_subkey.name)\n      self._output_writer.WriteIntegerValueAsDecimal(\n          'Format version', format_version)\n\n      self._output_writer.WriteText('\\n')\n\n    count_subkey = guid_subkey.GetSubkeyByName('Count')\n    for value in count_subkey.GetValues():\n      if self._debug:\n        self._output_writer.WriteValue('Original name', value.name)\n\n      try:\n        # Note that Python 2 codecs.decode() does not support keyword arguments\n        # such as encodings='rot-13'.\n        value_name = codecs.decode(value.name, 'rot-13')\n      except UnicodeEncodeError:\n        characters = []\n        for character in value.name:\n          if ord(character) < 128:\n            try:\n              character = codecs.decode(character, 'rot-13')\n              characters.append(character)\n            except UnicodeEncodeError:\n              characters.append(character)\n          else:\n            characters.append(character)\n\n        value_name = ''.join(characters)\n\n      if self._debug:\n        self._output_writer.WriteValue('Converted name', value_name)\n        self._output_writer.WriteDebugData('Value data:', value.data)\n\n      if value_name != 'UEME_CTLSESSION':\n        user_assist_entry = self._parser.ParseEntry(format_version, value.data)\n\n        user_assist_entry = UserAssistEntry(\n            guid=guid_subkey.name, name=value_name, value_name=value.name)\n        self.user_assist_entries.append(user_assist_entry)\n\n  def Collect(self, registry):  # pylint: disable=arguments-differ\n    \"\"\"Collects the UserAssist information.\n\n    Args:\n      registry (dfwinreg.WinRegistry): Windows Registry.\n\n    Returns:\n      bool: True if the UserAssist key was found, False if not.\n    \"\"\"\n    user_assist_key = registry.GetKeyByPath(self._USER_ASSIST_KEY)\n    if not user_assist_key:\n      return False\n\n    for guid_subkey in user_assist_key.GetSubkeys():\n      self._CollectUserAssistFromKey(guid_subkey)\n\n    return True\n"
  },
  {
    "path": "winregrc/userassist.yaml",
    "content": "# dtFabric format specification.\n---\nname: userassist\ntype: format\ndescription: UserAssist format\n---\nname: float32\ntype: floating-point\nattributes:\n  size: 4\n  units: bytes\n---\nname: uint32\ntype: integer\nattributes:\n  format: unsigned\n  size: 4\n  units: bytes\n---\nname: uint64\ntype: integer\nattributes:\n  format: unsigned\n  size: 8\n  units: bytes\n---\nname: user_assist_entry_v3\ntype: structure\ndescription: UserAssist format version used in Windows 2000, XP, 2003, Vista.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: unknown1\n  data_type: uint32\n- name: number_of_executions\n  data_type: uint32\n- name: last_execution_time\n  data_type: uint64\n---\nname: user_assist_entry_v5\ntype: structure\ndescription: UserAssist format version used in Windows 2008, 7, 8, 10.\nattributes:\n  byte_order: little-endian\nmembers:\n- name: unknown1\n  data_type: uint32\n- name: number_of_executions\n  data_type: uint32\n- name: application_focus_count\n  data_type: uint32\n- name: application_focus_duration\n  data_type: uint32\n- name: unknown2\n  data_type: float32\n- name: unknown3\n  data_type: float32\n- name: unknown4\n  data_type: float32\n- name: unknown5\n  data_type: float32\n- name: unknown6\n  data_type: float32\n- name: unknown7\n  data_type: float32\n- name: unknown8\n  data_type: float32\n- name: unknown9\n  data_type: float32\n- name: unknown10\n  data_type: float32\n- name: unknown11\n  data_type: float32\n- name: unknown12\n  data_type: uint32\n- name: last_execution_time\n  data_type: uint64\n- name: unknown13\n  data_type: uint32\n"
  },
  {
    "path": "winregrc/versions.py",
    "content": "\"\"\"Windows versions.\"\"\"\n\n\nclass WindowsVersions:\n  \"\"\"Windows versions.\"\"\"\n\n  _SORT_KEY_PER_VERSION = {\n       # TODO: update the dates of the Windows 10 releases.\n      'Windows 10 (1511)': 2015,\n      'Windows 10 (1607)': 2015,\n      'Windows 10 (1703)': 2015,\n      'Windows 10 (1709)': 2015,\n      'Windows 10 (1803)': 2015,\n      'Windows 10 (1809)': 2015,\n      'Windows 10 (1903)': 2015,\n      'Windows 10 (1909)': 2015,\n      'Windows 10 (2004)': 2015,\n      'Windows 10 (20H2)': 2015,\n      'Windows 11 (21H2)': 2021,\n      'Windows 2000': 2000,\n      'Windows 2003': 2003,\n      'Windows 2003 R2': 2005,\n      'Windows 2008': 2008,\n      'Windows 2008 R2': 2009,\n      'Windows 2012': 2012,\n      'Windows 2012 R2': 2013,\n      'Windows 2016': 2016,\n      'Windows 2019': 2019,\n      'Windows 7': 2009,\n      'Windows 8.0': 2012,\n      'Windows 8.1': 2013,\n      'Windows 95': 1995,\n      'Windows 98': 1998,\n      'Windows Me': 2000,\n      'Windows NT4': 1996,\n      'Windows Vista': 2007,\n      'Windows XP 32-bit': 2001,\n      'Windows XP 64-bit': 2005}\n\n  @classmethod\n  def KeyFunction(cls, windows_version):\n    \"\"\"Key function for sorting.\n\n    Args:\n      windows_version (str): Windows version.\n\n    Returns:\n      tuple[int, str]: sort key and Windows version\n    \"\"\"\n    sort_key = cls._SORT_KEY_PER_VERSION.get(windows_version, 9999)\n    return sort_key, windows_version\n"
  },
  {
    "path": "winregrc/volume_scanner.py",
    "content": "\"\"\"Windows Registry volume scanner.\"\"\"\n\nfrom dfimagetools import windows_registry\n\nfrom dfvfs.helpers import command_line as dfvfs_command_line\nfrom dfvfs.helpers import volume_scanner as dfvfs_volume_scanner\nfrom dfvfs.lib import definitions as dfvfs_definitions\nfrom dfvfs.lib import errors as dfvfs_errors\nfrom dfvfs.resolver import resolver as dfvfs_resolver\n\nfrom dfwinreg import interface as dfwinreg_interface\nfrom dfwinreg import registry as dfwinreg_registry\n\n\nclass VolumeScannerOptions(dfvfs_volume_scanner.VolumeScannerOptions):\n  \"\"\"Volume scanner options.\n\n  Attributes:\n    credentials (list[tuple[str, str]]): credentials, per type, to unlock\n        volumes.\n    partitions (list[str]): partition identifiers.\n    scan_mode (str): mode that defines how the VolumeScanner should scan\n        for volumes and snapshots.\n    snapshots (list[str]): snapshot identifiers.\n    username (str): username.\n    volumes (list[str]): volume identifiers, e.g. those of an APFS or LVM\n        volume system.\n  \"\"\"\n\n  def __init__(self):\n    \"\"\"Initializes volume scanner options.\"\"\"\n    super().__init__()\n    self.username = None\n\n\nclass SingleFileWindowsRegistryFileReader(\n    dfwinreg_interface.WinRegistryFileReader):\n  \"\"\"Single file Windows Registry file reader.\"\"\"\n\n  def __init__(self, path):\n    \"\"\"Initializes a single file Windows Registry file reader.\n\n    Args:\n      path (str): path of the Windows Registry file.\n    \"\"\"\n    super().__init__()\n    self._path = path\n\n  def Open(self, path, ascii_codepage='cp1252'):\n    \"\"\"Opens the Windows Registry file specified by the path.\n\n    Args:\n      path (str): path of the Windows Registry file. The path is a Windows path\n          relative to the root of the file system that contains the specific\n          Windows Registry file. E.g. C:\\\\Windows\\\\System32\\\\config\\\\SYSTEM\n      ascii_codepage (Optional[str]): ASCII string codepage.\n\n    Returns:\n      WinRegistryFile: Windows Registry file or None if the file cannot\n          be opened.\n    \"\"\"\n    file_object = open(self._path, 'rb')  # pylint: disable=consider-using-with\n    if file_object is None:\n      return None\n\n    try:\n      signature = file_object.read(4)\n\n      if signature == b'regf':\n        registry_file = windows_registry.REGFWindowsRegistryFile(\n            ascii_codepage=ascii_codepage)\n      else:\n        registry_file = windows_registry.CREGWindowsRegistryFile(\n            ascii_codepage=ascii_codepage)\n\n      # Note that registry_file takes over management of file_object.\n      registry_file.Open(file_object)\n\n    except OSError:\n      file_object.close()\n      return None\n\n    return registry_file\n\n\nclass WindowsRegistryVolumeScanner(dfvfs_volume_scanner.WindowsVolumeScanner):\n  \"\"\"Windows Registry volume scanner.\n\n  Attributes:\n    registry (dfwinreg.WinRegistry): Windows Registry.\n  \"\"\"\n\n  def __init__(self, mediator=None):\n    \"\"\"Initializes a Windows Registry collector.\n\n    Args:\n      mediator (Optional[dfvfs.VolumeScannerMediator]): a volume scanner\n          mediator.\n    \"\"\"\n    super().__init__(mediator=mediator)\n    self._single_file = False\n    self._users_path = False\n\n    self.registry = None\n\n  def _GetUsername(self, options):\n    \"\"\"Determines the username.\n\n    Args:\n      options (VolumeScannerOptions): volume scanner options.\n\n    Returns:\n      str: username or None if not available.\n\n    Raises:\n      ScannerError: if the scanner does not know how to proceed.\n      UserAbort: if the user requested to abort.\n    \"\"\"\n    usernames = []\n\n    # TODO: handle alternative users path locations\n    self._users_path = '\\\\Users'\n    users_path_spec = self._path_resolver.ResolvePath(self._users_path)\n    if not users_path_spec:\n      self._users_path = '\\\\Documents and Settings'\n      users_path_spec = self._path_resolver.ResolvePath(self._users_path)\n\n    if users_path_spec:\n      users_file_entry = dfvfs_resolver.Resolver.OpenFileEntry(\n          users_path_spec)\n      for sub_file_entry in users_file_entry.sub_file_entries:\n        if sub_file_entry.IsDirectory():\n          usernames.append(sub_file_entry.name)\n\n    if not usernames:\n      return None\n\n    # Handle options without an username.\n    if hasattr(options, 'username'):\n      if options.username == ['none']:\n        return None\n\n      if options.username:\n        if options.username in usernames:\n          return options.username\n\n    elif len(usernames) == 1:\n      return usernames[0]\n\n    if not self._mediator:\n      raise dfvfs_errors.ScannerError(\n          'Unable to proceed. Found user profile paths but no mediator to '\n          'determine which user to select.')\n\n    try:\n      username = self._mediator.GetUsername(usernames)\n\n    except KeyboardInterrupt:\n      raise dfvfs_errors.UserAbort('Volume scan aborted.')\n\n    return username\n\n  def IsSingleFileRegistry(self):\n    \"\"\"Determines if the Registry consists of a single file.\n\n    Returns:\n      bool: True if the Registry consists of a single file.\n    \"\"\"\n    return self._single_file\n\n  def ScanForWindowsVolume(self, source_path, options=None):\n    \"\"\"Scans for a Windows volume.\n\n    Args:\n      source_path (str): source path.\n      options (Optional[VolumeScannerOptions]): volume scanner options. If None\n          the default volume scanner options are used, which are defined in the\n          VolumeScannerOptions class.\n\n    Returns:\n      bool: True if a Windows volume was found.\n\n    Raises:\n      ScannerError: if the source path does not exists, or if the source path\n          is not a file or directory, or if the format of or within\n          the source file is not supported.\n    \"\"\"\n    result = super().ScanForWindowsVolume(\n        source_path, options=options)\n\n    registry_file_reader = None\n    if self._source_type == dfvfs_definitions.SOURCE_TYPE_FILE:\n      self._single_file = True\n\n      registry_file_reader = SingleFileWindowsRegistryFileReader(source_path)\n\n    elif result:\n      username = self._GetUsername(options)\n      if username:\n        self._path_resolver.SetEnvironmentVariable(\n            'UserProfile', f'{self._users_path:s}\\\\{username:s}')\n\n      registry_file_reader = (\n          windows_registry.StorageMediaImageWindowsRegistryFileReader(\n              self._file_system, self._path_resolver))\n\n    if registry_file_reader:\n      self.registry = dfwinreg_registry.WinRegistry(\n          registry_file_reader=registry_file_reader)\n\n    return bool(registry_file_reader)\n\n\nclass WindowsRegistryVolumeScannerMediator(\n    dfvfs_command_line.CLIVolumeScannerMediator):\n  \"\"\"Windows Registry volume scanner mediator.\"\"\"\n\n  _USER_PROMPT_USERNAMES = (\n      'Please specify the username that should be processed. Note that you can '\n      'abort with Ctrl^C.')\n\n  def GetUsername(self, usernames):\n    \"\"\"Retrieves a username.\n\n    This method can be used to prompt the user to provide a username.\n\n    Args:\n      usernames (list[str]): usernames.\n\n    Returns:\n      str: selected username or None.\n    \"\"\"\n    # TODO: use user artifact\n    self._PrintUsernames(usernames)\n\n    while True:\n      self._output_writer.Write('\\n')\n\n      lines = self._textwrapper.wrap(self._USER_PROMPT_USERNAMES)\n      self._output_writer.Write('\\n'.join(lines))\n      self._output_writer.Write('\\n\\nUsername: ')\n\n      try:\n        selected_username = self._input_reader.Read()\n        selected_username = selected_username.strip()\n        if selected_username in usernames:\n          break\n      except ValueError:\n        pass\n\n      self._output_writer.Write('\\n')\n\n      lines = self._textwrapper.wrap(\n          'Unsupported username, please try again or abort with Ctrl^C.')\n      self._output_writer.Write('\\n'.join(lines))\n      self._output_writer.Write('\\n\\n')\n\n    return selected_username\n\n  def _PrintUsernames(self, usernames):\n    \"\"\"Prints an overview of usernames.\n\n    Args:\n      usernames (list[str]): usernames.\n\n    Raises:\n      ScannerError: if a username cannot be resolved.\n    \"\"\"\n    header = 'The following usernames were found:\\n'\n    self._output_writer.Write(header)\n\n    column_names = ['Username', 'Profile path']\n    table_view = dfvfs_command_line.CLITabularTableView(\n        column_names=column_names)\n\n    for username in sorted(usernames, key=lambda username: username.lower()):\n      # TODO: use user artifact\n      table_view.AddRow([username, f'C:\\\\Users\\\\{username:s}'])\n\n    self._output_writer.Write('\\n')\n    table_view.Write(self._output_writer)\n"
  }
]