Skip to content

Commit 6375472

Browse files
authored
Changes to VirtualREGFWinRegistryKey (#224)
1 parent 62c37ca commit 6375472

File tree

2 files changed

+73
-38
lines changed

2 files changed

+73
-38
lines changed

dfwinreg/regf.py

Lines changed: 70 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,9 @@ def GetRootKey(self):
164164
self._current_control_set_key_path)
165165

166166
registry_key = VirtualREGFWinRegistryKey(
167-
'', regf_key, current_control_set_key=current_control_set_key,
168-
key_path=self._key_path_prefix)
167+
'', regf_key, key_path=self._key_path_prefix)
168+
registry_key.AddVirtualSubKey(
169+
'CurrentControlSet', current_control_set_key)
169170

170171
else:
171172
registry_key = REGFWinRegistryKey(
@@ -327,25 +328,23 @@ def GetValueByName(self, name):
327328
class VirtualREGFWinRegistryKey(REGFWinRegistryKey):
328329
"""Implementation of a virtual Windows Registry key using pyregf.
329330
330-
The virtual Windows Registry key are keys that do not exist on-disk but do
331-
exist at run-time, for example HKEY_LOCAL_MACHINE\\System\\CurrentControlSet.
331+
Virtual Windows Registry key are used to handle keys that do not exist on-disk
332+
but do exist at run-time, like HKEY_LOCAL_MACHINE\\System\\CurrentControlSet.
332333
"""
333334

334-
def __init__(
335-
self, name, pyregf_key, current_control_set_key=None, key_path=''):
335+
def __init__(self, name, pyregf_key, key_path=''):
336336
"""Initializes a virtual Windows Registry key.
337337
338338
Args:
339339
name (str): name of the Windows Registry key.
340340
pyregf_key (pyregf.key): pyregf key object.
341-
current_control_set_key (Optional[pyregf.key]): pyregf key object of
342-
the control set key that represents CurrentControlSet.
343341
key_path (Optional[str]): Windows Registry key path.
344342
"""
345343
super(VirtualREGFWinRegistryKey, self).__init__(
346344
pyregf_key, key_path=key_path)
347-
self._current_control_set_key = current_control_set_key
348345
self._name = name
346+
self._virtual_subkeys = []
347+
self._virtual_subkeys_by_name = {}
349348

350349
@property
351350
def name(self):
@@ -356,10 +355,43 @@ def name(self):
356355
def number_of_subkeys(self):
357356
"""int: number of subkeys within the key."""
358357
number_of_keys = self._pyregf_key.number_of_sub_keys
359-
if self._current_control_set_key:
360-
number_of_keys += 1
358+
if self._virtual_subkeys:
359+
number_of_keys += len(self._virtual_subkeys)
361360
return number_of_keys
362361

362+
def _GetVirtualSubKey(self, name):
363+
"""Retrieves a virtual subkey.
364+
365+
Args:
366+
name (str): name of the Windows Registry subkey.
367+
368+
Raises:
369+
tuple[str, pyregf.key]: name and pyregf key object of the subkey.
370+
"""
371+
lookup_name = name.upper()
372+
subkey_index = self._virtual_subkeys_by_name.get(lookup_name, None)
373+
if subkey_index is None:
374+
return None, None
375+
376+
return self._virtual_subkeys[subkey_index]
377+
378+
def AddVirtualSubKey(self, name, subkey):
379+
"""Adds a virtual subkey.
380+
381+
Args:
382+
name (str): name of the Windows Registry subkey.
383+
subkey (pyregf.key): pyregf key object of the subkey.
384+
385+
Raises:
386+
ValueError: if the subkey already exists.
387+
"""
388+
lookup_name = name.upper()
389+
if lookup_name in self._virtual_subkeys_by_name:
390+
raise ValueError(f'Subkey: {name:s} already set')
391+
392+
self._virtual_subkeys_by_name[lookup_name] = len(self._virtual_subkeys)
393+
self._virtual_subkeys.append((name, subkey))
394+
363395
def GetSubkeyByIndex(self, index):
364396
"""Retrieves a subkey by index.
365397
@@ -375,16 +407,20 @@ def GetSubkeyByIndex(self, index):
375407
if index < 0 or index >= self.number_of_subkeys:
376408
raise IndexError('Index out of bounds.')
377409

378-
if (self._current_control_set_key and
379-
index == self._pyregf_key.number_of_sub_keys):
380-
name = 'CurrentControlSet'
381-
key_path = key_paths.JoinKeyPath([self._key_path, name])
382-
return VirtualREGFWinRegistryKey(
383-
name, self._current_control_set_key, key_path=key_path)
410+
if index < self._pyregf_key.number_of_sub_keys:
411+
pyregf_key = self._pyregf_key.get_sub_key(index)
412+
key_path = key_paths.JoinKeyPath([self._key_path, pyregf_key.name])
413+
subkey = REGFWinRegistryKey(pyregf_key, key_path=key_path)
384414

385-
pyregf_key = self._pyregf_key.get_sub_key(index)
386-
key_path = key_paths.JoinKeyPath([self._key_path, pyregf_key.name])
387-
return REGFWinRegistryKey(pyregf_key, key_path=key_path)
415+
else:
416+
index -= self._pyregf_key.number_of_sub_keys
417+
418+
virtual_name, virtual_subkey = self._virtual_subkeys[index]
419+
key_path = key_paths.JoinKeyPath([self._key_path, virtual_name])
420+
subkey = VirtualREGFWinRegistryKey(
421+
virtual_name, virtual_subkey, key_path=key_path)
422+
423+
return subkey
388424

389425
def GetSubkeyByName(self, name):
390426
"""Retrieves a subkey by name.
@@ -395,11 +431,11 @@ def GetSubkeyByName(self, name):
395431
Returns:
396432
WinRegistryKey: Windows Registry subkey or None if not found.
397433
"""
398-
if self._current_control_set_key and name.upper() == 'CURRENTCONTROLSET':
399-
name = 'CurrentControlSet'
400-
key_path = key_paths.JoinKeyPath([self._key_path, name])
434+
virtual_name, virtual_sub_key = self._GetVirtualSubKey(name)
435+
if virtual_sub_key:
436+
key_path = key_paths.JoinKeyPath([self._key_path, virtual_name])
401437
return VirtualREGFWinRegistryKey(
402-
name, self._current_control_set_key, key_path=key_path)
438+
virtual_name, virtual_sub_key, key_path=key_path)
403439

404440
pyregf_key = self._pyregf_key.get_sub_key_by_name(name)
405441
if not pyregf_key:
@@ -422,22 +458,19 @@ def GetSubkeyByPath(self, key_path):
422458

423459
key_path_segments = key_path.split('\\')
424460

425-
if (self._current_control_set_key and
426-
key_path_segments[0].upper() == 'CURRENTCONTROLSET'):
461+
virtual_name, virtual_sub_key = self._GetVirtualSubKey(key_path_segments[0])
462+
if not virtual_sub_key:
463+
pyregf_key = self._pyregf_key.get_sub_key_by_path(key_path)
464+
else:
427465
key_path_segments.pop(0)
428466

429467
if not key_path_segments:
430-
name = 'CurrentControlSet'
431-
key_path = key_paths.JoinKeyPath([self._key_path, name])
468+
key_path = key_paths.JoinKeyPath([self._key_path, virtual_name])
432469
return VirtualREGFWinRegistryKey(
433-
name, self._current_control_set_key, key_path=key_path)
470+
virtual_name, virtual_sub_key, key_path=key_path)
434471

435472
sub_key_path = '\\'.join(key_path_segments)
436-
pyregf_key = self._current_control_set_key.get_sub_key_by_path(
437-
sub_key_path)
438-
439-
else:
440-
pyregf_key = self._pyregf_key.get_sub_key_by_path(key_path)
473+
pyregf_key = virtual_sub_key.get_sub_key_by_path(sub_key_path)
441474

442475
if not pyregf_key:
443476
return None
@@ -455,11 +488,10 @@ def GetSubkeys(self):
455488
key_path = key_paths.JoinKeyPath([self._key_path, pyregf_key.name])
456489
yield REGFWinRegistryKey(pyregf_key, key_path=key_path)
457490

458-
if self._current_control_set_key:
459-
key_path = key_paths.JoinKeyPath([self._key_path, 'CurrentControlSet'])
491+
for virtual_name, virtual_sub_key in self._virtual_subkeys:
492+
key_path = key_paths.JoinKeyPath([self._key_path, virtual_name])
460493
yield VirtualREGFWinRegistryKey(
461-
'CurrentControlSet', self._current_control_set_key,
462-
key_path=key_path)
494+
virtual_name, virtual_sub_key, key_path=key_path)
463495

464496

465497
class REGFWinRegistryValue(interface.WinRegistryValue):

dfwinreg/registry.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@ def _GetFileByPath(self, key_path_upper):
283283
key_path_prefix_upper = key_path_prefix.upper()
284284
self.MapFile(key_path_prefix_upper, registry_file)
285285

286+
# TODO: if HKEY_CURRENT_USER set 'HKEY_CURRENT_USER\\SOFTWARE\\CLASSES' as
287+
#virtual key in the file.
288+
286289
return key_path_prefix_upper, registry_file
287290

288291
def _GetKeyByPathFromFile(self, key_path):

0 commit comments

Comments
 (0)