@@ -211,6 +211,11 @@ def reg_parse(location):
211211 """
212212 for installed_program in report_installed_programs (location ):
213213 yield installed_program
214+ for installed_program in report_installed_programs (
215+ location ,
216+ registry_path = '\\ Wow6432Node\\ Microsoft\\ Windows\\ CurrentVersion\\ Uninstall'
217+ ):
218+ yield installed_program
214219 for installed_dotnet in report_installed_dotnet_versions (location ):
215220 yield installed_dotnet
216221
@@ -222,22 +227,38 @@ def get_installed_packages(root_dir, is_container=True):
222227 """
223228 # These paths are relative to a Windows docker image layer root directory
224229 if is_container :
225- software_registry_locations = [
226- os .path .join (root_dir , 'Hives' , 'Software_Delta' ),
227- os .path .join (root_dir , 'Files' , 'Windows' , 'System32' , 'config' , 'SOFTWARE' )
228- ]
229- # We are setting the root to be the `Files` directory, since this
230- # directory represents the root `C:\` drive of a Windows installation
231- root_dir = os .path .join (root_dir , 'Files' )
230+ hives_software_delta_loc = os .path .join (root_dir , 'Hives' , 'Software_Delta' )
231+ files_software_loc = os .path .join (
232+ root_dir ,
233+ 'Files' ,
234+ 'Windows' ,
235+ 'System32' ,
236+ 'config' ,
237+ 'SOFTWARE'
238+ )
239+ utilityvm_software_loc = os .path .join (
240+ root_dir ,
241+ 'UtilityVM' ,
242+ 'Files' ,
243+ 'Windows' ,
244+ 'System32' ,
245+ 'config' ,
246+ 'SOFTWARE'
247+ )
248+ root_prefixes_by_software_registry_locations = {
249+ hives_software_delta_loc : 'Files' ,
250+ files_software_loc : 'Files' ,
251+ utilityvm_software_loc : os .path .join ('UtilityVM' , 'Files' )
252+ }
232253 else :
233254 # TODO: Add support for virtual machines
234255 raise Exception ('Unsuported file system type' )
235256
236- for software_registry_loc in software_registry_locations :
257+ for software_registry_loc , root_prefix in root_prefixes_by_software_registry_locations . items () :
237258 if not os .path .exists (software_registry_loc ):
238259 continue
239260 for package in reg_parse (software_registry_loc ):
240- package .populate_installed_files (root_dir )
261+ package .populate_installed_files (root_dir , root_prefix = root_prefix )
241262 yield package
242263
243264
@@ -264,16 +285,27 @@ def create_absolute_installed_file_path(root_dir, file_path):
264285 return str (Path (root_dir ).joinpath (file_path ))
265286
266287
267- def create_relative_file_path (file_path , root_dir ):
288+ def create_relative_file_path (file_path , root_dir , root_prefix = '' ):
268289 """
269290 Return a subpath of `file_path` that is relative to `root_dir`
270291
271292 >>> file_path = '/home/test/example/foo.txt'
272293 >>> root_dir = '/home/test/'
273294 >>> create_relative_file_path(file_path, root_dir)
274295 'example/foo.txt'
296+
297+ If there is a `root_prefix`, then it is prepended to the resulting
298+ relative file path.
299+
300+ >>> file_path = '/home/test/example/foo.txt'
301+ >>> root_dir = '/home/test/'
302+ >>> create_relative_file_path(file_path, root_dir, 'prefix')
303+ 'prefix/example/foo.txt'
275304 """
276- return str (Path (file_path ).relative_to (root_dir ))
305+ relative_file_path = str (Path (file_path ).relative_to (root_dir ))
306+ if root_prefix :
307+ return os .path .join (root_prefix , relative_file_path )
308+ return relative_file_path
277309
278310
279311@attr .s ()
@@ -285,11 +317,19 @@ def recognize(cls, location):
285317 for installed in reg_parse (location ):
286318 yield installed
287319
288- def populate_installed_files (self , root_dir ):
320+ def populate_installed_files (self , root_dir , root_prefix = '' ):
289321 install_location = self .extra_data .get ('install_location' )
290322 if not install_location :
291323 return
292324
325+ if root_prefix :
326+ # The rootfs location of a Docker image layer can be in a
327+ # subdirectory of the layer directory (where `root_dir` is the path
328+ # to the layer directory), so we append `root_prefix` (where prefix
329+ # is relative to the file paths within the Docker image layer's
330+ # rootfs files) to `root_dir`
331+ root_dir = os .path .join (root_dir , root_prefix )
332+
293333 absolute_install_location = create_absolute_installed_file_path (
294334 root_dir = root_dir ,
295335 file_path = install_location
@@ -301,7 +341,11 @@ def populate_installed_files(self, root_dir):
301341 for root , _ , files in os .walk (absolute_install_location ):
302342 for file in files :
303343 installed_file_location = os .path .join (root , file )
304- relative_installed_file_path = create_relative_file_path (installed_file_location , root_dir )
344+ relative_installed_file_path = create_relative_file_path (
345+ file_path = installed_file_location ,
346+ root_dir = root_dir ,
347+ root_prefix = root_prefix
348+ )
305349 installed_files .append (relative_installed_file_path )
306350
307351 known_program_files = self .extra_data .get ('known_program_files' , [])
@@ -310,7 +354,11 @@ def populate_installed_files(self, root_dir):
310354 root_dir = root_dir ,
311355 file_path = known_program_file_path ,
312356 )
313- relative_known_file_path = create_relative_file_path (known_program_file_location , root_dir )
357+ relative_known_file_path = create_relative_file_path (
358+ file_path = known_program_file_location ,
359+ root_dir = root_dir ,
360+ root_prefix = root_prefix
361+ )
314362 if (not os .path .exists (known_program_file_location )
315363 or relative_known_file_path in installed_files ):
316364 continue
0 commit comments