VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testboxscript/win/fix_stale_refs.py@ 96407

Last change on this file since 96407 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.2 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: fix_stale_refs.py 96407 2022-08-22 17:43:14Z vboxsync $
3
4"""
5This module must be used interactively!
6Use with caution as it will delete some values from the regisry!
7
8It tries to locate client references to products that no longer exist.
9"""
10
11__copyright__ = \
12"""
13Copyright (C) 2012-2022 Oracle and/or its affiliates.
14
15This file is part of VirtualBox base platform packages, as
16available from https://www.virtualbox.org.
17
18This program is free software; you can redistribute it and/or
19modify it under the terms of the GNU General Public License
20as published by the Free Software Foundation, in version 3 of the
21License.
22
23This program is distributed in the hope that it will be useful, but
24WITHOUT ANY WARRANTY; without even the implied warranty of
25MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26General Public License for more details.
27
28You should have received a copy of the GNU General Public License
29along with this program; if not, see <https://www.gnu.org/licenses>.
30
31The contents of this file may alternatively be used under the terms
32of the Common Development and Distribution License Version 1.0
33(CDDL), a copy of it is provided in the "COPYING.CDDL" file included
34in the VirtualBox distribution, in which case the provisions of the
35CDDL are applicable instead of those of the GPL.
36
37You may elect to license modified versions of this file under the
38terms and conditions of either the GPL or the CDDL or both.
39
40SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
41"""
42__version__ = "$Revision: 96407 $"
43
44
45from _winreg import HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS
46from _winreg import OpenKey, CloseKey, EnumKey, QueryInfoKey, EnumValue, DeleteValue, QueryValueEx
47from distutils.util import strtobool
48
49def reverse_bytes(hex_string):
50 """
51 This function reverses the order of bytes in the provided string.
52 Each byte is represented by two characters which are reversed as well.
53 """
54 #print 'reverse_bytes(' + hex_string + ')'
55 chars = len(hex_string)
56 if chars > 2:
57 return reverse_bytes(hex_string[chars/2:]) + reverse_bytes(hex_string[:chars/2])
58 else:
59 return hex_string[1] + hex_string[0]
60
61def transpose_guid(guid):
62 """
63 Windows Installer uses different way to present GUID string. This function converts GUID
64 from installer's presentation to more conventional form.
65 """
66 return '{' + reverse_bytes(guid[0:8]) + '-' + reverse_bytes(guid[8:12]) + \
67 '-' + reverse_bytes(guid[12:16]) + \
68 '-' + reverse_bytes(guid[16:18]) + reverse_bytes(guid[18:20]) + \
69 '-' + ''.join([reverse_bytes(guid[i:i+2]) for i in range(20, 32, 2)]) + '}'
70
71PRODUCTS_KEY = r'SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products'
72COMPONENTS_KEY = r'SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components'
73
74def get_installed_products():
75 """
76 Enumerate all installed products.
77 """
78 products = {}
79 hkey_products = OpenKey(HKEY_LOCAL_MACHINE, PRODUCTS_KEY, 0, KEY_ALL_ACCESS)
80
81 try:
82 product_index = 0
83 while True:
84 product_guid = EnumKey(hkey_products, product_index)
85 hkey_product_properties = OpenKey(hkey_products, product_guid + r'\InstallProperties', 0, KEY_ALL_ACCESS)
86 try:
87 value = QueryValueEx(hkey_product_properties, 'DisplayName')[0]
88 except WindowsError as oXcpt:
89 if oXcpt.winerror != 2:
90 raise
91 value = '<unknown>'
92 CloseKey(hkey_product_properties)
93 products[product_guid] = value
94 product_index += 1
95 except WindowsError as oXcpt:
96 if oXcpt.winerror != 259:
97 print(oXcpt.strerror + '.', 'error', oXcpt.winerror)
98 CloseKey(hkey_products)
99
100 print('Installed products:')
101 for product_key in sorted(products.keys()):
102 print(transpose_guid(product_key), '=', products[product_key])
103
104 print()
105 return products
106
107def get_missing_products(hkey_components):
108 """
109 Detect references to missing products.
110 """
111 products = get_installed_products()
112
113 missing_products = {}
114
115 for component_index in xrange(0, QueryInfoKey(hkey_components)[0]):
116 component_guid = EnumKey(hkey_components, component_index)
117 hkey_component = OpenKey(hkey_components, component_guid, 0, KEY_ALL_ACCESS)
118 clients = []
119 for value_index in xrange(0, QueryInfoKey(hkey_component)[1]):
120 client_guid, client_path = EnumValue(hkey_component, value_index)[:2]
121 clients.append((client_guid, client_path))
122 if not client_guid in products:
123 if client_guid in missing_products:
124 missing_products[client_guid].append((component_guid, client_path))
125 else:
126 missing_products[client_guid] = [(component_guid, client_path)]
127 CloseKey(hkey_component)
128 return missing_products
129
130def main():
131 """
132 Enumerate all installed products, go through all components and check if client refences
133 point to valid products. Remove references to non-existing products if the user allowed it.
134 """
135 hkey_components = OpenKey(HKEY_LOCAL_MACHINE, COMPONENTS_KEY, 0, KEY_ALL_ACCESS)
136
137 missing_products = get_missing_products(hkey_components)
138
139 print('Missing products refer the following components:')
140 for product_guid in sorted(missing_products.keys()):
141 if product_guid[1:] == '0'*31:
142 continue
143 print('Product', transpose_guid(product_guid) + ':')
144 for component_guid, component_file in missing_products[product_guid]:
145 print(' ' + transpose_guid(component_guid), '=', component_file)
146
147 print('Remove all references to product', transpose_guid(product_guid) + '? [y/n]')
148 if strtobool(raw_input().lower()):
149 for component_guid, component_file in missing_products[product_guid]:
150 hkey_component = OpenKey(hkey_components, component_guid, 0, KEY_ALL_ACCESS)
151 print('Removing reference in ' + transpose_guid(component_guid), '=', component_file)
152 DeleteValue(hkey_component, product_guid)
153 CloseKey(hkey_component)
154 else:
155 print('Cancelled removal of product', transpose_guid(product_guid))
156
157 CloseKey(hkey_components)
158
159if __name__ == "__main__":
160 main()
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette