Updated files to meet PEP8 guidelines

* Fixes issue #42
  * More work is likely needed
This commit is contained in:
2Shirt 2018-12-27 21:46:04 -07:00
commit 7b8b1ab111
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
33 changed files with 7011 additions and 6612 deletions

View file

@ -12,19 +12,20 @@ from functions.network import *
init_global_vars()
if __name__ == '__main__':
try:
# Prep
clear_screen()
try:
# Prep
clear_screen()
# Connect
connect_to_network()
# Done
print_standard('\nDone.')
#pause("Press Enter to exit...")
exit_script()
except SystemExit:
pass
except:
major_exception()
# Connect
connect_to_network()
# Done
print_standard('\nDone.')
#pause("Press Enter to exit...")
exit_script()
except SystemExit:
pass
except:
major_exception()
# vim: sts=2 sw=2 ts=2

View file

@ -6,58 +6,58 @@ import os
import sys
# Init
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
os.chdir(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(os.getcwd())
from functions.ddrescue import *
from functions.hw_diags import *
init_global_vars()
if __name__ == '__main__':
try:
# Prep
clear_screen()
args = list(sys.argv)
run_mode = ''
source_path = None
dest_path = None
# Parse args
try:
# Prep
clear_screen()
args = list(sys.argv)
run_mode = ''
source_path = None
dest_path = None
script_name = os.path.basename(args.pop(0))
run_mode = str(args.pop(0)).lower()
source_path = args.pop(0)
dest_path = args.pop(0)
except IndexError:
# We'll set the missing paths later
pass
# Parse args
try:
script_name = os.path.basename(args.pop(0))
run_mode = str(args.pop(0)).lower()
source_path = args.pop(0)
dest_path = args.pop(0)
except IndexError:
# We'll set the missing paths later
pass
# Show usage
if re.search(r'-+(h|help)', str(sys.argv), re.IGNORECASE):
show_usage(script_name)
exit_script()
# Show usage
if re.search(r'-+(h|help)', str(sys.argv), re.IGNORECASE):
show_usage(script_name)
exit_script()
# Start cloning/imaging
if run_mode in ('clone', 'image'):
menu_ddrescue(source_path, dest_path, run_mode)
else:
if not re.search(r'^-*(h|help\?)', run_mode, re.IGNORECASE):
print_error('Invalid mode.')
# Start cloning/imaging
if run_mode in ('clone', 'image'):
menu_ddrescue(source_path, dest_path, run_mode)
else:
if not re.search(r'^-*(h|help\?)', run_mode, re.IGNORECASE):
print_error('Invalid mode.')
# Done
print_standard('\nDone.')
pause("Press Enter to exit...")
exit_script()
except GenericAbort:
abort()
except GenericError as ge:
msg = 'Generic Error'
if str(ge):
msg = str(ge)
print_error(msg)
abort()
except SystemExit:
pass
except:
major_exception()
# Done
print_standard('\nDone.')
pause("Press Enter to exit...")
exit_script()
except GenericAbort:
abort()
except GenericError as ge:
msg = 'Generic Error'
if str(ge):
msg = str(ge)
print_error(msg)
abort()
except SystemExit:
pass
except:
major_exception()
# vim: sts=4 sw=4 ts=4
# vim: sts=2 sw=2 ts=2

View file

@ -6,61 +6,68 @@ from borrowed import acpi
from functions.common import *
from os import environ
# Variables
# STATIC VARIABLES
SLMGR = r'{}\System32\slmgr.vbs'.format(environ.get('SYSTEMROOT'))
def activate_with_bios():
"""Attempt to activate Windows with a key stored in the BIOS."""
# Code borrowed from https://github.com/aeruder/get_win8key
#####################################################
#script to query windows 8.x OEM key from PC firmware
#ACPI -> table MSDM -> raw content -> byte offset 56 to end
#ck, 03-Jan-2014 (christian@korneck.de)
#####################################################
bios_key = None
table = b"MSDM"
if acpi.FindAcpiTable(table) is True:
rawtable = acpi.GetAcpiTable(table)
#http://msdn.microsoft.com/library/windows/hardware/hh673514
#byte offset 36 from beginning \
# = Microsoft 'software licensing data structure' \
# / 36 + 20 bytes offset from beginning = Win Key
bios_key = rawtable[56:len(rawtable)].decode("utf-8")
if bios_key is None:
raise BIOSKeyNotFoundError
"""Attempt to activate Windows with a key stored in the BIOS."""
# Code borrowed from https://github.com/aeruder/get_win8key
#####################################################
#script to query windows 8.x OEM key from PC firmware
#ACPI -> table MSDM -> raw content -> byte offset 56 to end
#ck, 03-Jan-2014 (christian@korneck.de)
#####################################################
bios_key = None
table = b"MSDM"
if acpi.FindAcpiTable(table) is True:
rawtable = acpi.GetAcpiTable(table)
#http://msdn.microsoft.com/library/windows/hardware/hh673514
#byte offset 36 from beginning \
# = Microsoft 'software licensing data structure' \
# / 36 + 20 bytes offset from beginning = Win Key
bios_key = rawtable[56:len(rawtable)].decode("utf-8")
if bios_key is None:
raise BIOSKeyNotFoundError
# Install Key
cmd = ['cscript', '//nologo', SLMGR, '/ipk', bios_key]
subprocess.run(cmd, check=False)
sleep(5)
# Install Key
cmd = ['cscript', '//nologo', SLMGR, '/ipk', bios_key]
subprocess.run(cmd, check=False)
sleep(5)
# Attempt activation
cmd = ['cscript', '//nologo', SLMGR, '/ato']
subprocess.run(cmd, check=False)
sleep(5)
# Attempt activation
cmd = ['cscript', '//nologo', SLMGR, '/ato']
subprocess.run(cmd, check=False)
sleep(5)
# Check status
if not windows_is_activated():
raise Exception('Activation Failed')
# Check status
if not windows_is_activated():
raise Exception('Activation Failed')
def get_activation_string():
"""Get activation status, returns str."""
act_str = subprocess.run(
['cscript', '//nologo', SLMGR, '/xpr'], check=False,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
act_str = act_str.stdout.decode()
act_str = act_str.splitlines()
act_str = act_str[1].strip()
return act_str
"""Get activation status, returns str."""
act_str = subprocess.run(
['cscript', '//nologo', SLMGR, '/xpr'], check=False,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
act_str = act_str.stdout.decode()
act_str = act_str.splitlines()
act_str = act_str[1].strip()
return act_str
def windows_is_activated():
"""Check if Windows is activated via slmgr.vbs and return bool."""
activation_string = subprocess.run(
['cscript', '//nologo', SLMGR, '/xpr'], check=False,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
activation_string = activation_string.stdout.decode()
"""Check if Windows is activated via slmgr.vbs and return bool."""
activation_string = subprocess.run(
['cscript', '//nologo', SLMGR, '/xpr'], check=False,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
activation_string = activation_string.stdout.decode()
return bool(activation_string and 'permanent' in activation_string)
return bool(activation_string and 'permanent' in activation_string)
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -4,202 +4,216 @@ import ctypes
from functions.disk import *
# Regex
REGEX_BAD_PATH_NAMES = re.compile(
r'([<>:"/\|\?\*]'
r'|^(CON|PRN|AUX|NUL|COM\d*|LPT\d*)$)'
r'|^\s+'
r'|[\s\.]+$',
re.IGNORECASE)
r'([<>:"/\|\?\*]'
r'|^(CON|PRN|AUX|NUL|COM\d*|LPT\d*)$)'
r'|^\s+'
r'|[\s\.]+$',
re.IGNORECASE)
def backup_partition(disk, par):
"""Create a backup image of a partition."""
if par.get('Image Exists', False) or par['Number'] in disk['Bad Partitions']:
raise GenericAbort
"""Create a backup image of a partition."""
if (par.get('Image Exists', False)
or par['Number'] in disk['Bad Partitions']):
raise GenericAbort
cmd = [
global_vars['Tools']['wimlib-imagex'],
'capture',
'{}:\\'.format(par['Letter']),
par['Image Path'],
par['Image Name'], # Image name
par['Image Name'], # Image description
'--compress=none',
]
dest_dir = re.sub(r'(.*)\\.*$', r'\1', par['Image Path'], re.IGNORECASE)
os.makedirs(dest_dir, exist_ok=True)
run_program(cmd)
cmd = [
global_vars['Tools']['wimlib-imagex'],
'capture',
'{}:\\'.format(par['Letter']),
par['Image Path'],
par['Image Name'], # Image name
par['Image Name'], # Image description
'--compress=none',
]
dest_dir = re.sub(r'(.*)\\.*$', r'\1', par['Image Path'], re.IGNORECASE)
os.makedirs(dest_dir, exist_ok=True)
run_program(cmd)
def fix_path(path):
"""Replace invalid filename characters with underscores."""
local_drive = path[1:2] == ':'
new_path = REGEX_BAD_PATH_NAMES.sub('_', path)
if local_drive:
new_path = '{}:{}'.format(new_path[0:1], new_path[2:])
return new_path
"""Replace invalid filename characters with underscores."""
local_drive = path[1:2] == ':'
new_path = REGEX_BAD_PATH_NAMES.sub('_', path)
if local_drive:
new_path = '{}:{}'.format(new_path[0:1], new_path[2:])
return new_path
def get_volume_display_name(mountpoint):
"""Get display name from volume mountpoint and label, returns str."""
name = mountpoint
try:
kernel32 = ctypes.windll.kernel32
vol_name_buffer = ctypes.create_unicode_buffer(1024)
fs_name_buffer = ctypes.create_unicode_buffer(1024)
serial_number = None
max_component_length = None
file_system_flags = None
"""Get display name from volume mountpoint and label, returns str."""
name = mountpoint
try:
kernel32 = ctypes.windll.kernel32
vol_name_buffer = ctypes.create_unicode_buffer(1024)
fs_name_buffer = ctypes.create_unicode_buffer(1024)
serial_number = None
max_component_length = None
file_system_flags = None
vol_info = kernel32.GetVolumeInformationW(
ctypes.c_wchar_p(mountpoint),
vol_name_buffer,
ctypes.sizeof(vol_name_buffer),
serial_number,
max_component_length,
file_system_flags,
fs_name_buffer,
ctypes.sizeof(fs_name_buffer)
)
vol_info = kernel32.GetVolumeInformationW(
ctypes.c_wchar_p(mountpoint),
vol_name_buffer,
ctypes.sizeof(vol_name_buffer),
serial_number,
max_component_length,
file_system_flags,
fs_name_buffer,
ctypes.sizeof(fs_name_buffer)
)
name = '{} "{}"'.format(name, vol_name_buffer.value)
except:
pass
name = '{} "{}"'.format(name, vol_name_buffer.value)
except:
pass
return name
return name
def prep_disk_for_backup(destination, disk, backup_prefix):
"""Gather details about the disk and its partitions.
"""Gather details about the disk and its partitions.
This includes partitions that can't be backed up,
whether backups already exist on the BACKUP_SERVER,
partition names/sizes/used space, etc."""
disk['Clobber Risk'] = []
width = len(str(len(disk['Partitions'])))
This includes partitions that can't be backed up,
whether backups already exist on the BACKUP_SERVER,
partition names/sizes/used space, etc."""
disk['Clobber Risk'] = []
width = len(str(len(disk['Partitions'])))
# Get partition totals
disk['Bad Partitions'] = [par['Number'] for par in disk['Partitions']
if is_bad_partition(par)]
num_valid_partitions = len(disk['Partitions']) - len(disk['Bad Partitions'])
disk['Valid Partitions'] = num_valid_partitions
if disk['Valid Partitions'] <= 0:
print_error('ERROR: No partitions can be backed up for this disk')
raise GenericAbort
# Get partition totals
disk['Bad Partitions'] = [par['Number'] for par in disk['Partitions']
if is_bad_partition(par)]
num_valid_partitions = len(disk['Partitions']) - len(disk['Bad Partitions'])
disk['Valid Partitions'] = num_valid_partitions
if disk['Valid Partitions'] <= 0:
print_error('ERROR: No partitions can be backed up for this disk')
raise GenericAbort
# Prep partitions
for par in disk['Partitions']:
display = '{size} {fs}'.format(
num = par['Number'],
width = width,
size = par['Size'],
fs = par['FileSystem'])
# Prep partitions
for par in disk['Partitions']:
display = '{size} {fs}'.format(
num = par['Number'],
width = width,
size = par['Size'],
fs = par['FileSystem'])
if par['Number'] in disk['Bad Partitions']:
# Set display string using partition description & OS type
display = '* {display}\t\t{q}{name}{q}\t{desc} ({os})'.format(
display = display,
q = '"' if par['Name'] != '' else '',
name = par['Name'],
desc = par['Description'],
os = par['OS'])
else:
# Update info for WIM capturing
par['Image Name'] = par['Name'] if par['Name'] else 'Unknown'
if 'IP' in destination:
par['Image Path'] = r'\\{}\{}\{}'.format(
destination['IP'], destination['Share'], backup_prefix)
else:
par['Image Path'] = r'{}:\{}'.format(
destination['Letter'], backup_prefix)
par['Image Path'] += r'\{}_{}.wim'.format(
par['Number'], par['Image Name'])
par['Image Path'] = fix_path(par['Image Path'])
if par['Number'] in disk['Bad Partitions']:
# Set display string using partition description & OS type
display = '* {display}\t\t{q}{name}{q}\t{desc} ({os})'.format(
display = display,
q = '"' if par['Name'] != '' else '',
name = par['Name'],
desc = par['Description'],
os = par['OS'])
else:
# Update info for WIM capturing
par['Image Name'] = par['Name'] if par['Name'] else 'Unknown'
if 'IP' in destination:
par['Image Path'] = r'\\{}\{}\{}'.format(
destination['IP'], destination['Share'], backup_prefix)
else:
par['Image Path'] = r'{}:\{}'.format(
destination['Letter'], backup_prefix)
par['Image Path'] += r'\{}_{}.wim'.format(
par['Number'], par['Image Name'])
par['Image Path'] = fix_path(par['Image Path'])
# Check for existing backups
par['Image Exists'] = os.path.exists(par['Image Path'])
if par['Image Exists']:
disk['Clobber Risk'].append(par['Number'])
display = '+ {}'.format(display)
else:
display = ' {}'.format(display)
# Check for existing backups
par['Image Exists'] = os.path.exists(par['Image Path'])
if par['Image Exists']:
disk['Clobber Risk'].append(par['Number'])
display = '+ {}'.format(display)
else:
display = ' {}'.format(display)
# Append rest of Display String for valid/clobber partitions
display += ' (Used: {used})\t{q}{name}{q}'.format(
used = par['Used Space'],
q = '"' if par['Name'] != '' else '',
name = par['Name'])
# For all partitions
par['Display String'] = display
# Append rest of Display String for valid/clobber partitions
display += ' (Used: {used})\t{q}{name}{q}'.format(
used = par['Used Space'],
q = '"' if par['Name'] != '' else '',
name = par['Name'])
# For all partitions
par['Display String'] = display
# Set description for bad partitions
warnings = '\n'
if disk['Bad Partitions']:
warnings += '{} * Unsupported filesystem{}\n'.format(
COLORS['YELLOW'], COLORS['CLEAR'])
if disk['Clobber Risk']:
warnings += '{} + Backup exists on {}{}\n'.format(
COLORS['BLUE'], destination['Name'], COLORS['CLEAR'])
if disk['Bad Partitions'] or disk['Clobber Risk']:
warnings += '\n{}Marked partition(s) will NOT be backed up.{}\n'.format(
COLORS['YELLOW'], COLORS['CLEAR'])
disk['Backup Warnings'] = warnings
# Set description for bad partitions
warnings = '\n'
if disk['Bad Partitions']:
warnings += '{} * Unsupported filesystem{}\n'.format(
COLORS['YELLOW'], COLORS['CLEAR'])
if disk['Clobber Risk']:
warnings += '{} + Backup exists on {}{}\n'.format(
COLORS['BLUE'], destination['Name'], COLORS['CLEAR'])
if disk['Bad Partitions'] or disk['Clobber Risk']:
warnings += '\n{}Marked partition(s) will NOT be backed up.{}\n'.format(
COLORS['YELLOW'], COLORS['CLEAR'])
disk['Backup Warnings'] = warnings
def select_backup_destination(auto_select=True):
"""Select a backup destination from a menu, returns server dict."""
destinations = [s for s in BACKUP_SERVERS if s['Mounted']]
actions = [
{'Name': 'Main Menu', 'Letter': 'M'},
]
"""Select a backup destination from a menu, returns server dict."""
destinations = [s for s in BACKUP_SERVERS if s['Mounted']]
actions = [
{'Name': 'Main Menu', 'Letter': 'M'},
]
# Add local disks
for d in psutil.disk_partitions():
if re.search(r'^{}'.format(global_vars['Env']['SYSTEMDRIVE']), d.mountpoint, re.IGNORECASE):
# Skip current OS drive
pass
elif 'fixed' in d.opts:
# Skip DVD, etc
destinations.append({
'Name': 'Local Disk - {}'.format(
get_volume_display_name(d.mountpoint)),
'Letter': re.sub(r'^(\w):\\.*$', r'\1', d.mountpoint),
})
# Add local disks
for d in psutil.disk_partitions():
if re.search(
r'^{}'.format(global_vars['Env']['SYSTEMDRIVE']),
d.mountpoint,
re.IGNORECASE):
# Skip current OS drive
pass
elif 'fixed' in d.opts:
# Skip DVD, etc
destinations.append({
'Name': 'Local Disk - {}'.format(
get_volume_display_name(d.mountpoint)),
'Letter': re.sub(r'^(\w):\\.*$', r'\1', d.mountpoint),
})
# Size check
for dest in destinations:
if 'IP' in dest:
dest['Usage'] = shutil.disk_usage(r'\\{IP}\{Share}'.format(**dest))
else:
dest['Usage'] = shutil.disk_usage('{}:\\'.format(dest['Letter']))
dest['Free Space'] = human_readable_size(dest['Usage'].free)
dest['Display Name'] = '{Name} ({Free Space} available)'.format(**dest)
# Bail
if not destinations:
print_warning('No backup destinations found.')
raise GenericAbort
# Skip menu?
if len(destinations) == 1 and auto_select:
return destinations[0]
selection = menu_select(
title = 'Where are we backing up to?',
main_entries = destinations,
action_entries = actions)
if selection == 'M':
raise GenericAbort
# Size check
for dest in destinations:
if 'IP' in dest:
dest['Usage'] = shutil.disk_usage(r'\\{IP}\{Share}'.format(**dest))
else:
return destinations[int(selection)-1]
dest['Usage'] = shutil.disk_usage('{}:\\'.format(dest['Letter']))
dest['Free Space'] = human_readable_size(dest['Usage'].free)
dest['Display Name'] = '{Name} ({Free Space} available)'.format(**dest)
# Bail
if not destinations:
print_warning('No backup destinations found.')
raise GenericAbort
# Skip menu?
if len(destinations) == 1 and auto_select:
return destinations[0]
selection = menu_select(
title = 'Where are we backing up to?',
main_entries = destinations,
action_entries = actions)
if selection == 'M':
raise GenericAbort
else:
return destinations[int(selection)-1]
def verify_wim_backup(partition):
"""Verify WIM integrity."""
if not os.path.exists(partition['Image Path']):
raise PathNotFoundError
cmd = [
global_vars['Tools']['wimlib-imagex'],
'verify',
partition['Image Path'],
'--nocheck',
]
run_program(cmd)
"""Verify WIM integrity."""
if not os.path.exists(partition['Image Path']):
raise PathNotFoundError
cmd = [
global_vars['Tools']['wimlib-imagex'],
'verify',
partition['Image Path'],
'--nocheck',
]
run_program(cmd)
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -1,48 +1,32 @@
# Wizard Kit: Functions - Browsers
from functions.common import *
from operator import itemgetter
# Define other_results for later try_and_print
browser_data = {}
other_results = {
'Error': {
'MultipleInstallationsError': 'Multiple installations detected',
},
'Warning': {
'NotInstalledError': 'Not installed',
'NoProfilesError': 'No profiles found',
}
'Error': {
'MultipleInstallationsError': 'Multiple installations detected',
},
'Warning': {
'NotInstalledError': 'Not installed',
'NoProfilesError': 'No profiles found',
}
}
# Regex
REGEX_BACKUP = re.compile(
r'\.\w*bak.*',
re.IGNORECASE)
REGEX_CHROMIUM_PROFILE = re.compile(
r'^(Default|Profile)',
re.IGNORECASE)
REGEX_CHROMIUM_ITEMS = re.compile(
r'^(Bookmarks|Cookies|Favicons|Google Profile'
r'|History|Login Data|Top Sites|TransportSecurity'
r'|Visited Links|Web Data)',
re.IGNORECASE)
REGEX_MOZILLA = re.compile(
r'^(bookmarkbackups|(cookies|formhistory|places).sqlite'
r'|key3.db|logins.json|persdict.dat)$',
re.IGNORECASE)
# STATIC VARIABLES
DEFAULT_HOMEPAGE = 'https://www.google.com/'
IE_GALLERY = 'https://www.microsoft.com/en-us/iegallery'
MOZILLA_PREFS = {
'browser.search.defaultenginename': '"Google"',
'browser.search.defaultenginename.US': '"Google"',
'browser.search.geoSpecificDefaults': 'false',
'browser.startup.homepage': '"{}"'.format(DEFAULT_HOMEPAGE),
'extensions.ui.lastCategory': '"addons://list/extension"',
}
'browser.search.defaultenginename': '"Google"',
'browser.search.defaultenginename.US': '"Google"',
'browser.search.geoSpecificDefaults': 'false',
'browser.startup.homepage': '"{}"'.format(DEFAULT_HOMEPAGE),
'extensions.ui.lastCategory': '"addons://list/extension"',
}
UBO_CHROME = 'https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm?hl=en'
UBO_CHROME_REG = r'Software\Wow6432Node\Google\Chrome\Extensions\cjpalhdlnbpafiamejdnhcphjbkeiagm'
UBO_EXTRA_CHROME = 'https://chrome.google.com/webstore/detail/ublock-origin-extra/pgdnlhfefecpicbbihgmbmffkjpaplco?hl=en'
@ -53,456 +37,505 @@ UBO_MOZILLA_REG = r'Software\Mozilla\Firefox\Extensions'
UBO_MOZILLA_REG_NAME = 'uBlock0@raymondhill.net'
UBO_OPERA = 'https://addons.opera.com/en/extensions/details/ublock/?display=en'
SUPPORTED_BROWSERS = {
'Internet Explorer': {
'base': 'ie',
'exe_name': 'iexplore.exe',
'rel_install_path': 'Internet Explorer',
'user_data_path': r'{USERPROFILE}\Favorites',
},
'Google Chrome': {
'base': 'chromium',
'exe_name': 'chrome.exe',
'rel_install_path': r'Google\Chrome\Application',
'user_data_path': r'{LOCALAPPDATA}\Google\Chrome\User Data',
},
'Google Chrome Canary': {
'base': 'chromium',
'exe_name': 'chrome.exe',
'rel_install_path': r'Google\Chrome SxS\Application',
'user_data_path': r'{LOCALAPPDATA}\Google\Chrome SxS\User Data',
},
'Mozilla Firefox': {
'base': 'mozilla',
'exe_name': 'firefox.exe',
'rel_install_path': 'Mozilla Firefox',
'user_data_path': r'{APPDATA}\Mozilla\Firefox\Profiles',
},
'Mozilla Firefox Dev': {
'base': 'mozilla',
'exe_name': 'firefox.exe',
'rel_install_path': 'Firefox Developer Edition',
'user_data_path': r'{APPDATA}\Mozilla\Firefox\Profiles',
},
'Opera': {
'base': 'chromium',
'exe_name': 'launcher.exe',
'rel_install_path': 'Opera',
'user_data_path': r'{APPDATA}\Opera Software\Opera Stable',
},
'Opera Beta': {
'base': 'chromium',
'exe_name': 'launcher.exe',
'rel_install_path': 'Opera beta',
'user_data_path': r'{APPDATA}\Opera Software\Opera Next',
},
'Opera Dev': {
'base': 'chromium',
'exe_name': 'launcher.exe',
'rel_install_path': 'Opera developer',
'user_data_path': r'{APPDATA}\Opera Software\Opera Developer',
},
}
'Internet Explorer': {
'base': 'ie',
'exe_name': 'iexplore.exe',
'rel_install_path': 'Internet Explorer',
'user_data_path': r'{USERPROFILE}\Favorites',
},
'Google Chrome': {
'base': 'chromium',
'exe_name': 'chrome.exe',
'rel_install_path': r'Google\Chrome\Application',
'user_data_path': r'{LOCALAPPDATA}\Google\Chrome\User Data',
},
'Google Chrome Canary': {
'base': 'chromium',
'exe_name': 'chrome.exe',
'rel_install_path': r'Google\Chrome SxS\Application',
'user_data_path': r'{LOCALAPPDATA}\Google\Chrome SxS\User Data',
},
'Mozilla Firefox': {
'base': 'mozilla',
'exe_name': 'firefox.exe',
'rel_install_path': 'Mozilla Firefox',
'user_data_path': r'{APPDATA}\Mozilla\Firefox\Profiles',
},
'Mozilla Firefox Dev': {
'base': 'mozilla',
'exe_name': 'firefox.exe',
'rel_install_path': 'Firefox Developer Edition',
'user_data_path': r'{APPDATA}\Mozilla\Firefox\Profiles',
},
'Opera': {
'base': 'chromium',
'exe_name': 'launcher.exe',
'rel_install_path': 'Opera',
'user_data_path': r'{APPDATA}\Opera Software\Opera Stable',
},
'Opera Beta': {
'base': 'chromium',
'exe_name': 'launcher.exe',
'rel_install_path': 'Opera beta',
'user_data_path': r'{APPDATA}\Opera Software\Opera Next',
},
'Opera Dev': {
'base': 'chromium',
'exe_name': 'launcher.exe',
'rel_install_path': 'Opera developer',
'user_data_path': r'{APPDATA}\Opera Software\Opera Developer',
},
}
# Regex
REGEX_BACKUP = re.compile(
r'\.\w*bak.*',
re.IGNORECASE)
REGEX_CHROMIUM_PROFILE = re.compile(
r'^(Default|Profile)',
re.IGNORECASE)
REGEX_CHROMIUM_ITEMS = re.compile(
r'^(Bookmarks|Cookies|Favicons|Google Profile'
r'|History|Login Data|Top Sites|TransportSecurity'
r'|Visited Links|Web Data)',
re.IGNORECASE)
REGEX_MOZILLA = re.compile(
r'^(bookmarkbackups|(cookies|formhistory|places).sqlite'
r'|key3.db|logins.json|persdict.dat)$',
re.IGNORECASE)
def archive_all_users():
"""Create backups for all browsers for all users."""
users_root = r'{}\Users'.format(global_vars['Env']['SYSTEMDRIVE'])
user_envs = []
"""Create backups for all browsers for all users."""
users_root = r'{}\Users'.format(global_vars['Env']['SYSTEMDRIVE'])
user_envs = []
# Build list of valid users
for user_name in os.listdir(users_root):
valid_user = True
if user_name in ('Default', 'Default User'):
# Skip default users
continue
user_path = os.path.join(users_root, user_name)
appdata_local = os.path.join(user_path, r'AppData\Local')
appdata_roaming = os.path.join(user_path, r'AppData\Roaming')
valid_user &= os.path.exists(appdata_local)
valid_user &= os.path.exists(appdata_roaming)
if valid_user:
user_envs.append({
'USERNAME': user_name,
'USERPROFILE': user_path,
'APPDATA': appdata_roaming,
'LOCALAPPDATA': appdata_local})
# Build list of valid users
for user_name in os.listdir(users_root):
valid_user = True
if user_name in ('Default', 'Default User'):
# Skip default users
continue
user_path = os.path.join(users_root, user_name)
appdata_local = os.path.join(user_path, r'AppData\Local')
appdata_roaming = os.path.join(user_path, r'AppData\Roaming')
valid_user &= os.path.exists(appdata_local)
valid_user &= os.path.exists(appdata_roaming)
if valid_user:
user_envs.append({
'USERNAME': user_name,
'USERPROFILE': user_path,
'APPDATA': appdata_roaming,
'LOCALAPPDATA': appdata_local})
# Backup browsers for all valid users
print_info('Backing up browsers')
for fake_env in sorted(user_envs, key=itemgetter('USERPROFILE')):
print_standard(' {}'.format(fake_env['USERNAME']))
for b_k, b_v in sorted(SUPPORTED_BROWSERS.items()):
if b_k == 'Mozilla Firefox Dev':
continue
source_path = b_v['user_data_path'].format(**fake_env)
if not os.path.exists(source_path):
continue
source_items = source_path + '*'
archive_path = r'{BackupDir}\Browsers ({USERNAME})\{Date}'.format(
**global_vars, **fake_env)
os.makedirs(archive_path, exist_ok=True)
archive_path += r'\{}.7z'.format(b_k)
cmd = [
global_vars['Tools']['SevenZip'],
'a', '-aoa', '-bso0', '-bse0', '-mx=1',
archive_path, source_items]
try_and_print(message='{}...'.format(b_k),
function=run_program, cmd=cmd)
print_standard(' ')
def archive_browser(name):
"""Create backup of Browser saved in the BackupDir."""
source = '{}*'.format(browser_data[name]['user_data_path'])
dest = r'{BackupDir}\Browsers ({USERNAME})\{Date}'.format(
**global_vars, **global_vars['Env'])
archive = r'{}\{}.7z'.format(dest, name)
os.makedirs(dest, exist_ok=True)
cmd = [
# Backup browsers for all valid users
print_info('Backing up browsers')
for fake_env in sorted(user_envs, key=itemgetter('USERPROFILE')):
print_standard(' {}'.format(fake_env['USERNAME']))
for b_k, b_v in sorted(SUPPORTED_BROWSERS.items()):
if b_k == 'Mozilla Firefox Dev':
continue
source_path = b_v['user_data_path'].format(**fake_env)
if not os.path.exists(source_path):
continue
source_items = source_path + '*'
archive_path = r'{BackupDir}\Browsers ({USERNAME})\{Date}'.format(
**global_vars, **fake_env)
os.makedirs(archive_path, exist_ok=True)
archive_path += r'\{}.7z'.format(b_k)
cmd = [
global_vars['Tools']['SevenZip'],
'a', '-aoa', '-bso0', '-bse0', '-mx=1',
'-mhe=on', '-p{}'.format(ARCHIVE_PASSWORD),
archive, source]
run_program(cmd)
archive_path, source_items]
try_and_print(message='{}...'.format(b_k),
function=run_program, cmd=cmd)
print_standard(' ')
def archive_browser(name):
"""Create backup of Browser saved in the BackupDir."""
source = '{}*'.format(browser_data[name]['user_data_path'])
dest = r'{BackupDir}\Browsers ({USERNAME})\{Date}'.format(
**global_vars, **global_vars['Env'])
archive = r'{}\{}.7z'.format(dest, name)
os.makedirs(dest, exist_ok=True)
cmd = [
global_vars['Tools']['SevenZip'],
'a', '-aoa', '-bso0', '-bse0', '-mx=1',
'-mhe=on', '-p{}'.format(ARCHIVE_PASSWORD),
archive, source]
run_program(cmd)
def backup_browsers():
"""Create backup of all detected browser profiles."""
for name in [k for k, v in sorted(browser_data.items()) if v['profiles']]:
try_and_print(message='{}...'.format(name),
function=archive_browser, name=name)
"""Create backup of all detected browser profiles."""
for name in [k for k, v in sorted(browser_data.items()) if v['profiles']]:
try_and_print(message='{}...'.format(name),
function=archive_browser, name=name)
def clean_chromium_profile(profile):
"""Renames profile, creates a new folder, and copies the user data to it."""
if profile is None:
raise Exception
backup_path = '{path}_{Date}.bak'.format(
path=profile['path'], **global_vars)
backup_path = non_clobber_rename(backup_path)
shutil.move(profile['path'], backup_path)
os.makedirs(profile['path'], exist_ok=True)
"""Recreate profile with only the essential user data.
This is done by renaming the existing profile, creating a new folder
with the original name, then copying the essential files from the
backup folder. This way the original state is preserved in case
something goes wrong.
"""
if profile is None:
raise Exception
backup_path = '{path}_{Date}.bak'.format(
path=profile['path'], **global_vars)
backup_path = non_clobber_rename(backup_path)
shutil.move(profile['path'], backup_path)
os.makedirs(profile['path'], exist_ok=True)
# Restore essential files from backup_path
for entry in os.scandir(backup_path):
if REGEX_CHROMIUM_ITEMS.search(entry.name):
shutil.copy(entry.path, r'{}\{}'.format(
profile['path'], entry.name))
# Restore essential files from backup_path
for entry in os.scandir(backup_path):
if REGEX_CHROMIUM_ITEMS.search(entry.name):
shutil.copy(entry.path, r'{}\{}'.format(
profile['path'], entry.name))
def clean_internet_explorer(**kwargs):
"""Uses the built-in function to reset IE and sets the homepage.
"""Uses the built-in function to reset IE and sets the homepage.
NOTE: kwargs set but unused as a workaround."""
kill_process('iexplore.exe')
run_program(['rundll32.exe', 'inetcpl.cpl,ResetIEtoDefaults'], check=False)
key = r'Software\Microsoft\Internet Explorer\Main'
NOTE: kwargs set but unused as a workaround."""
kill_process('iexplore.exe')
run_program(['rundll32.exe', 'inetcpl.cpl,ResetIEtoDefaults'], check=False)
key = r'Software\Microsoft\Internet Explorer\Main'
# Set homepage
with winreg.OpenKey(HKCU, key, access=winreg.KEY_WRITE) as _key:
winreg.SetValueEx(_key, 'Start Page', 0,
winreg.REG_SZ, DEFAULT_HOMEPAGE)
try:
winreg.DeleteValue(_key, 'Secondary Start Pages')
except FileNotFoundError:
pass
# Set homepage
with winreg.OpenKey(HKCU, key, access=winreg.KEY_WRITE) as _key:
winreg.SetValueEx(_key, 'Start Page', 0,
winreg.REG_SZ, DEFAULT_HOMEPAGE)
try:
winreg.DeleteValue(_key, 'Secondary Start Pages')
except FileNotFoundError:
pass
def clean_mozilla_profile(profile):
"""Renames profile, creates a new folder, and copies the user data to it."""
if profile is None:
raise Exception
backup_path = '{path}_{Date}.bak'.format(
path=profile['path'], **global_vars)
backup_path = non_clobber_rename(backup_path)
shutil.move(profile['path'], backup_path)
homepages = []
os.makedirs(profile['path'], exist_ok=True)
"""Recreate profile with only the essential user data.
# Restore essential files from backup_path
for entry in os.scandir(backup_path):
if REGEX_MOZILLA.search(entry.name):
if entry.is_dir():
shutil.copytree(entry.path, r'{}\{}'.format(
profile['path'], entry.name))
else:
shutil.copy(entry.path, r'{}\{}'.format(
profile['path'], entry.name))
This is done by renaming the existing profile, creating a new folder
with the original name, then copying the essential files from the
backup folder. This way the original state is preserved in case
something goes wrong.
"""
if profile is None:
raise Exception
backup_path = '{path}_{Date}.bak'.format(
path=profile['path'], **global_vars)
backup_path = non_clobber_rename(backup_path)
shutil.move(profile['path'], backup_path)
homepages = []
os.makedirs(profile['path'], exist_ok=True)
# Restore essential files from backup_path
for entry in os.scandir(backup_path):
if REGEX_MOZILLA.search(entry.name):
if entry.is_dir():
shutil.copytree(entry.path, r'{}\{}'.format(
profile['path'], entry.name))
else:
shutil.copy(entry.path, r'{}\{}'.format(
profile['path'], entry.name))
# Set profile defaults
with open(r'{path}\prefs.js'.format(**profile), 'a', encoding='ascii') as f:
for k, v in MOZILLA_PREFS.items():
f.write('user_pref("{}", {});\n'.format(k, v))
# Set profile defaults
with open(r'{path}\prefs.js'.format(**profile), 'a', encoding='ascii') as f:
for k, v in MOZILLA_PREFS.items():
f.write('user_pref("{}", {});\n'.format(k, v))
def get_browser_details(name):
"""Get installation status and profile details for all supported browsers."""
browser = SUPPORTED_BROWSERS[name].copy()
"""Get installation and profile details for all supported browsers."""
browser = SUPPORTED_BROWSERS[name].copy()
# Update user_data_path
browser['user_data_path'] = browser['user_data_path'].format(
**global_vars['Env'])
# Update user_data_path
browser['user_data_path'] = browser['user_data_path'].format(
**global_vars['Env'])
# Find executable (if multiple files are found, the last one is used)
exe_path = None
num_installs = 0
for install_path in ['LOCALAPPDATA', 'PROGRAMFILES(X86)', 'PROGRAMFILES']:
test_path = r'{install_path}\{rel_install_path}\{exe_name}'.format(
install_path = global_vars['Env'].get(install_path, ''),
**browser)
if os.path.exists(test_path):
num_installs += 1
exe_path = test_path
# Find executable (if multiple files are found, the last one is used)
exe_path = None
num_installs = 0
for install_path in ['LOCALAPPDATA', 'PROGRAMFILES(X86)', 'PROGRAMFILES']:
test_path = r'{install_path}\{rel_install_path}\{exe_name}'.format(
install_path = global_vars['Env'].get(install_path, ''),
**browser)
if os.path.exists(test_path):
num_installs += 1
exe_path = test_path
# Find profile(s)
profiles = []
if browser['base'] == 'ie':
profiles.append({'name': 'Default', 'path': None})
elif 'Google Chrome' in name:
profiles.extend(
get_chromium_profiles(
search_path=browser['user_data_path']))
elif browser['base'] == 'mozilla':
dev = 'Dev' in name
profiles.extend(
get_mozilla_profiles(
search_path=browser['user_data_path'], dev=dev))
if exe_path and not dev and len(profiles) == 0:
# e.g. If Firefox is installed but no profiles were found.
## Rename profiles.ini and create a new default profile
profiles_ini_path = browser['user_data_path'].replace(
'Profiles', 'profiles.ini')
if os.path.exists(profiles_ini_path):
backup_path = '{path}_{Date}.bak'.format(
path=profiles_ini_path, **global_vars)
backup_path = non_clobber_rename(backup_path)
shutil.move(profiles_ini_path, backup_path)
run_program([exe_path, '-createprofile', 'default'], check=False)
profiles.extend(
get_mozilla_profiles(
search_path=browser['user_data_path'], dev=dev))
# Find profile(s)
profiles = []
if browser['base'] == 'ie':
profiles.append({'name': 'Default', 'path': None})
elif 'Google Chrome' in name:
profiles.extend(
get_chromium_profiles(
search_path=browser['user_data_path']))
elif browser['base'] == 'mozilla':
dev = 'Dev' in name
profiles.extend(
get_mozilla_profiles(
search_path=browser['user_data_path'], dev=dev))
if exe_path and not dev and len(profiles) == 0:
# e.g. If Firefox is installed but no profiles were found.
## Rename profiles.ini and create a new default profile
profiles_ini_path = browser['user_data_path'].replace(
'Profiles', 'profiles.ini')
if os.path.exists(profiles_ini_path):
backup_path = '{path}_{Date}.bak'.format(
path=profiles_ini_path, **global_vars)
backup_path = non_clobber_rename(backup_path)
shutil.move(profiles_ini_path, backup_path)
run_program([exe_path, '-createprofile', 'default'], check=False)
profiles.extend(
get_mozilla_profiles(
search_path=browser['user_data_path'], dev=dev))
elif 'Opera' in name:
if os.path.exists(browser['user_data_path']):
profiles.append(
{'name': 'Default', 'path': browser['user_data_path']})
elif 'Opera' in name:
if os.path.exists(browser['user_data_path']):
profiles.append(
{'name': 'Default', 'path': browser['user_data_path']})
# Get homepages
if browser['base'] == 'ie':
# IE is set to only have one profile above
profiles[0]['homepages'] = get_ie_homepages()
elif browser['base'] == 'mozilla':
for profile in profiles:
prefs_path = r'{path}\prefs.js'.format(**profile)
profile['homepages'] = get_mozilla_homepages(prefs_path=prefs_path)
# Get homepages
if browser['base'] == 'ie':
# IE is set to only have one profile above
profiles[0]['homepages'] = get_ie_homepages()
elif browser['base'] == 'mozilla':
for profile in profiles:
prefs_path = r'{path}\prefs.js'.format(**profile)
profile['homepages'] = get_mozilla_homepages(prefs_path=prefs_path)
# Add to browser_data
browser_data[name] = browser
browser_data[name].update({
'exe_path': exe_path,
'profiles': profiles,
})
# Add to browser_data
browser_data[name] = browser
browser_data[name].update({
'exe_path': exe_path,
'profiles': profiles,
})
# Raise installation warnings (if any)
if num_installs == 0:
raise NotInstalledError
elif num_installs > 1 and browser['base'] != 'ie':
raise MultipleInstallationsError
# Raise installation warnings (if any)
if num_installs == 0:
raise NotInstalledError
elif num_installs > 1 and browser['base'] != 'ie':
raise MultipleInstallationsError
def get_chromium_profiles(search_path):
"""Find any chromium-style profiles and return as a list of dicts."""
profiles = []
try:
for entry in os.scandir(search_path):
if entry.is_dir() and REGEX_CHROMIUM_PROFILE.search(entry.name):
profiles.append(entry)
REGEX_PROFILE_BACKUP = r'\.\w+bak.*'
profiles = [p for p in profiles if not REGEX_BACKUP.search(p.name)]
# Convert os.DirEntries to dicts
profiles = [{'name': p.name, 'path': p.path} for p in profiles]
except Exception:
pass
"""Find any chromium-style profiles and return as a list of dicts."""
profiles = []
try:
for entry in os.scandir(search_path):
if entry.is_dir() and REGEX_CHROMIUM_PROFILE.search(entry.name):
profiles.append(entry)
REGEX_PROFILE_BACKUP = r'\.\w+bak.*'
profiles = [p for p in profiles if not REGEX_BACKUP.search(p.name)]
# Convert os.DirEntries to dicts
profiles = [{'name': p.name, 'path': p.path} for p in profiles]
except Exception:
pass
return profiles
return profiles
def get_ie_homepages():
"""Read homepages from the registry and return as a list."""
homepages = []
main_page = ''
extra_pages = []
key = r'Software\Microsoft\Internet Explorer\Main'
with winreg.OpenKey(HKCU, key) as _key:
try:
main_page = winreg.QueryValueEx(_key, 'Start Page')[0]
except FileNotFoundError:
pass
try:
extra_pages = winreg.QueryValueEx(_key, 'Secondary Start Pages')[0]
except FileNotFoundError:
pass
if main_page != '':
homepages.append(main_page)
if len(extra_pages) > 0:
homepages.extend(extra_pages)
"""Read homepages from the registry and return as a list."""
homepages = []
main_page = ''
extra_pages = []
key = r'Software\Microsoft\Internet Explorer\Main'
with winreg.OpenKey(HKCU, key) as _key:
try:
main_page = winreg.QueryValueEx(_key, 'Start Page')[0]
except FileNotFoundError:
pass
try:
extra_pages = winreg.QueryValueEx(_key, 'Secondary Start Pages')[0]
except FileNotFoundError:
pass
if main_page != '':
homepages.append(main_page)
if len(extra_pages) > 0:
homepages.extend(extra_pages)
# Remove all curly braces
homepages = [h.replace('{', '').replace('}', '') for h in homepages]
return homepages
# Remove all curly braces
homepages = [h.replace('{', '').replace('}', '') for h in homepages]
return homepages
def get_mozilla_homepages(prefs_path):
"""Read homepages from prefs.js and return as a list."""
homepages = []
try:
with open(prefs_path, 'r') as f:
search = re.search(
r'browser\.startup\.homepage", "([^"]*)"',
f.read(), re.IGNORECASE)
if search:
homepages = search.group(1).split('|')
except Exception:
pass
"""Read homepages from prefs.js and return as a list."""
homepages = []
try:
with open(prefs_path, 'r') as f:
search = re.search(
r'browser\.startup\.homepage", "([^"]*)"',
f.read(), re.IGNORECASE)
if search:
homepages = search.group(1).split('|')
except Exception:
pass
return homepages
return homepages
def get_mozilla_profiles(search_path, dev=False):
"""Find any mozilla-style profiles and return as a list of dicts."""
profiles = []
try:
for entry in os.scandir(search_path):
if entry.is_dir():
if 'dev-edition' in entry.name:
# NOTE: Not always present which can lead
# to Dev profiles being marked as non-Dev
## NOTE 2: It is possible that a non-Dev profile
## to be created with 'dev-edition' in the name.
## (It wouldn't make sense, but possible)
if dev:
profiles.append(entry)
elif not dev:
profiles.append(entry)
profiles = [p for p in profiles if not REGEX_BACKUP.search(p.name)]
# Convert os.DirEntries to dicts
profiles = [{'name': p.name, 'path': p.path} for p in profiles]
except Exception:
pass
"""Find any mozilla-style profiles and return as a list of dicts."""
profiles = []
try:
for entry in os.scandir(search_path):
if entry.is_dir():
if 'dev-edition' in entry.name:
# NOTE: Not always present which can lead
# to Dev profiles being marked as non-Dev
## NOTE 2: It is possible that a non-Dev profile
## to be created with 'dev-edition' in the name.
## (It wouldn't make sense, but possible)
if dev:
profiles.append(entry)
elif not dev:
profiles.append(entry)
profiles = [p for p in profiles if not REGEX_BACKUP.search(p.name)]
# Convert os.DirEntries to dicts
profiles = [{'name': p.name, 'path': p.path} for p in profiles]
except Exception:
pass
return profiles
return profiles
def install_adblock(indent=8, width=32, just_firefox=False):
"""Install adblock for all supported browsers."""
for browser in sorted(browser_data):
if just_firefox and browser_data[browser]['base'] != 'mozilla':
continue
exe_path = browser_data[browser].get('exe_path', None)
function=run_program
if not exe_path:
if browser_data[browser]['profiles']:
print_standard(
'{indent}{browser:<{width}}'.format(
indent=' '*indent, width=width, browser=browser+'...'),
end='', flush=True)
print_warning('Profile(s) detected but browser not installed',
timestamp=False)
else:
# Only warn if profile(s) are detected.
pass
"""Install adblock for all supported browsers."""
for browser in sorted(browser_data):
if just_firefox and browser_data[browser]['base'] != 'mozilla':
continue
exe_path = browser_data[browser].get('exe_path', None)
function=run_program
if not exe_path:
if browser_data[browser]['profiles']:
print_standard(
'{indent}{browser:<{width}}'.format(
indent=' '*indent, width=width, browser=browser+'...'),
end='', flush=True)
print_warning('Profile(s) detected but browser not installed',
timestamp=False)
else:
# Only warn if profile(s) are detected.
pass
else:
# Set urls to open
urls = []
if browser_data[browser]['base'] == 'chromium':
if browser == 'Google Chrome':
# Check for system exensions
try:
winreg.QueryValue(HKLM, UBO_CHROME_REG)
except FileNotFoundError:
urls.append(UBO_CHROME)
try:
winreg.QueryValue(HKLM, UBO_EXTRA_CHROME_REG)
except FileNotFoundError:
urls.append(UBO_EXTRA_CHROME)
if len(urls) == 0:
urls = ['chrome://extensions']
elif 'Opera' in browser:
urls.append(UBO_OPERA)
else:
# Set urls to open
urls = []
if browser_data[browser]['base'] == 'chromium':
if browser == 'Google Chrome':
# Check for system exensions
try:
winreg.QueryValue(HKLM, UBO_CHROME_REG)
except FileNotFoundError:
urls.append(UBO_CHROME)
try:
winreg.QueryValue(HKLM, UBO_EXTRA_CHROME_REG)
except FileNotFoundError:
urls.append(UBO_EXTRA_CHROME)
urls.append(UBO_CHROME)
urls.append(UBO_EXTRA_CHROME)
if len(urls) == 0:
urls = ['chrome://extensions']
elif 'Opera' in browser:
urls.append(UBO_OPERA)
else:
urls.append(UBO_CHROME)
urls.append(UBO_EXTRA_CHROME)
elif browser_data[browser]['base'] == 'mozilla':
# Check for system extensions
try:
with winreg.OpenKey(HKLM, UBO_MOZILLA_REG) as key:
winreg.QueryValueEx(key, UBO_MOZILLA_REG_NAME)
except FileNotFoundError:
urls = [UBO_MOZILLA]
else:
if os.path.exists(UBO_MOZZILA_PATH):
urls = ['about:addons']
else:
urls = [UBO_MOZILLA]
elif browser_data[browser]['base'] == 'mozilla':
# Check for system extensions
try:
with winreg.OpenKey(HKLM, UBO_MOZILLA_REG) as key:
winreg.QueryValueEx(key, UBO_MOZILLA_REG_NAME)
except FileNotFoundError:
urls = [UBO_MOZILLA]
else:
if os.path.exists(UBO_MOZZILA_PATH):
urls = ['about:addons']
else:
urls = [UBO_MOZILLA]
elif browser_data[browser]['base'] == 'ie':
urls.append(IE_GALLERY)
function=popen_program
elif browser_data[browser]['base'] == 'ie':
urls.append(IE_GALLERY)
function=popen_program
# By using check=False we're skipping any return codes so
# it should only fail if the program can't be run
# (or can't be found).
# In other words, this isn't tracking the addon/extension's
# installation status.
try_and_print(message='{}...'.format(browser),
indent=indent, width=width,
cs='Done', function=function,
cmd=[exe_path, *urls], check=False)
# By using check=False we're skipping any return codes so
# it should only fail if the program can't be run
# (or can't be found).
# In other words, this isn't tracking the addon/extension's
# installation status.
try_and_print(message='{}...'.format(browser),
indent=indent, width=width,
cs='Done', function=function,
cmd=[exe_path, *urls], check=False)
def list_homepages(indent=8, width=32):
"""List current homepages for reference."""
"""List current homepages for reference."""
browser_list = [k for k, v in sorted(browser_data.items()) if v['exe_path']]
for browser in browser_list:
# Skip Chromium-based browsers
if browser_data[browser]['base'] == 'chromium':
print_info(
'{indent}{browser:<{width}}'.format(
indent=' '*indent, width=width, browser=browser+'...'),
end='', flush=True)
print_warning('Not implemented', timestamp=False)
continue
for browser in [k for k, v in sorted(browser_data.items()) if v['exe_path']]:
# Skip Chromium-based browsers
if browser_data[browser]['base'] == 'chromium':
print_info(
'{indent}{browser:<{width}}'.format(
indent=' '*indent, width=width, browser=browser+'...'),
end='', flush=True)
print_warning('Not implemented', timestamp=False)
continue
# All other browsers
print_info('{indent}{browser:<{width}}'.format(
indent=' '*indent, width=width, browser=browser+'...'))
for profile in browser_data[browser].get('profiles', []):
name = profile.get('name', '?')
homepages = profile.get('homepages', [])
if len(homepages) == 0:
print_standard(
'{indent}{name:<{width}}'.format(
indent=' '*indent, width=width, name=name),
end='', flush=True)
print_warning('None found', timestamp=False)
else:
for page in homepages:
print_standard('{indent}{name:<{width}}{page}'.format(
indent=' '*indent, width=width, name=name, page=page))
# All other browsers
print_info('{indent}{browser:<{width}}'.format(
indent=' '*indent, width=width, browser=browser+'...'))
for profile in browser_data[browser].get('profiles', []):
name = profile.get('name', '?')
homepages = profile.get('homepages', [])
if len(homepages) == 0:
print_standard(
'{indent}{name:<{width}}'.format(
indent=' '*indent, width=width, name=name),
end='', flush=True)
print_warning('None found', timestamp=False)
else:
for page in homepages:
print_standard('{indent}{name:<{width}}{page}'.format(
indent=' '*indent, width=width, name=name, page=page))
def reset_browsers(indent=8, width=32):
"""Reset all detected browsers to safe defaults."""
for browser in [k for k, v in sorted(browser_data.items()) if v['profiles']]:
print_info('{indent}{name}'.format(indent=' '*indent, name=browser))
for profile in browser_data[browser]['profiles']:
if browser_data[browser]['base'] == 'chromium':
function = clean_chromium_profile
elif browser_data[browser]['base'] == 'ie':
function = clean_internet_explorer
elif browser_data[browser]['base'] == 'mozilla':
function = clean_mozilla_profile
try_and_print(
message='{}...'.format(profile['name']),
indent=indent, width=width, function=function,
other_results=other_results, profile=profile)
"""Reset all detected browsers to safe defaults."""
browser_list = [k for k, v in sorted(browser_data.items()) if v['profiles']]
for browser in browser_list:
print_info('{indent}{name}'.format(indent=' '*indent, name=browser))
for profile in browser_data[browser]['profiles']:
if browser_data[browser]['base'] == 'chromium':
function = clean_chromium_profile
elif browser_data[browser]['base'] == 'ie':
function = clean_internet_explorer
elif browser_data[browser]['base'] == 'mozilla':
function = clean_mozilla_profile
try_and_print(
message='{}...'.format(profile['name']),
indent=indent, width=width, function=function,
other_results=other_results, profile=profile)
def scan_for_browsers(just_firefox=False):
"""Scan system for any supported browsers."""
for name, details in sorted(SUPPORTED_BROWSERS.items()):
if just_firefox and details['base'] != 'mozilla':
continue
try_and_print(message='{}...'.format(name),
function=get_browser_details, cs='Detected',
other_results=other_results, name=name)
"""Scan system for any supported browsers."""
for name, details in sorted(SUPPORTED_BROWSERS.items()):
if just_firefox and details['base'] != 'mozilla':
continue
try_and_print(message='{}...'.format(name),
function=get_browser_details, cs='Detected',
other_results=other_results, name=name)
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -2,128 +2,135 @@
from functions.common import *
def cleanup_adwcleaner():
"""Move AdwCleaner folders into the ClientDir."""
source_path = r'{SYSTEMDRIVE}\AdwCleaner'.format(**global_vars['Env'])
source_quarantine = r'{}\Quarantine'.format(source_path)
"""Move AdwCleaner folders into the ClientDir."""
source_path = r'{SYSTEMDRIVE}\AdwCleaner'.format(**global_vars['Env'])
source_quarantine = r'{}\Quarantine'.format(source_path)
# Quarantine
if os.path.exists(source_quarantine):
os.makedirs(global_vars['QuarantineDir'], exist_ok=True)
dest_name = r'{QuarantineDir}\AdwCleaner_{Date-Time}'.format(
**global_vars)
dest_name = non_clobber_rename(dest_name)
shutil.move(source_quarantine, dest_name)
# Quarantine
if os.path.exists(source_quarantine):
os.makedirs(global_vars['QuarantineDir'], exist_ok=True)
dest_name = r'{QuarantineDir}\AdwCleaner_{Date-Time}'.format(
**global_vars)
dest_name = non_clobber_rename(dest_name)
shutil.move(source_quarantine, dest_name)
# Delete source folder if empty
delete_empty_folders(source_path)
# Delete source folder if empty
delete_empty_folders(source_path)
# Main folder
if os.path.exists(source_path):
os.makedirs(global_vars['LogDir'], exist_ok=True)
dest_name = r'{LogDir}\Tools\AdwCleaner'.format(
**global_vars)
dest_name = non_clobber_rename(dest_name)
shutil.move(source_path, dest_name)
# Main folder
if os.path.exists(source_path):
os.makedirs(global_vars['LogDir'], exist_ok=True)
dest_name = r'{LogDir}\Tools\AdwCleaner'.format(
**global_vars)
dest_name = non_clobber_rename(dest_name)
shutil.move(source_path, dest_name)
def cleanup_cbs(dest_folder):
"""Safely cleanup a known CBS archive bug under Windows 7.
"""Safely cleanup a known CBS archive bug under Windows 7.
If a CbsPersist file is larger than 2 Gb then the auto archive feature
continually fails and will fill up the system drive with temp files.
If a CbsPersist file is larger than 2 Gb then the auto archive feature
continually fails and will fill up the system drive with temp files.
This function moves the temp files and CbsPersist file to a temp folder,
compresses the CbsPersist files with 7-Zip, and then opens the temp folder
for the user to manually save the backup files and delete the temp files.
"""
backup_folder = r'{dest_folder}\CbsFix'.format(dest_folder=dest_folder)
temp_folder = r'{backup_folder}\Temp'.format(backup_folder=backup_folder)
os.makedirs(backup_folder, exist_ok=True)
os.makedirs(temp_folder, exist_ok=True)
This function moves the temp files and CbsPersist file to a temp folder,
compresses the CbsPersist files with 7-Zip, and then opens the temp folder
for the user to manually save the backup files and delete the temp files.
"""
backup_folder = r'{dest_folder}\CbsFix'.format(dest_folder=dest_folder)
temp_folder = r'{backup_folder}\Temp'.format(backup_folder=backup_folder)
os.makedirs(backup_folder, exist_ok=True)
os.makedirs(temp_folder, exist_ok=True)
# Move files into temp folder
cbs_path = r'{SYSTEMROOT}\Logs\CBS'.format(**global_vars['Env'])
for entry in os.scandir(cbs_path):
# CbsPersist files
if entry.name.lower().startswith('cbspersist'):
dest_name = r'{}\{}'.format(temp_folder, entry.name)
dest_name = non_clobber_rename(dest_name)
shutil.move(entry.path, dest_name)
temp_path = r'{SYSTEMROOT}\Temp'.format(**global_vars['Env'])
for entry in os.scandir(temp_path):
# cab_ files
if entry.name.lower().startswith('cab_'):
dest_name = r'{}\{}'.format(temp_folder, entry.name)
dest_name = non_clobber_rename(dest_name)
shutil.move(entry.path, dest_name)
# Move files into temp folder
cbs_path = r'{SYSTEMROOT}\Logs\CBS'.format(**global_vars['Env'])
for entry in os.scandir(cbs_path):
# CbsPersist files
if entry.name.lower().startswith('cbspersist'):
dest_name = r'{}\{}'.format(temp_folder, entry.name)
dest_name = non_clobber_rename(dest_name)
shutil.move(entry.path, dest_name)
temp_path = r'{SYSTEMROOT}\Temp'.format(**global_vars['Env'])
for entry in os.scandir(temp_path):
# cab_ files
if entry.name.lower().startswith('cab_'):
dest_name = r'{}\{}'.format(temp_folder, entry.name)
dest_name = non_clobber_rename(dest_name)
shutil.move(entry.path, dest_name)
# Compress CbsPersist files with 7-Zip
cmd = [
global_vars['Tools']['SevenZip'],
'a', '-t7z', '-mx=3', '-bso0', '-bse0',
r'{}\CbsPersists.7z'.format(backup_folder),
r'{}\CbsPersist*'.format(temp_folder)]
run_program(cmd)
# Compress CbsPersist files with 7-Zip
cmd = [
global_vars['Tools']['SevenZip'],
'a', '-t7z', '-mx=3', '-bso0', '-bse0',
r'{}\CbsPersists.7z'.format(backup_folder),
r'{}\CbsPersist*'.format(temp_folder)]
run_program(cmd)
def cleanup_desktop():
"""Move known backup files and reports into the ClientDir."""
dest_folder = r'{LogDir}\Tools'.format(**global_vars)
os.makedirs(dest_folder, exist_ok=True)
"""Move known backup files and reports into the ClientDir."""
dest_folder = r'{LogDir}\Tools'.format(**global_vars)
os.makedirs(dest_folder, exist_ok=True)
desktop_path = r'{USERPROFILE}\Desktop'.format(**global_vars['Env'])
for entry in os.scandir(desktop_path):
# JRT, RKill, Shortcut cleaner
if re.search(r'^(JRT|RKill|sc-cleaner)', entry.name, re.IGNORECASE):
dest_name = r'{}\{}'.format(dest_folder, entry.name)
dest_name = non_clobber_rename(dest_name)
shutil.move(entry.path, dest_name)
desktop_path = r'{USERPROFILE}\Desktop'.format(**global_vars['Env'])
for entry in os.scandir(desktop_path):
# JRT, RKill, Shortcut cleaner
if re.search(r'^(JRT|RKill|sc-cleaner)', entry.name, re.IGNORECASE):
dest_name = r'{}\{}'.format(dest_folder, entry.name)
dest_name = non_clobber_rename(dest_name)
shutil.move(entry.path, dest_name)
# Remove dir if empty
delete_empty_folders(dest_folder)
# Remove dir if empty
delete_empty_folders(dest_folder)
def delete_empty_folders(folder_path):
"""Delete all empty folders in path (depth first)."""
if not os.path.exists(folder_path) or not os.path.isdir(folder_path):
# Bail early (silently)
return
"""Delete all empty folders in path (depth first)."""
if not os.path.exists(folder_path) or not os.path.isdir(folder_path):
# Bail early (silently)
return
# Delete empty subfolders first
for item in os.scandir(folder_path):
if item.is_dir():
delete_empty_folders(item.path)
# Delete empty subfolders first
for item in os.scandir(folder_path):
if item.is_dir():
delete_empty_folders(item.path)
# Remove top folder
try:
os.rmdir(folder_path)
except OSError:
pass
# Remove top folder
try:
os.rmdir(folder_path)
except OSError:
pass
def delete_registry_key(hive, key, recurse=False):
"""Delete a registry key and all it's subkeys."""
access = winreg.KEY_ALL_ACCESS
"""Delete a registry key and all it's subkeys."""
access = winreg.KEY_ALL_ACCESS
try:
if recurse:
# Delete all subkeys first
with winreg.OpenKeyEx(hive, key, 0, access) as k:
key_info = winreg.QueryInfoKey(k)
for x in range(key_info[0]):
subkey = r'{}\{}'.format(key, winreg.EnumKey(k, 0))
delete_registry_key(hive, subkey)
try:
if recurse:
# Delete all subkeys first
with winreg.OpenKeyEx(hive, key, 0, access) as k:
key_info = winreg.QueryInfoKey(k)
for x in range(key_info[0]):
subkey = r'{}\{}'.format(key, winreg.EnumKey(k, 0))
delete_registry_key(hive, subkey)
# Delete key
winreg.DeleteKey(hive, key)
except FileNotFoundError:
# Ignore
pass
# Delete key
winreg.DeleteKey(hive, key)
except FileNotFoundError:
# Ignore
pass
def delete_registry_value(hive, key, value):
"""Delete a registry value."""
access = winreg.KEY_ALL_ACCESS
with winreg.OpenKeyEx(hive, key, 0, access) as k:
winreg.DeleteValue(k, value)
"""Delete a registry value."""
access = winreg.KEY_ALL_ACCESS
with winreg.OpenKeyEx(hive, key, 0, access) as k:
winreg.DeleteValue(k, value)
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=4 sw=4 ts=4
# vim: sts=2 sw=2 ts=2

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,189 +0,0 @@
# Wizard Kit: Functions - Diagnostics
import ctypes
from functions.common import *
# STATIC VARIABLES
AUTORUNS_SETTINGS = {
r'Software\Sysinternals\AutoRuns': {
'checkvirustotal': 1,
'EulaAccepted': 1,
'shownomicrosoft': 1,
'shownowindows': 1,
'showonlyvirustotal': 1,
'submitvirustotal': 0,
'verifysignatures': 1,
},
r'Software\Sysinternals\AutoRuns\SigCheck': {
'EulaAccepted': 1,
},
r'Software\Sysinternals\AutoRuns\Streams': {
'EulaAccepted': 1,
},
r'Software\Sysinternals\AutoRuns\VirusTotal': {
'VirusTotalTermsAccepted': 1,
},
}
def check_connection():
"""Check if the system is online and optionally abort the script."""
while True:
result = try_and_print(message='Ping test...', function=ping, cs='OK')
if result['CS']:
break
if not ask('ERROR: System appears offline, try again?'):
if ask('Continue anyway?'):
break
else:
abort()
def check_secure_boot_status(show_alert=False):
"""Checks UEFI Secure Boot status via PowerShell."""
boot_mode = get_boot_mode()
cmd = ['PowerShell', '-Command', 'Confirm-SecureBootUEFI']
result = run_program(cmd, check=False)
# Check results
if result.returncode == 0:
out = result.stdout.decode()
if 'True' in out:
# It's on, do nothing
return
elif 'False' in out:
if show_alert:
show_alert_box('Secure Boot DISABLED')
raise SecureBootDisabledError
else:
if show_alert:
show_alert_box('Secure Boot status UNKNOWN')
raise SecureBootUnknownError
else:
if boot_mode != 'UEFI':
if (show_alert and
global_vars['OS']['Version'] in ('8', '8.1', '10')):
# OS supports Secure Boot
show_alert_box('Secure Boot DISABLED\n\nOS installed LEGACY')
raise OSInstalledLegacyError
else:
# Check error message
err = result.stderr.decode()
if 'Cmdlet not supported' in err:
if show_alert:
show_alert_box('Secure Boot UNAVAILABLE?')
raise SecureBootNotAvailError
else:
if show_alert:
show_alert_box('Secure Boot ERROR')
raise GenericError
def get_boot_mode():
"""Check if Windows is booted in UEFI or Legacy mode, returns str."""
kernel = ctypes.windll.kernel32
firmware_type = ctypes.c_uint()
# Get value from kernel32 API
try:
kernel.GetFirmwareType(ctypes.byref(firmware_type))
except:
# Just set to zero
firmware_type = ctypes.c_uint(0)
# Set return value
type_str = 'Unknown'
if firmware_type.value == 1:
type_str = 'Legacy'
elif firmware_type.value == 2:
type_str = 'UEFI'
return type_str
def run_autoruns():
"""Run AutoRuns in the background with VirusTotal checks enabled."""
extract_item('Autoruns', filter='autoruns*', silent=True)
# Update AutoRuns settings before running
for path, settings in AUTORUNS_SETTINGS.items():
winreg.CreateKey(HKCU, path)
with winreg.OpenKey(HKCU, path, access=winreg.KEY_WRITE) as key:
for name, value in settings.items():
winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value)
popen_program(global_vars['Tools']['AutoRuns'], minimized=True)
def run_hwinfo_sensors():
"""Run HWiNFO sensors."""
path = r'{BinDir}\HWiNFO'.format(**global_vars)
for bit in [32, 64]:
# Configure
source = r'{}\general.ini'.format(path)
dest = r'{}\HWiNFO{}.ini'.format(path, bit)
shutil.copy(source, dest)
with open(dest, 'a') as f:
f.write('SensorsOnly=1\n')
f.write('SummaryOnly=0\n')
popen_program(global_vars['Tools']['HWiNFO'])
def run_nircmd(*cmd):
"""Run custom NirCmd."""
extract_item('NirCmd', silent=True)
cmd = [global_vars['Tools']['NirCmd'], *cmd]
run_program(cmd, check=False)
def run_xmplay():
"""Run XMPlay to test audio."""
extract_item('XMPlay', silent=True)
cmd = [global_vars['Tools']['XMPlay'],
r'{BinDir}\XMPlay\music.7z'.format(**global_vars)]
# Unmute audio first
extract_item('NirCmd', silent=True)
run_nircmd('mutesysvolume', '0')
# Open XMPlay
popen_program(cmd)
def run_hitmanpro():
"""Run HitmanPro in the background."""
extract_item('HitmanPro', silent=True)
cmd = [
global_vars['Tools']['HitmanPro'],
'/quiet', '/noinstall', '/noupload',
r'/log={LogDir}\Tools\HitmanPro.txt'.format(**global_vars)]
popen_program(cmd)
def run_process_killer():
"""Kill most running processes skipping those in the whitelist.txt."""
# borrowed from TronScript (reddit.com/r/TronScript)
# credit to /u/cuddlychops06
prev_dir = os.getcwd()
extract_item('ProcessKiller', silent=True)
os.chdir(r'{BinDir}\ProcessKiller'.format(**global_vars))
run_program(['ProcessKiller.exe', '/silent'], check=False)
os.chdir(prev_dir)
def run_rkill():
"""Run RKill and cleanup afterwards."""
extract_item('RKill', silent=True)
cmd = [
global_vars['Tools']['RKill'],
'-s', '-l', r'{LogDir}\Tools\RKill.log'.format(**global_vars),
'-new_console:n', '-new_console:s33V']
run_program(cmd, check=False)
wait_for_process('RKill')
# RKill cleanup
desktop_path = r'{USERPROFILE}\Desktop'.format(**global_vars['Env'])
if os.path.exists(desktop_path):
for item in os.scandir(desktop_path):
if re.search(r'^RKill', item.name, re.IGNORECASE):
dest = r'{LogDir}\Tools\{name}'.format(
name=dest, **global_vars)
dest = non_clobber_rename(dest)
shutil.move(item.path, dest)
def show_alert_box(message, title='Wizard Kit Warning'):
"""Show Windows alert box with message."""
message_box = ctypes.windll.user32.MessageBoxW
message_box(None, message, title, 0x00001030)
if __name__ == '__main__':
print("This file is not meant to be called directly.")

View file

@ -1,395 +1,414 @@
# Wizard Kit: Functions - Disk
from functions.common import *
from functions import partition_uids
from settings.partition_uids import *
# Regex
REGEX_BAD_PARTITION = re.compile(r'(RAW|Unknown)', re.IGNORECASE)
REGEX_DISK_GPT = re.compile(
r'Disk ID: {[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+}',
re.IGNORECASE)
r'Disk ID: {[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+}',
re.IGNORECASE)
REGEX_DISK_MBR = re.compile(r'Disk ID: [A-Z0-9]+', re.IGNORECASE)
REGEX_DISK_RAW = re.compile(r'Disk ID: 00000000', re.IGNORECASE)
def assign_volume_letters():
"""Assign a volume letter to all available volumes."""
remove_volume_letters()
"""Assign a volume letter to all available volumes."""
remove_volume_letters()
# Write script
script = []
for vol in get_volumes():
script.append('select volume {}'.format(vol['Number']))
script.append('assign')
# Write script
script = []
for vol in get_volumes():
script.append('select volume {}'.format(vol['Number']))
script.append('assign')
# Run
run_diskpart(script)
# Run
run_diskpart(script)
def get_boot_mode():
"""Check if the boot mode was UEFI or legacy."""
boot_mode = 'Legacy'
try:
reg_key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE, r'System\CurrentControlSet\Control')
reg_value = winreg.QueryValueEx(reg_key, 'PEFirmwareType')[0]
if reg_value == 2:
boot_mode = 'UEFI'
except:
boot_mode = 'Unknown'
"""Check if the boot mode was UEFI or legacy."""
boot_mode = 'Legacy'
try:
reg_key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE, r'System\CurrentControlSet\Control')
reg_value = winreg.QueryValueEx(reg_key, 'PEFirmwareType')[0]
if reg_value == 2:
boot_mode = 'UEFI'
except:
boot_mode = 'Unknown'
return boot_mode
return boot_mode
def get_disk_details(disk):
"""Get disk details using DiskPart."""
details = {}
script = [
'select disk {}'.format(disk['Number']),
'detail disk']
"""Get disk details using DiskPart."""
details = {}
script = [
'select disk {}'.format(disk['Number']),
'detail disk']
# Run
try:
result = run_diskpart(script)
except subprocess.CalledProcessError:
pass
else:
output = result.stdout.decode().strip()
# Remove empty lines
tmp = [s.strip() for s in output.splitlines() if s.strip() != '']
# Set disk name
details['Name'] = tmp[4]
# Split each line on ':' skipping those without ':'
tmp = [s.split(':') for s in tmp if ':' in s]
# Add key/value pairs to the details variable and return dict
details.update({key.strip(): value.strip() for (key, value) in tmp})
# Run
try:
result = run_diskpart(script)
except subprocess.CalledProcessError:
pass
else:
output = result.stdout.decode().strip()
# Remove empty lines
tmp = [s.strip() for s in output.splitlines() if s.strip() != '']
# Set disk name
details['Name'] = tmp[4]
# Split each line on ':' skipping those without ':'
tmp = [s.split(':') for s in tmp if ':' in s]
# Add key/value pairs to the details variable and return dict
details.update({key.strip(): value.strip() for (key, value) in tmp})
return details
return details
def get_disks():
"""Get list of attached disks using DiskPart."""
disks = []
"""Get list of attached disks using DiskPart."""
disks = []
try:
# Run script
result = run_diskpart(['list disk'])
except subprocess.CalledProcessError:
pass
else:
# Append disk numbers
output = result.stdout.decode().strip()
for tmp in re.findall(r'Disk (\d+)\s+\w+\s+(\d+\s+\w+)', output):
num = tmp[0]
size = human_readable_size(tmp[1])
disks.append({'Number': num, 'Size': size})
try:
# Run script
result = run_diskpart(['list disk'])
except subprocess.CalledProcessError:
pass
else:
# Append disk numbers
output = result.stdout.decode().strip()
for tmp in re.findall(r'Disk (\d+)\s+\w+\s+(\d+\s+\w+)', output):
num = tmp[0]
size = human_readable_size(tmp[1])
disks.append({'Number': num, 'Size': size})
return disks
return disks
def get_partition_details(disk, partition):
"""Get partition details using DiskPart and fsutil."""
details = {}
script = [
'select disk {}'.format(disk['Number']),
'select partition {}'.format(partition['Number']),
'detail partition']
"""Get partition details using DiskPart and fsutil."""
details = {}
script = [
'select disk {}'.format(disk['Number']),
'select partition {}'.format(partition['Number']),
'detail partition']
# Diskpart details
# Diskpart details
try:
# Run script
result = run_diskpart(script)
except subprocess.CalledProcessError:
pass
else:
# Get volume letter or RAW status
output = result.stdout.decode().strip()
tmp = re.search(r'Volume\s+\d+\s+(\w|RAW)\s+', output)
if tmp:
if tmp.group(1).upper() == 'RAW':
details['FileSystem'] = RAW
else:
details['Letter'] = tmp.group(1)
# Remove empty lines from output
tmp = [s.strip() for s in output.splitlines() if s.strip() != '']
# Split each line on ':' skipping those without ':'
tmp = [s.split(':') for s in tmp if ':' in s]
# Add key/value pairs to the details variable and return dict
details.update({key.strip(): value.strip() for (key, value) in tmp})
# Get MBR type / GPT GUID for extra details on "Unknown" partitions
guid = PARTITION_UIDS.get(details.get('Type').upper(), {})
if guid:
details.update({
'Description': guid.get('Description', '')[:29],
'OS': guid.get('OS', 'Unknown')[:27]})
if 'Letter' in details:
# Disk usage
try:
# Run script
result = run_diskpart(script)
except subprocess.CalledProcessError:
pass
tmp = psutil.disk_usage('{}:\\'.format(details['Letter']))
except OSError as err:
details['FileSystem'] = 'Unknown'
details['Error'] = err.strerror
else:
# Get volume letter or RAW status
output = result.stdout.decode().strip()
tmp = re.search(r'Volume\s+\d+\s+(\w|RAW)\s+', output)
if tmp:
if tmp.group(1).upper() == 'RAW':
details['FileSystem'] = RAW
else:
details['Letter'] = tmp.group(1)
# Remove empty lines from output
tmp = [s.strip() for s in output.splitlines() if s.strip() != '']
# Split each line on ':' skipping those without ':'
tmp = [s.split(':') for s in tmp if ':' in s]
# Add key/value pairs to the details variable and return dict
details.update({key.strip(): value.strip() for (key, value) in tmp})
details['Used Space'] = human_readable_size(tmp.used)
# Get MBR type / GPT GUID for extra details on "Unknown" partitions
guid = partition_uids.lookup_guid(details.get('Type'))
if guid:
details.update({
'Description': guid.get('Description', '')[:29],
'OS': guid.get('OS', 'Unknown')[:27]})
# fsutil details
cmd = [
'fsutil',
'fsinfo',
'volumeinfo',
'{}:'.format(details['Letter'])
]
try:
result = run_program(cmd)
except subprocess.CalledProcessError:
pass
else:
output = result.stdout.decode().strip()
# Remove empty lines from output
tmp = [s.strip() for s in output.splitlines() if s.strip() != '']
# Add "Feature" lines
details['File System Features'] = [s.strip() for s in tmp
if ':' not in s]
# Split each line on ':' skipping those without ':'
tmp = [s.split(':') for s in tmp if ':' in s]
# Add key/value pairs to the details variable and return dict
details.update({key.strip(): value.strip() for (key, value) in tmp})
if 'Letter' in details:
# Disk usage
try:
tmp = psutil.disk_usage('{}:\\'.format(details['Letter']))
except OSError as err:
details['FileSystem'] = 'Unknown'
details['Error'] = err.strerror
else:
details['Used Space'] = human_readable_size(tmp.used)
# Set Volume Name
details['Name'] = details.get('Volume Name', '')
# fsutil details
cmd = [
'fsutil',
'fsinfo',
'volumeinfo',
'{}:'.format(details['Letter'])
]
try:
result = run_program(cmd)
except subprocess.CalledProcessError:
pass
else:
output = result.stdout.decode().strip()
# Remove empty lines from output
tmp = [s.strip() for s in output.splitlines() if s.strip() != '']
# Add "Feature" lines
details['File System Features'] = [s.strip() for s in tmp
if ':' not in s]
# Split each line on ':' skipping those without ':'
tmp = [s.split(':') for s in tmp if ':' in s]
# Add key/value pairs to the details variable and return dict
details.update({key.strip(): value.strip() for (key, value) in tmp})
# Set FileSystem Type
if details.get('FileSystem', '') not in ['RAW', 'Unknown']:
details['FileSystem'] = details.get('File System Name', 'Unknown')
# Set Volume Name
details['Name'] = details.get('Volume Name', '')
return details
# Set FileSystem Type
if details.get('FileSystem', '') not in ['RAW', 'Unknown']:
details['FileSystem'] = details.get('File System Name', 'Unknown')
return details
def get_partitions(disk):
"""Get list of partition using DiskPart."""
partitions = []
script = [
'select disk {}'.format(disk['Number']),
'list partition']
"""Get list of partition using DiskPart."""
partitions = []
script = [
'select disk {}'.format(disk['Number']),
'list partition']
try:
# Run script
result = run_diskpart(script)
except subprocess.CalledProcessError:
pass
else:
# Append partition numbers
output = result.stdout.decode().strip()
regex = r'Partition\s+(\d+)\s+\w+\s+(\d+\s+\w+)\s+'
for tmp in re.findall(regex, output, re.IGNORECASE):
num = tmp[0]
size = human_readable_size(tmp[1])
partitions.append({'Number': num, 'Size': size})
try:
# Run script
result = run_diskpart(script)
except subprocess.CalledProcessError:
pass
else:
# Append partition numbers
output = result.stdout.decode().strip()
regex = r'Partition\s+(\d+)\s+\w+\s+(\d+\s+\w+)\s+'
for tmp in re.findall(regex, output, re.IGNORECASE):
num = tmp[0]
size = human_readable_size(tmp[1])
partitions.append({'Number': num, 'Size': size})
return partitions
return partitions
def get_table_type(disk):
"""Get disk partition table type using DiskPart."""
part_type = 'Unknown'
script = [
'select disk {}'.format(disk['Number']),
'uniqueid disk']
"""Get disk partition table type using DiskPart."""
part_type = 'Unknown'
script = [
'select disk {}'.format(disk['Number']),
'uniqueid disk']
try:
result = run_diskpart(script)
except subprocess.CalledProcessError:
pass
else:
output = result.stdout.decode().strip()
if REGEX_DISK_GPT.search(output):
part_type = 'GPT'
elif REGEX_DISK_MBR.search(output):
part_type = 'MBR'
elif REGEX_DISK_RAW.search(output):
part_type = 'RAW'
try:
result = run_diskpart(script)
except subprocess.CalledProcessError:
pass
else:
output = result.stdout.decode().strip()
if REGEX_DISK_GPT.search(output):
part_type = 'GPT'
elif REGEX_DISK_MBR.search(output):
part_type = 'MBR'
elif REGEX_DISK_RAW.search(output):
part_type = 'RAW'
return part_type
return part_type
def get_volumes():
"""Get list of volumes using DiskPart."""
vols = []
try:
result = run_diskpart(['list volume'])
except subprocess.CalledProcessError:
pass
else:
# Append volume numbers
output = result.stdout.decode().strip()
for tmp in re.findall(r'Volume (\d+)\s+([A-Za-z]?)\s+', output):
vols.append({'Number': tmp[0], 'Letter': tmp[1]})
"""Get list of volumes using DiskPart."""
vols = []
try:
result = run_diskpart(['list volume'])
except subprocess.CalledProcessError:
pass
else:
# Append volume numbers
output = result.stdout.decode().strip()
for tmp in re.findall(r'Volume (\d+)\s+([A-Za-z]?)\s+', output):
vols.append({'Number': tmp[0], 'Letter': tmp[1]})
return vols
return vols
def is_bad_partition(par):
"""Check if the partition is accessible."""
return 'Letter' not in par or REGEX_BAD_PARTITION.search(par['FileSystem'])
"""Check if the partition is accessible."""
return 'Letter' not in par or REGEX_BAD_PARTITION.search(par['FileSystem'])
def prep_disk_for_formatting(disk=None):
"""Gather details about the disk and its partitions."""
disk['Format Warnings'] = '\n'
width = len(str(len(disk['Partitions'])))
"""Gather details about the disk and its partitions."""
disk['Format Warnings'] = '\n'
width = len(str(len(disk['Partitions'])))
# Bail early
if disk is None:
raise Exception('Disk not provided.')
# Bail early
if disk is None:
raise Exception('Disk not provided.')
# Set boot method and partition table type
disk['Use GPT'] = True
if (get_boot_mode() == 'UEFI'):
if (not ask("Setup Windows to use UEFI booting?")):
disk['Use GPT'] = False
# Set boot method and partition table type
disk['Use GPT'] = True
if (get_boot_mode() == 'UEFI'):
if (not ask("Setup Windows to use UEFI booting?")):
disk['Use GPT'] = False
else:
if (ask("Setup Windows to use BIOS/Legacy booting?")):
disk['Use GPT'] = False
# Set Display and Warning Strings
if len(disk['Partitions']) == 0:
disk['Format Warnings'] += 'No partitions found\n'
for partition in disk['Partitions']:
display = '{size} {fs}'.format(
num = partition['Number'],
width = width,
size = partition['Size'],
fs = partition['FileSystem'])
if is_bad_partition(partition):
# Set display string using partition description & OS type
display += '\t\t{q}{name}{q}\t{desc} ({os})'.format(
display = display,
q = '"' if partition['Name'] != '' else '',
name = partition['Name'],
desc = partition['Description'],
os = partition['OS'])
else:
if (ask("Setup Windows to use BIOS/Legacy booting?")):
disk['Use GPT'] = False
# List space used instead of partition description & OS type
display += ' (Used: {used})\t{q}{name}{q}'.format(
used = partition['Used Space'],
q = '"' if partition['Name'] != '' else '',
name = partition['Name'])
# For all partitions
partition['Display String'] = display
# Set Display and Warning Strings
if len(disk['Partitions']) == 0:
disk['Format Warnings'] += 'No partitions found\n'
for partition in disk['Partitions']:
display = '{size} {fs}'.format(
num = partition['Number'],
width = width,
size = partition['Size'],
fs = partition['FileSystem'])
if is_bad_partition(partition):
# Set display string using partition description & OS type
display += '\t\t{q}{name}{q}\t{desc} ({os})'.format(
display = display,
q = '"' if partition['Name'] != '' else '',
name = partition['Name'],
desc = partition['Description'],
os = partition['OS'])
else:
# List space used instead of partition description & OS type
display += ' (Used: {used})\t{q}{name}{q}'.format(
used = partition['Used Space'],
q = '"' if partition['Name'] != '' else '',
name = partition['Name'])
# For all partitions
partition['Display String'] = display
def reassign_volume_letter(letter, new_letter='I'):
"""Assign a new letter to a volume using DiskPart."""
if not letter:
# Ignore
return None
script = [
'select volume {}'.format(letter),
'remove noerr',
'assign letter={}'.format(new_letter)]
try:
run_diskpart(script)
except subprocess.CalledProcessError:
pass
else:
return new_letter
"""Assign a new letter to a volume using DiskPart."""
if not letter:
# Ignore
return None
script = [
'select volume {}'.format(letter),
'remove noerr',
'assign letter={}'.format(new_letter)]
try:
run_diskpart(script)
except subprocess.CalledProcessError:
pass
else:
return new_letter
def remove_volume_letters(keep=None):
"""Remove all assigned volume letters using DiskPart."""
if not keep:
keep = ''
"""Remove all assigned volume letters using DiskPart."""
if not keep:
keep = ''
script = []
for vol in get_volumes():
if vol['Letter'].upper() != keep.upper():
script.append('select volume {}'.format(vol['Number']))
script.append('remove noerr')
script = []
for vol in get_volumes():
if vol['Letter'].upper() != keep.upper():
script.append('select volume {}'.format(vol['Number']))
script.append('remove noerr')
# Run script
try:
run_diskpart(script)
except subprocess.CalledProcessError:
pass
# Run script
try:
run_diskpart(script)
except subprocess.CalledProcessError:
pass
def run_diskpart(script):
"""Run DiskPart script."""
tempfile = r'{}\diskpart.script'.format(global_vars['Env']['TMP'])
"""Run DiskPart script."""
tempfile = r'{}\diskpart.script'.format(global_vars['Env']['TMP'])
# Write script
with open(tempfile, 'w') as f:
for line in script:
f.write('{}\n'.format(line))
# Write script
with open(tempfile, 'w') as f:
for line in script:
f.write('{}\n'.format(line))
# Run script
cmd = [
r'{}\Windows\System32\diskpart.exe'.format(
global_vars['Env']['SYSTEMDRIVE']),
'/s', tempfile]
result = run_program(cmd)
sleep(2)
return result
# Run script
cmd = [
r'{}\Windows\System32\diskpart.exe'.format(
global_vars['Env']['SYSTEMDRIVE']),
'/s', tempfile]
result = run_program(cmd)
sleep(2)
return result
def scan_disks():
"""Get details about the attached disks"""
disks = get_disks()
"""Get details about the attached disks"""
disks = get_disks()
# Get disk details
for disk in disks:
# Get partition style
disk['Table'] = get_table_type(disk)
# Get disk details
for disk in disks:
# Get partition style
disk['Table'] = get_table_type(disk)
# Get disk name/model and physical details
disk.update(get_disk_details(disk))
# Get disk name/model and physical details
disk.update(get_disk_details(disk))
# Get partition info for disk
disk['Partitions'] = get_partitions(disk)
# Get partition info for disk
disk['Partitions'] = get_partitions(disk)
for partition in disk['Partitions']:
# Get partition details
partition.update(get_partition_details(disk, partition))
for partition in disk['Partitions']:
# Get partition details
partition.update(get_partition_details(disk, partition))
# Done
return disks
# Done
return disks
def select_disk(title='Which disk?', disks=[]):
"""Select a disk from the attached disks"""
# Build menu
disk_options = []
for disk in disks:
display_name = '{}\t[{}] ({}) {}'.format(
disk.get('Size', ''),
disk.get('Table', ''),
disk.get('Type', ''),
disk.get('Name', 'Unknown'),
)
pwidth=len(str(len(disk['Partitions'])))
for partition in disk['Partitions']:
# Main text
p_name = 'Partition {num:>{width}}: {size} ({fs})'.format(
num = partition['Number'],
width = pwidth,
size = partition['Size'],
fs = partition['FileSystem'])
if partition['Name']:
p_name += '\t"{}"'.format(partition['Name'])
"""Select a disk from the attached disks"""
# Build menu
disk_options = []
for disk in disks:
display_name = '{}\t[{}] ({}) {}'.format(
disk.get('Size', ''),
disk.get('Table', ''),
disk.get('Type', ''),
disk.get('Name', 'Unknown'),
)
pwidth=len(str(len(disk['Partitions'])))
for partition in disk['Partitions']:
# Main text
p_name = 'Partition {num:>{width}}: {size} ({fs})'.format(
num = partition['Number'],
width = pwidth,
size = partition['Size'],
fs = partition['FileSystem'])
if partition['Name']:
p_name += '\t"{}"'.format(partition['Name'])
# Show unsupported partition(s)
if is_bad_partition(partition):
p_name = '{YELLOW}{p_name}{CLEAR}'.format(
p_name=p_name, **COLORS)
# Show unsupported partition(s)
if is_bad_partition(partition):
p_name = '{YELLOW}{p_name}{CLEAR}'.format(
p_name=p_name, **COLORS)
display_name += '\n\t\t\t{}'.format(p_name)
if not disk['Partitions']:
display_name += '\n\t\t\t{}No partitions found.{}'.format(
COLORS['YELLOW'], COLORS['CLEAR'])
display_name += '\n\t\t\t{}'.format(p_name)
if not disk['Partitions']:
display_name += '\n\t\t\t{}No partitions found.{}'.format(
COLORS['YELLOW'], COLORS['CLEAR'])
disk_options.append({'Name': display_name, 'Disk': disk})
actions = [
{'Name': 'Main Menu', 'Letter': 'M'},
]
disk_options.append({'Name': display_name, 'Disk': disk})
actions = [
{'Name': 'Main Menu', 'Letter': 'M'},
]
# Menu loop
selection = menu_select(
title = title,
main_entries = disk_options,
action_entries = actions)
# Menu loop
selection = menu_select(
title = title,
main_entries = disk_options,
action_entries = actions)
if (selection.isnumeric()):
return disk_options[int(selection)-1]['Disk']
elif (selection == 'M'):
raise GenericAbort
if (selection.isnumeric()):
return disk_options[int(selection)-1]['Disk']
elif (selection == 'M'):
raise GenericAbort
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -8,6 +8,7 @@ from collections import OrderedDict
from functions.sensors import *
from functions.tmux import *
# STATIC VARIABLES
ATTRIBUTES = {
'NVMe': {
@ -83,13 +84,16 @@ TMUX_LAYOUT = OrderedDict({
'Progress': {'x': SIDE_PANE_WIDTH, 'Check': True},
})
# Regex
REGEX_ERROR_STATUS = re.compile('|'.join(STATUSES['RED']))
# Error Classes
class DeviceTooSmallError(Exception):
pass
# Classes
class CpuObj():
"""Object for tracking CPU specific data."""
@ -130,6 +134,7 @@ class CpuObj():
return report
class DiskObj():
"""Object for tracking disk specific data."""
def __init__(self, disk_path):
@ -487,6 +492,7 @@ class DiskObj():
for t in ['badblocks', 'I/O Benchmark']:
self.disable_test(t, 'Denied')
class State():
"""Object to track device objects and overall state."""
def __init__(self):
@ -559,6 +565,7 @@ class State():
if not skip_disk:
self.disks.append(disk_obj)
class TestObj():
"""Object to track test data."""
def __init__(self, dev, label=None, info_label=False):
@ -589,6 +596,7 @@ class TestObj():
self.status = build_status_string(
self.label, 'Working', self.info_label)
# Functions
def build_outer_panes(state):
"""Build top and side panes."""
@ -611,6 +619,7 @@ def build_outer_panes(state):
lines=SIDE_PANE_WIDTH,
watch=state.progress_out)
def build_status_string(label, status, info_label=False):
"""Build status string with appropriate colors."""
status_color = COLORS['CLEAR']
@ -626,6 +635,7 @@ def build_status_string(label, status, info_label=False):
s_w=SIDE_PANE_WIDTH-len(label),
**COLORS)
def fix_tmux_panes(state, tmux_layout):
"""Fix pane sizes if the window has been resized."""
needs_fixed = False
@ -669,6 +679,7 @@ def fix_tmux_panes(state, tmux_layout):
# Resize pane
tmux_resize_pane(pane_id=target, **v)
def generate_horizontal_graph(rates, oneline=False):
"""Generate horizontal graph from rates, returns list."""
graph = ['', '', '', '']
@ -714,6 +725,7 @@ def generate_horizontal_graph(rates, oneline=False):
else:
return graph
def get_graph_step(rate, scale=16):
"""Get graph step based on rate and scale, returns int."""
m_rate = rate / (1024**2)
@ -726,6 +738,7 @@ def get_graph_step(rate, scale=16):
break
return step
def get_read_rate(s):
"""Get read rate in bytes/s from dd progress output."""
real_rate = None
@ -734,6 +747,7 @@ def get_read_rate(s):
real_rate = convert_to_bytes(human_rate)
return real_rate
def menu_diags(state, args):
"""Main menu to select and run HW tests."""
args = [a.lower() for a in args]
@ -840,12 +854,14 @@ def menu_diags(state, args):
elif selection == 'S':
run_hw_tests(state)
def run_audio_test():
"""Run audio test."""
clear_screen()
run_program(['hw-diags-audio'], check=False, pipe=False)
pause('Press Enter to return to main menu... ')
def run_badblocks_test(state, test):
"""Run a read-only surface scan with badblocks."""
# Bail early
@ -939,6 +955,7 @@ def run_badblocks_test(state, test):
# Cleanup
tmux_kill_pane(state.panes['badblocks'])
def run_hw_tests(state):
"""Run enabled hardware tests."""
print_standard('Scanning devices...')
@ -1016,6 +1033,7 @@ def run_hw_tests(state):
# Cleanup
tmux_kill_pane(*state.panes.values())
def run_io_benchmark(state, test):
"""Run a read-only I/O benchmark using dd."""
# Bail early
@ -1173,11 +1191,13 @@ def run_io_benchmark(state, test):
# Cleanup
tmux_kill_pane(state.panes['io_benchmark'])
def run_keyboard_test():
"""Run keyboard test."""
clear_screen()
run_program(['xev', '-event', 'keyboard'], check=False, pipe=False)
def run_mprime_test(state, test):
"""Test CPU with Prime95 and track temps."""
# Bail early
@ -1320,7 +1340,8 @@ def run_mprime_test(state, test):
if re.search(r'(error|fail)', line, re.IGNORECASE):
test.failed = True
test.update_status('NS')
test.report.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS))
test.report.append(
' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS))
# prime.log (CS check)
if log == 'prime.log':
@ -1349,7 +1370,8 @@ def run_mprime_test(state, test):
for line in sorted(_tmp['Pass'].keys()):
test.report.append(' {}'.format(line))
for line in sorted(_tmp['Warn'].keys()):
test.report.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS))
test.report.append(
' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS))
# Unknown result
if not (test.aborted or test.failed or test.passed):
@ -1369,12 +1391,14 @@ def run_mprime_test(state, test):
tmux_kill_pane(state.panes['mprime'], state.panes['Temps'])
test.monitor_proc.kill()
def run_network_test():
"""Run network test."""
clear_screen()
run_program(['hw-diags-network'], check=False, pipe=False)
pause('Press Enter to return to main menu... ')
def run_nvme_smart_tests(state, test):
"""Run NVMe or SMART test for test.dev."""
# Bail early
@ -1518,6 +1542,7 @@ def run_nvme_smart_tests(state, test):
# Done
update_progress_pane(state)
def secret_screensaver(screensaver=None):
"""Show screensaver."""
if screensaver == 'matrix':
@ -1528,6 +1553,7 @@ def secret_screensaver(screensaver=None):
raise Exception('Invalid screensaver')
run_program(cmd, check=False, pipe=False)
def show_report(report, log_report=False):
"""Show report on screen and optionally save to log w/out color."""
for line in report:
@ -1535,6 +1561,7 @@ def show_report(report, log_report=False):
if log_report:
print_log(strip_colors(line))
def show_results(state):
"""Show results for all tests."""
clear_screen()
@ -1562,6 +1589,7 @@ def show_results(state):
show_report(disk.generate_disk_report(), log_report=True)
print_standard(' ')
def update_main_options(state, selection, main_options):
"""Update menu and state based on selection."""
index = int(selection) - 1
@ -1605,6 +1633,7 @@ def update_main_options(state, selection, main_options):
# Done
return main_options
def update_io_progress(percent, rate, progress_file):
"""Update I/O progress file."""
bar_color = COLORS['CLEAR']
@ -1629,6 +1658,7 @@ def update_io_progress(percent, rate, progress_file):
with open(progress_file, 'a') as f:
f.write(line)
def update_progress_pane(state):
"""Update progress file for side pane."""
output = []
@ -1656,6 +1686,7 @@ def update_progress_pane(state):
with open(state.progress_out, 'w') as f:
f.writelines(output)
if __name__ == '__main__':
print("This file is not meant to be called directly.")

View file

@ -1,520 +1,547 @@
# Wizard Kit: Functions - Information
from borrowed import knownpaths
from functions.activation import *
from operator import itemgetter
from functions.common import *
from functions.activation import *
# Regex
REGEX_OFFICE = re.compile(
r'(Microsoft (Office\s+'
r'(365|Enterprise|Home|Pro(\s|fessional)'
r'|Single|Small|Standard|Starter|Ultimate|system)'
r'|Works[-\s\d]+\d)'
r'|(Libre|Open|Star)\s*Office'
r'|WordPerfect|Gnumeric|Abiword)',
re.IGNORECASE)
# STATIC VARIABLES
REG_PROFILE_LIST = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList'
REG_SHELL_FOLDERS = r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders'
TMP_HIVE_PATH = 'TEMP_HIVE_MOUNT'
EXTRA_FOLDERS = [
'Dropbox',
'Google Drive',
'OneDrive',
'SkyDrive',
'Dropbox',
'Google Drive',
'OneDrive',
'SkyDrive',
]
SHELL_FOLDERS = {
#GUIDs from: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx
'Desktop': (
'{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}',
),
'Documents': (
'Personal',
'{FDD39AD0-238F-46AF-ADB4-6C85480369C7}',
),
'Downloads': (
'{374DE290-123F-4565-9164-39C4925E467B}',
),
'Favorites': (
'{1777F761-68AD-4D8A-87BD-30B759FA33DD}',
),
'Music': (
'My Music',
'{4BD8D571-6D19-48D3-BE97-422220080E43}',
),
'Pictures': (
'My Pictures',
'{33E28130-4E1E-4676-835A-98395C3BC3BB}',
),
'Videos': (
'My Video',
'{18989B1D-99B5-455B-841C-AB7C74E4DDFC}',
),
#GUIDs from: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx
'Desktop': (
'{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}',
),
'Documents': (
'Personal',
'{FDD39AD0-238F-46AF-ADB4-6C85480369C7}',
),
'Downloads': (
'{374DE290-123F-4565-9164-39C4925E467B}',
),
'Favorites': (
'{1777F761-68AD-4D8A-87BD-30B759FA33DD}',
),
'Music': (
'My Music',
'{4BD8D571-6D19-48D3-BE97-422220080E43}',
),
'Pictures': (
'My Pictures',
'{33E28130-4E1E-4676-835A-98395C3BC3BB}',
),
'Videos': (
'My Video',
'{18989B1D-99B5-455B-841C-AB7C74E4DDFC}',
),
}
# Regex
REGEX_OFFICE = re.compile(
r'(Microsoft (Office\s+'
r'(365|Enterprise|Home|Pro(\s|fessional)'
r'|Single|Small|Standard|Starter|Ultimate|system)'
r'|Works[-\s\d]+\d)'
r'|(Libre|Open|Star)\s*Office'
r'|WordPerfect|Gnumeric|Abiword)',
re.IGNORECASE)
def backup_file_list():
"""Export current file listing for the system."""
extract_item('Everything', silent=True)
cmd = [
global_vars['Tools']['Everything'],
'-nodb',
'-create-filelist',
r'{LogDir}\File List.txt'.format(**global_vars),
global_vars['Env']['SYSTEMDRIVE']]
run_program(cmd)
"""Export current file listing for the system."""
extract_item('Everything', silent=True)
cmd = [
global_vars['Tools']['Everything'],
'-nodb',
'-create-filelist',
r'{LogDir}\File List.txt'.format(**global_vars),
global_vars['Env']['SYSTEMDRIVE']]
run_program(cmd)
def backup_power_plans():
"""Export current power plans."""
os.makedirs(r'{BackupDir}\Power Plans\{Date}'.format(
**global_vars), exist_ok=True)
plans = run_program(['powercfg', '/L'])
plans = plans.stdout.decode().splitlines()
plans = [p for p in plans if re.search(r'^Power Scheme', p)]
for p in plans:
guid = re.sub(r'Power Scheme GUID:\s+([0-9a-f\-]+).*', r'\1', p)
name = re.sub(
r'Power Scheme GUID:\s+[0-9a-f\-]+\s+\(([^\)]+)\).*', r'\1', p)
out = r'{BackupDir}\Power Plans\{Date}\{name}.pow'.format(
name=name, **global_vars)
if not os.path.exists(out):
cmd = ['powercfg', '-export', out, guid]
run_program(cmd, check=False)
"""Export current power plans."""
os.makedirs(r'{BackupDir}\Power Plans\{Date}'.format(
**global_vars), exist_ok=True)
plans = run_program(['powercfg', '/L'])
plans = plans.stdout.decode().splitlines()
plans = [p for p in plans if re.search(r'^Power Scheme', p)]
for p in plans:
guid = re.sub(r'Power Scheme GUID:\s+([0-9a-f\-]+).*', r'\1', p)
name = re.sub(
r'Power Scheme GUID:\s+[0-9a-f\-]+\s+\(([^\)]+)\).*', r'\1', p)
out = r'{BackupDir}\Power Plans\{Date}\{name}.pow'.format(
name=name, **global_vars)
if not os.path.exists(out):
cmd = ['powercfg', '-export', out, guid]
run_program(cmd, check=False)
def backup_registry(overwrite=False):
"""Backup registry including user hives."""
extract_item('erunt', silent=True)
cmd = [
global_vars['Tools']['ERUNT'],
r'{BackupDir}\Registry\{Date}'.format(**global_vars),
'sysreg',
'curuser',
'otherusers',
'/noprogresswindow']
if overwrite:
cmd.append('/noconfirmdelete')
run_program(cmd)
"""Backup registry including user hives."""
extract_item('erunt', silent=True)
cmd = [
global_vars['Tools']['ERUNT'],
r'{BackupDir}\Registry\{Date}'.format(**global_vars),
'sysreg',
'curuser',
'otherusers',
'/noprogresswindow']
if overwrite:
cmd.append('/noconfirmdelete')
run_program(cmd)
def get_folder_size(path):
"""Get (human-readable) size of folder passed, returns str."""
size = 'Unknown'
cmd = [global_vars['Tools']['Du'], '-c', '-nobanner', '-q', path]
"""Get (human-readable) size of folder passed, returns str."""
size = 'Unknown'
cmd = [global_vars['Tools']['Du'], '-c', '-nobanner', '-q', path]
try:
out = run_program(cmd)
except FileNotFoundError:
# Failed to find folder
pass
except subprocess.CalledProcessError:
# Failed to get folder size
pass
else:
try:
out = run_program(cmd)
except FileNotFoundError:
# Failed to find folder
pass
except subprocess.CalledProcessError:
# Failed to get folder size
pass
size = out.stdout.decode().split(',')[-2]
except IndexError:
# Failed to parse csv data
pass
else:
try:
size = out.stdout.decode().split(',')[-2]
except IndexError:
# Failed to parse csv data
pass
else:
size = human_readable_size(size)
return size
size = human_readable_size(size)
return size
def get_installed_antivirus():
"""Get list of installed Antivirus programs."""
programs = []
"""Get list of installed Antivirus programs."""
programs = []
cmd = ['WMIC', r'/namespace:\\root\SecurityCenter2',
'path', 'AntivirusProduct',
'get', 'displayName', '/value']
out = run_program(cmd)
out = out.stdout.decode().strip()
products = out.splitlines()
products = [p.split('=')[1] for p in products if p]
for prod in sorted(products):
# Get product state and check if it's enabled
# credit: https://jdhitsolutions.com/blog/powershell/5187/get-antivirus-product-status-with-powershell/
cmd = ['WMIC', r'/namespace:\\root\SecurityCenter2',
'path', 'AntivirusProduct',
'get', 'displayName', '/value']
'path', 'AntivirusProduct',
'where', 'displayName="{}"'.format(prod),
'get', 'productState', '/value']
out = run_program(cmd)
out = out.stdout.decode().strip()
products = out.splitlines()
products = [p.split('=')[1] for p in products if p]
for prod in sorted(products):
# Get product state and check if it's enabled
# credit: https://jdhitsolutions.com/blog/powershell/5187/get-antivirus-product-status-with-powershell/
cmd = ['WMIC', r'/namespace:\\root\SecurityCenter2',
'path', 'AntivirusProduct',
'where', 'displayName="{}"'.format(prod),
'get', 'productState', '/value']
out = run_program(cmd)
out = out.stdout.decode().strip()
state = out.split('=')[1]
state = hex(int(state))
if str(state)[3:5] != '10':
programs.append('[Disabled] {}'.format(prod))
else:
programs.append(prod)
state = out.split('=')[1]
state = hex(int(state))
if str(state)[3:5] != '10':
programs.append('[Disabled] {}'.format(prod))
else:
programs.append(prod)
if len(programs) == 0:
programs = ['No programs found']
return programs
if len(programs) == 0:
programs = ['No programs found']
return programs
def get_installed_office():
"""Get list of installed Office programs."""
programs = []
log_file = r'{LogDir}\Installed Program List (AIDA64).txt'.format(
**global_vars)
with open (log_file, 'r') as f:
for line in sorted(f.readlines()):
if REGEX_OFFICE.search(line):
programs.append(line[4:82].strip())
"""Get list of installed Office programs."""
programs = []
log_file = r'{LogDir}\Installed Program List (AIDA64).txt'.format(
**global_vars)
with open (log_file, 'r') as f:
for line in sorted(f.readlines()):
if REGEX_OFFICE.search(line):
programs.append(line[4:82].strip())
if len(programs) == 0:
programs = ['No programs found']
return programs
if len(programs) == 0:
programs = ['No programs found']
return programs
def get_shell_path(folder, user='current'):
"""Get shell path using SHGetKnownFolderPath via knownpaths, returns str.
"""Get shell path using knownpaths, returns str.
NOTE: Only works for the current user.
Code based on https://gist.github.com/mkropat/7550097
"""
path = None
folderid = None
if user.lower() == 'public':
user = 'common'
NOTE: Only works for the current user.
Code based on https://gist.github.com/mkropat/7550097
"""
path = None
folderid = None
if user.lower() == 'public':
user = 'common'
try:
folderid = getattr(knownpaths.FOLDERID, folder)
except AttributeError:
# Unknown folder ID, ignore and return None
pass
if folderid:
try:
folderid = getattr(knownpaths.FOLDERID, folder)
except AttributeError:
# Unknown folder ID, ignore and return None
pass
path = knownpaths.get_path(
folderid, getattr(knownpaths.UserHandle, user))
except PathNotFoundError:
# Folder not found, ignore and return None
pass
if folderid:
try:
path = knownpaths.get_path(folderid, getattr(knownpaths.UserHandle, user))
except PathNotFoundError:
# Folder not found, ignore and return None
pass
return path
return path
def get_user_data_paths(user):
"""Get user data paths for provided user, returns dict."""
hive_path = user['SID']
paths = {
'Profile': {
'Path': None,
},
'Shell Folders': {},
'Extra Folders': {},
}
unload_hive = False
"""Get user data paths for provided user, returns dict."""
hive_path = user['SID']
paths = {
'Profile': {
'Path': None,
},
'Shell Folders': {},
'Extra Folders': {},
}
unload_hive = False
if user['Name'] == global_vars['Env']['USERNAME']:
# We can use SHGetKnownFolderPath for the current user
paths['Profile']['Path'] = get_shell_path('Profile')
paths['Shell Folders'] = {f: {'Path': get_shell_path(f)}
for f in SHELL_FOLDERS.keys()}
else:
# We have to use the NTUSER.dat hives which isn't recommended by MS
try:
key_path = r'{}\{}'.format(REG_PROFILE_LIST, user['SID'])
with winreg.OpenKey(HKLM, key_path) as key:
paths['Profile']['Path'] = winreg.QueryValueEx(
key, 'ProfileImagePath')[0]
except Exception:
# Profile path not found, leaving as None.
pass
if user['Name'] == global_vars['Env']['USERNAME']:
# We can use SHGetKnownFolderPath for the current user
paths['Profile']['Path'] = get_shell_path('Profile')
paths['Shell Folders'] = {f: {'Path': get_shell_path(f)}
for f in SHELL_FOLDERS.keys()}
else:
# We have to use the NTUSER.dat hives which isn't recommended by MS
try:
key_path = r'{}\{}'.format(REG_PROFILE_LIST, user['SID'])
with winreg.OpenKey(HKLM, key_path) as key:
paths['Profile']['Path'] = winreg.QueryValueEx(
key, 'ProfileImagePath')[0]
except Exception:
# Profile path not found, leaving as None.
pass
# Shell folders (Prep)
if not reg_path_exists(HKU, hive_path) and paths['Profile']['Path']:
# User not logged-in, loading hive
# Also setting unload_hive so it will be unloaded later.
hive_path = TMP_HIVE_PATH
cmd = ['reg', 'load', r'HKU\{}'.format(TMP_HIVE_PATH),
r'{}\NTUSER.DAT'.format(paths['Profile']['Path'])]
unload_hive = True
# Shell folders (Prep)
if not reg_path_exists(HKU, hive_path) and paths['Profile']['Path']:
# User not logged-in, loading hive
# Also setting unload_hive so it will be unloaded later.
hive_path = TMP_HIVE_PATH
cmd = ['reg', 'load', r'HKU\{}'.format(TMP_HIVE_PATH),
r'{}\NTUSER.DAT'.format(paths['Profile']['Path'])]
unload_hive = True
try:
run_program(cmd)
except subprocess.CalledProcessError:
# Failed to load user hive
pass
# Shell folders
shell_folders = r'{}\{}'.format(hive_path, REG_SHELL_FOLDERS)
if (reg_path_exists(HKU, hive_path)
and reg_path_exists(HKU, shell_folders)):
with winreg.OpenKey(HKU, shell_folders) as key:
for folder, values in SHELL_FOLDERS.items():
for value in values:
try:
run_program(cmd)
except subprocess.CalledProcessError:
# Failed to load user hive
pass
path = winreg.QueryValueEx(key, value)[0]
except FileNotFoundError:
# Skip missing values
pass
else:
paths['Shell Folders'][folder] = {'Path': path}
# Stop checking values for this folder
break
# Shell folders
shell_folders = r'{}\{}'.format(hive_path, REG_SHELL_FOLDERS)
if (reg_path_exists(HKU, hive_path)
and reg_path_exists(HKU, shell_folders)):
with winreg.OpenKey(HKU, shell_folders) as key:
for folder, values in SHELL_FOLDERS.items():
for value in values:
try:
path = winreg.QueryValueEx(key, value)[0]
except FileNotFoundError:
# Skip missing values
pass
else:
paths['Shell Folders'][folder] = {'Path': path}
# Stop checking values for this folder
break
# Shell folder (extra check)
if paths['Profile']['Path']:
for folder in SHELL_FOLDERS.keys():
folder_path = r'{Path}\{folder}'.format(
folder=folder, **paths['Profile'])
if (folder not in paths['Shell Folders']
and os.path.exists(folder_path)):
paths['Shell Folders'][folder] = {'Path': folder_path}
# Extra folders
# Shell folder (extra check)
if paths['Profile']['Path']:
for folder in EXTRA_FOLDERS:
folder_path = r'{Path}\{folder}'.format(
folder=folder, **paths['Profile'])
if os.path.exists(folder_path):
paths['Extra Folders'][folder] = {'Path': folder_path}
for folder in SHELL_FOLDERS.keys():
folder_path = r'{Path}\{folder}'.format(
folder=folder, **paths['Profile'])
if (folder not in paths['Shell Folders']
and os.path.exists(folder_path)):
paths['Shell Folders'][folder] = {'Path': folder_path}
# Shell folders (cleanup)
if unload_hive:
cmd = ['reg', 'unload', r'HKU\{}'.format(TMP_HIVE_PATH)]
run_program(cmd, check=False)
# Extra folders
if paths['Profile']['Path']:
for folder in EXTRA_FOLDERS:
folder_path = r'{Path}\{folder}'.format(
folder=folder, **paths['Profile'])
if os.path.exists(folder_path):
paths['Extra Folders'][folder] = {'Path': folder_path}
# Shell folders (cleanup)
if unload_hive:
cmd = ['reg', 'unload', r'HKU\{}'.format(TMP_HIVE_PATH)]
run_program(cmd, check=False)
# Done
return paths
# Done
return paths
def get_user_folder_sizes(users):
"""Update list(users) to include folder paths and sizes."""
extract_item('du', filter='du*', silent=True)
# Configure Du
winreg.CreateKey(HKCU, r'Software\Sysinternals\Du')
with winreg.OpenKey(HKCU,
r'Software\Sysinternals\Du', access=winreg.KEY_WRITE) as key:
winreg.SetValueEx(key, 'EulaAccepted', 0, winreg.REG_DWORD, 1)
"""Update list(users) to include folder paths and sizes."""
extract_item('du', filter='du*', silent=True)
# Configure Du
winreg.CreateKey(HKCU, r'Software\Sysinternals\Du')
with winreg.OpenKey(HKCU,
r'Software\Sysinternals\Du', access=winreg.KEY_WRITE) as key:
winreg.SetValueEx(key, 'EulaAccepted', 0, winreg.REG_DWORD, 1)
for u in users:
u.update(get_user_data_paths(u))
if u['Profile']['Path']:
u['Profile']['Size'] = get_folder_size(u['Profile']['Path'])
for folder in u['Shell Folders'].keys():
u['Shell Folders'][folder]['Size'] = get_folder_size(
u['Shell Folders'][folder]['Path'])
for folder in u['Extra Folders'].keys():
u['Extra Folders'][folder]['Size'] = get_folder_size(
u['Extra Folders'][folder]['Path'])
for u in users:
u.update(get_user_data_paths(u))
if u['Profile']['Path']:
u['Profile']['Size'] = get_folder_size(u['Profile']['Path'])
for folder in u['Shell Folders'].keys():
u['Shell Folders'][folder]['Size'] = get_folder_size(
u['Shell Folders'][folder]['Path'])
for folder in u['Extra Folders'].keys():
u['Extra Folders'][folder]['Size'] = get_folder_size(
u['Extra Folders'][folder]['Path'])
def get_user_list():
"""Get user list via WMIC, returns list of dicts."""
users = []
"""Get user list via WMIC, returns list of dicts."""
users = []
# Get user info from WMI
cmd = ['wmic', 'useraccount', 'get', '/format:csv']
try:
out = run_program(cmd)
except subprocess.CalledProcessError:
# Meh, return empty list to avoid a full crash
return users
entries = out.stdout.decode().splitlines()
entries = [e.strip().split(',') for e in entries if e.strip()]
# Add user(s) to dict
keys = entries[0]
for e in entries[1:]:
# Create dict using 1st line (keys)
e = dict(zip(keys, e))
# Set Active status via 'Disabled' TRUE/FALSE str
e['Active'] = bool(e['Disabled'].upper() == 'FALSE')
# Assume SIDs ending with 1000+ are "Standard" and others are "System"
e['Type'] = 'Standard' if re.search(r'-1\d+$', e['SID']) else 'System'
users.append(e)
# Sort list
users.sort(key=itemgetter('Name'))
# Done
# Get user info from WMI
cmd = ['wmic', 'useraccount', 'get', '/format:csv']
try:
out = run_program(cmd)
except subprocess.CalledProcessError:
# Meh, return empty list to avoid a full crash
return users
entries = out.stdout.decode().splitlines()
entries = [e.strip().split(',') for e in entries if e.strip()]
# Add user(s) to dict
keys = entries[0]
for e in entries[1:]:
# Create dict using 1st line (keys)
e = dict(zip(keys, e))
# Set Active status via 'Disabled' TRUE/FALSE str
e['Active'] = bool(e['Disabled'].upper() == 'FALSE')
# Assume SIDs ending with 1000+ are "Standard" and others are "System"
e['Type'] = 'Standard' if re.search(r'-1\d+$', e['SID']) else 'System'
users.append(e)
# Sort list
users.sort(key=itemgetter('Name'))
# Done
return users
def reg_path_exists(hive, path):
"""Test if specified path exists, returns bool."""
try:
winreg.QueryValue(hive, path)
except FileNotFoundError:
return False
else:
return True
"""Test if specified path exists, returns bool."""
try:
winreg.QueryValue(hive, path)
except FileNotFoundError:
return False
else:
return True
def run_aida64():
"""Run AIDA64 to save system reports."""
extract_item('AIDA64', silent=True)
# All system info
config = r'{BinDir}\AIDA64\full.rpf'.format(**global_vars)
report_file = r'{LogDir}\System Information (AIDA64).html'.format(
**global_vars)
if not os.path.exists(report_file):
cmd = [
global_vars['Tools']['AIDA64'],
'/R', report_file,
'/CUSTOM', config,
'/HTML', '/SILENT', '/SAFEST']
run_program(cmd, check=False)
"""Run AIDA64 to save system reports."""
extract_item('AIDA64', silent=True)
# All system info
config = r'{BinDir}\AIDA64\full.rpf'.format(**global_vars)
report_file = r'{LogDir}\System Information (AIDA64).html'.format(
**global_vars)
if not os.path.exists(report_file):
cmd = [
global_vars['Tools']['AIDA64'],
'/R', report_file,
'/CUSTOM', config,
'/HTML', '/SILENT', '/SAFEST']
run_program(cmd, check=False)
# Installed Programs
config = r'{BinDir}\AIDA64\installed_programs.rpf'.format(**global_vars)
report_file = r'{LogDir}\Installed Program List (AIDA64).txt'.format(
**global_vars)
if not os.path.exists(report_file):
cmd = [
global_vars['Tools']['AIDA64'],
'/R', report_file,
'/CUSTOM', config,
'/TEXT', '/SILENT', '/SAFEST']
run_program(cmd, check=False)
# Installed Programs
config = r'{BinDir}\AIDA64\installed_programs.rpf'.format(**global_vars)
report_file = r'{LogDir}\Installed Program List (AIDA64).txt'.format(
**global_vars)
if not os.path.exists(report_file):
cmd = [
global_vars['Tools']['AIDA64'],
'/R', report_file,
'/CUSTOM', config,
'/TEXT', '/SILENT', '/SAFEST']
run_program(cmd, check=False)
# Product Keys
config = r'{BinDir}\AIDA64\licenses.rpf'.format(**global_vars)
report_file = r'{LogDir}\Product Keys (AIDA64).txt'.format(**global_vars)
if not os.path.exists(report_file):
cmd = [
global_vars['Tools']['AIDA64'],
'/R', report_file,
'/CUSTOM', config,
'/TEXT', '/SILENT', '/SAFEST']
run_program(cmd, check=False)
# Product Keys
config = r'{BinDir}\AIDA64\licenses.rpf'.format(**global_vars)
report_file = r'{LogDir}\Product Keys (AIDA64).txt'.format(**global_vars)
if not os.path.exists(report_file):
cmd = [
global_vars['Tools']['AIDA64'],
'/R', report_file,
'/CUSTOM', config,
'/TEXT', '/SILENT', '/SAFEST']
run_program(cmd, check=False)
def run_bleachbit(cleaners=None, preview=True):
"""Run BleachBit preview and save log.
"""Run BleachBit preview and save log.
If preview is True then no files should be deleted."""
error_path = r'{}\Tools\BleachBit.err'.format(global_vars['LogDir'])
log_path = error_path.replace('err', 'log')
extract_item('BleachBit', silent=True)
If preview is True then no files should be deleted."""
error_path = r'{}\Tools\BleachBit.err'.format(global_vars['LogDir'])
log_path = error_path.replace('err', 'log')
extract_item('BleachBit', silent=True)
# Safety check
if not cleaners:
# Disable cleaning and use preset config
cleaners = ['--preset']
preview = True
# Safety check
if not cleaners:
# Disable cleaning and use preset config
cleaners = ['--preset']
preview = True
# Run
cmd = [
global_vars['Tools']['BleachBit'],
'--preview' if preview else '--clean']
cmd.extend(cleaners)
out = run_program(cmd, check=False)
# Run
cmd = [
global_vars['Tools']['BleachBit'],
'--preview' if preview else '--clean']
cmd.extend(cleaners)
out = run_program(cmd, check=False)
# Save stderr
if out.stderr.decode().splitlines():
with open(error_path, 'a', encoding='utf-8') as f:
for line in out.stderr.decode().splitlines():
f.write(line.strip() + '\n')
# Save stderr
if out.stderr.decode().splitlines():
with open(error_path, 'a', encoding='utf-8') as f:
for line in out.stderr.decode().splitlines():
f.write(line.strip() + '\n')
# Save stdout
with open(log_path, 'a', encoding='utf-8') as f:
for line in out.stdout.decode().splitlines():
f.write(line.strip() + '\n')
# Save stdout
with open(log_path, 'a', encoding='utf-8') as f:
for line in out.stdout.decode().splitlines():
f.write(line.strip() + '\n')
def show_disk_usage(disk):
"""Show free and used space for a specified disk."""
print_standard('{:5}'.format(disk.device.replace('/', ' ')),
end='', flush=True, timestamp=False)
try:
usage = psutil.disk_usage(disk.device)
display_string = '{percent:>5.2f}% Free ({free} / {total})'.format(
percent = 100 - usage.percent,
free = human_readable_size(usage.free, 2),
total = human_readable_size(usage.total, 2))
if usage.percent > 85:
print_error(display_string, timestamp=False)
elif usage.percent > 75:
print_warning(display_string, timestamp=False)
else:
print_standard(display_string, timestamp=False)
except Exception:
print_warning('Unknown', timestamp=False)
"""Show free and used space for a specified disk."""
print_standard('{:5}'.format(disk.device.replace('/', ' ')),
end='', flush=True, timestamp=False)
try:
usage = psutil.disk_usage(disk.device)
display_string = '{percent:>5.2f}% Free ({free} / {total})'.format(
percent = 100 - usage.percent,
free = human_readable_size(usage.free, 2),
total = human_readable_size(usage.total, 2))
if usage.percent > 85:
print_error(display_string, timestamp=False)
elif usage.percent > 75:
print_warning(display_string, timestamp=False)
else:
print_standard(display_string, timestamp=False)
except Exception:
print_warning('Unknown', timestamp=False)
def show_free_space(indent=8, width=32):
"""Show free space info for all fixed disks."""
message = 'Free Space:'
for disk in psutil.disk_partitions():
try:
if 'fixed' in disk.opts:
try_and_print(message=message, function=show_disk_usage,
ns='Unknown', silent_function=False,
indent=indent, width=width, disk=disk)
message = ''
except Exception:
pass
"""Show free space info for all fixed disks."""
message = 'Free Space:'
for disk in psutil.disk_partitions():
try:
if 'fixed' in disk.opts:
try_and_print(message=message, function=show_disk_usage,
ns='Unknown', silent_function=False,
indent=indent, width=width, disk=disk)
message = ''
except Exception:
pass
def show_installed_ram():
"""Show installed RAM."""
mem = psutil.virtual_memory()
if mem.total > 5905580032:
# > 5.5 Gb so 6Gb or greater
print_standard(human_readable_size(mem.total).strip(), timestamp=False)
elif mem.total > 3758096384:
# > 3.5 Gb so 4Gb or greater
print_warning(human_readable_size(mem.total).strip(), timestamp=False)
else:
print_error(human_readable_size(mem.total).strip(), timestamp=False)
"""Show installed RAM."""
mem = psutil.virtual_memory()
if mem.total > 5905580032:
# > 5.5 Gb so 6Gb or greater
print_standard(human_readable_size(mem.total).strip(), timestamp=False)
elif mem.total > 3758096384:
# > 3.5 Gb so 4Gb or greater
print_warning(human_readable_size(mem.total).strip(), timestamp=False)
else:
print_error(human_readable_size(mem.total).strip(), timestamp=False)
def show_os_activation():
"""Show OS activation info."""
act_str = get_activation_string()
if windows_is_activated():
print_standard(act_str, timestamp=False)
elif re.search(r'unavailable', act_str, re.IGNORECASE):
print_warning(act_str, timestamp=False)
else:
print_error(act_str, timestamp=False)
"""Show OS activation info."""
act_str = get_activation_string()
if windows_is_activated():
print_standard(act_str, timestamp=False)
elif re.search(r'unavailable', act_str, re.IGNORECASE):
print_warning(act_str, timestamp=False)
else:
print_error(act_str, timestamp=False)
def show_os_name():
"""Show extended OS name (including warnings)."""
os_name = global_vars['OS']['DisplayName']
if global_vars['OS']['Arch'] == 32:
# Show all 32-bit installs as an error message
print_error(os_name, timestamp=False)
"""Show extended OS name (including warnings)."""
os_name = global_vars['OS']['DisplayName']
if global_vars['OS']['Arch'] == 32:
# Show all 32-bit installs as an error message
print_error(os_name, timestamp=False)
else:
if re.search(
r'(preview build|unrecognized|unsupported)',
os_name,
re.IGNORECASE):
print_error(os_name, timestamp=False)
elif re.search(r'outdated', os_name, re.IGNORECASE):
print_warning(os_name, timestamp=False)
else:
if re.search(r'(preview build|unrecognized|unsupported)', os_name, re.IGNORECASE):
print_error(os_name, timestamp=False)
elif re.search(r'outdated', os_name, re.IGNORECASE):
print_warning(os_name, timestamp=False)
else:
print_standard(os_name, timestamp=False)
print_standard(os_name, timestamp=False)
def show_temp_files_size():
"""Show total size of temp files identified by BleachBit."""
size = None
with open(r'{LogDir}\Tools\BleachBit.log'.format(**global_vars), 'r') as f:
for line in f.readlines():
if re.search(r'^disk space to be recovered:', line, re.IGNORECASE):
size = re.sub(r'.*: ', '', line.strip())
size = re.sub(r'(\w)iB$', r' \1b', size)
if size is None:
print_warning(size, timestamp=False)
else:
print_standard(size, timestamp=False)
"""Show total size of temp files identified by BleachBit."""
size = None
with open(r'{LogDir}\Tools\BleachBit.log'.format(**global_vars), 'r') as f:
for line in f.readlines():
if re.search(r'^disk space to be recovered:', line, re.IGNORECASE):
size = re.sub(r'.*: ', '', line.strip())
size = re.sub(r'(\w)iB$', r' \1b', size)
if size is None:
print_warning(size, timestamp=False)
else:
print_standard(size, timestamp=False)
def show_user_data_summary(indent=8, width=32):
"""Print user data folder sizes for all users."""
users = get_user_list()
users = [u for u in users if u['Active']]
get_user_folder_sizes(users)
for user in users:
if ('Size' not in user['Profile']
and not any(user['Shell Folders'])
and not any(user['Extra Folders'])):
# Skip empty users
continue
print_success('{indent}User: {user}'.format(
indent = ' '*int(indent/2),
user = user['Name']))
for section in ['Profile', None, 'Shell Folders', 'Extra Folders']:
folders = []
if section is None:
# Divider
print_standard('{}{}'.format(' '*indent, '-'*(width+6)))
elif section == 'Profile':
folders = {'Profile': user['Profile']}
else:
folders = user[section]
for folder in folders:
print_standard(
'{indent}{folder:<{width}}{size:>6} ({path})'.format(
indent = ' ' * indent,
width = width,
folder = folder,
size = folders[folder].get('Size', 'Unknown'),
path = folders[folder].get('Path', 'Unknown')))
"""Print user data folder sizes for all users."""
users = get_user_list()
users = [u for u in users if u['Active']]
get_user_folder_sizes(users)
for user in users:
if ('Size' not in user['Profile']
and not any(user['Shell Folders'])
and not any(user['Extra Folders'])):
# Skip empty users
continue
print_success('{indent}User: {user}'.format(
indent = ' '*int(indent/2),
user = user['Name']))
for section in ['Profile', None, 'Shell Folders', 'Extra Folders']:
folders = []
if section is None:
# Divider
print_standard('{}{}'.format(' '*indent, '-'*(width+6)))
elif section == 'Profile':
folders = {'Profile': user['Profile']}
else:
folders = user[section]
for folder in folders:
print_standard(
'{indent}{folder:<{width}}{size:>6} ({path})'.format(
indent = ' ' * indent,
width = width,
folder = folder,
size = folders[folder].get('Size', 'Unknown'),
path = folders[folder].get('Path', 'Unknown')))
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -6,67 +6,71 @@ import os
import shutil
import sys
# Init
os.chdir(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(os.getcwd())
from functions.common import *
# REGEX
REGEX_VALID_IP = re.compile(
r'(10.\d+.\d+.\d+'
r'|172.(1[6-9]|2\d|3[0-1])'
r'|192.168.\d+.\d+)',
re.IGNORECASE)
r'(10.\d+.\d+.\d+'
r'|172.(1[6-9]|2\d|3[0-1])'
r'|192.168.\d+.\d+)',
re.IGNORECASE)
def connect_to_network():
"""Connect to network if not already connected."""
net_ifs = psutil.net_if_addrs()
net_ifs = [i[:2] for i in net_ifs.keys()]
"""Connect to network if not already connected."""
net_ifs = psutil.net_if_addrs()
net_ifs = [i[:2] for i in net_ifs.keys()]
# Bail if currently connected
if is_connected():
return
# Bail if currently connected
if is_connected():
return
# WiFi
if 'wl' in net_ifs:
cmd = [
'nmcli', 'dev', 'wifi',
'connect', WIFI_SSID,
'password', WIFI_PASSWORD]
try_and_print(
message = 'Connecting to {}...'.format(WIFI_SSID),
function = run_program,
cmd = cmd)
# WiFi
if 'wl' in net_ifs:
cmd = [
'nmcli', 'dev', 'wifi',
'connect', WIFI_SSID,
'password', WIFI_PASSWORD]
try_and_print(
message = 'Connecting to {}...'.format(WIFI_SSID),
function = run_program,
cmd = cmd)
def is_connected():
"""Check for a valid private IP."""
devs = psutil.net_if_addrs()
for dev in devs.values():
for family in dev:
if REGEX_VALID_IP.search(family.address):
# Valid IP found
return True
# Else
return False
"""Check for a valid private IP."""
devs = psutil.net_if_addrs()
for dev in devs.values():
for family in dev:
if REGEX_VALID_IP.search(family.address):
# Valid IP found
return True
# Else
return False
def show_valid_addresses():
"""Show all valid private IP addresses assigned to the system."""
devs = psutil.net_if_addrs()
for dev, families in sorted(devs.items()):
for family in families:
if REGEX_VALID_IP.search(family.address):
# Valid IP found
show_data(message=dev, data=family.address)
"""Show all valid private IP addresses assigned to the system."""
devs = psutil.net_if_addrs()
for dev, families in sorted(devs.items()):
for family in families:
if REGEX_VALID_IP.search(family.address):
# Valid IP found
show_data(message=dev, data=family.address)
def speedtest():
"""Run a network speedtest using speedtest-cli."""
result = run_program(['speedtest-cli', '--simple'])
output = [line.strip() for line in result.stdout.decode().splitlines()
if line.strip()]
output = [line.split() for line in output]
output = [(a, float(b), c) for a, b, c in output]
return ['{:10}{:6.2f} {}'.format(*line) for line in output]
"""Run a network speedtest using speedtest-cli."""
result = run_program(['speedtest-cli', '--simple'])
output = [line.strip() for line in result.stdout.decode().splitlines()
if line.strip()]
output = [line.split() for line in output]
output = [(a, float(b), c) for a, b, c in output]
return ['{:10}{:6.2f} {}'.format(*line) for line in output]
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -1,326 +0,0 @@
# Wizard Kit: Functions - PARTITION UIDs
# sources: https://en.wikipedia.org/wiki/GUID_Partition_Table
# https://en.wikipedia.org/wiki/Partition_type
# NOTE: Info has been trimmed for brevity. As such, there may be some inaccuracy.
PARTITION_UIDS = {
'00': {'OS': 'All','Description': 'Empty partition entry'},
'01': {'OS': 'DOS','Description': 'FAT12 as primary partition'},
'02': {'OS': 'XENIX','Description': 'XENIX root'},
'03': {'OS': 'XENIX','Description': 'XENIX usr'},
'04': {'OS': 'DOS','Description': 'FAT16 with less than 32 MB'},
'05': {'OS': 'DOS / SpeedStor','Description': 'Extended partition'},
'06': {'OS': 'DOS1+','Description': 'FAT16B [over 65K sectors]'},
'07': {'OS': 'Windows / OS/2 / QNX 2','Description': 'NTFS/exFAT/HPFS/IFS/QNX'},
'08': {'OS': 'CBM / DOS / OS/2 / AIX /QNX','Description': 'FAT12-16/AIX/QNY/SplitDrive'},
'09': {'OS': 'AIX / QNX / Coherent / OS-9','Description': 'AIX/QNZ/Coherent/RBF'},
'0A': {'OS': 'OS/2 / Coherent','Description': 'Boot Manager / Swap'},
'0B': {'OS': 'DOS','Description': 'FAT32 with CHS addressing'},
'0C': {'OS': 'DOS','Description': 'FAT32 with LBA'},
'0D': {'OS': 'Silicon Safe','Description': 'Reserved'},
'0E': {'OS': 'DOS','Description': 'FAT16B with LBA'},
'0F': {'OS': 'DOS','Description': 'Extended partition with LBA'},
'10': {'OS': 'OPUS','Description': 'Unknown'},
'11': {'OS': 'Leading Edge MS-DOS / OS/2','Description': 'FAT12/FAT16'},
'12': {'OS': 'Compaq Contura','Description': 'conf/diag/hiber/rescue/serv'},
'14': {'OS': 'AST DOS / OS/2 / MaverickOS','Description': 'FAT12/FAT16/Omega'},
'15': {'OS': 'OS/2 / Maverick OS','Description': 'Hidden extended / Swap'},
'16': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT16B'},
'17': {'OS': 'OS/2 Boot Manager','Description': 'Hidden IFS/HPFS/NTFS/exFAT'},
'18': {'OS': 'AST Windows','Description': '0-Volt Suspend/SmartSleep'},
'19': {'OS': 'Willowtech Photon coS','Description': 'Willowtech Photon coS'},
'1B': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT32'},
'1C': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT32 with LBA'},
'1E': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT16 with LBA'},
'1F': {'OS': 'OS/2 Boot Manager','Description': 'Hidden extended with LBA'},
'20': {'OS': 'Windows Mobile','Description': 'update XIP/Willowsoft OFS1'},
'21': {'OS': 'Oxygen','Description': 'SpeedStor / FSo2'},
'22': {'OS': 'Oxygen','Description': 'Oxygen Extended Partition'},
'23': {'OS': 'Windows Mobile','Description': 'Reserved / boot XIP'},
'24': {'OS': 'NEC MS-DOS0','Description': 'Logical FAT12 or FAT16'},
'25': {'OS': 'Windows Mobile','Description': 'IMGFS[citation needed]'},
'26': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'27': {'OS': 'Win/PQserv/MirOS/RooterBOOT','Description': 'WinRE/Rescue/MirOS/RooterBOOT'},
'2A': {'OS': 'AtheOS','Description': 'AthFS/AFS/Reserved'},
'2B': {'OS': 'SyllableOS','Description': 'SyllableSecure (SylStor)'},
'31': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'32': {'OS': 'NOS','Description': 'Unknown'},
'33': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'34': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'35': {'OS': 'OS/2 Server /eComStation','Description': 'JFS'},
'36': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'38': {'OS': 'THEOS','Description': 'THEOS version 3.2, 2 GB'},
'39': {'OS': 'Plan 9 / THEOS','Description': 'Plan 9 edition 3 / THEOS v4'},
'3A': {'OS': 'THEOS','Description': 'THEOS v4, 4 GB'},
'3B': {'OS': 'THEOS','Description': 'THEOS v4 extended'},
'3C': {'OS': 'PartitionMagic','Description': 'PqRP (image in progress)'},
'3D': {'OS': 'PartitionMagic','Description': 'Hidden NetWare'},
'3F': {'OS': 'OS/32','Description': 'Unknown'},
'40': {'OS': 'PICK / Venix','Description': 'PICK R83 / Venix 80286'},
'41': {'OS': 'RISC / Linux / PowerPC','Description': 'Boot / Old Linux/Minix'},
'42': {'OS': 'SFS / Linux / Win2K/XP/etc','Description': 'SFS / Old Linux Swap'},
'43': {'OS': 'Linux','Description': 'Old Linux native'},
'44': {'OS': 'GoBack','Description': 'Norton/WildFire/Adaptec/Roxio'},
'45': {'OS': 'Boot-US / EUMEL/ELAN','Description': 'Priam/Boot/EUMEL/ELAN (L2)'},
'46': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2)'},
'47': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2)'},
'48': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2), ERGOS L3'},
'4A': {'OS': 'AdaOS / ALFS/THIN','Description': 'Aquila / ALFS/THIN'},
'4C': {'OS': 'ETH Oberon','Description': 'Aos (A2) file system (76)'},
'4D': {'OS': 'QNX Neutrino','Description': 'Primary QNX POSIX volume'},
'4E': {'OS': 'QNX Neutrino','Description': 'Secondary QNX POSIX volume'},
'4F': {'OS': 'QNX Neutrino / ETH Oberon','Description': '3rd QNX POSIX/Boot/Native'},
'50': {'OS': 'DiskMan4/ETH/LynxOS/Novell','Description': 'Alt FS/Read-only/Lynx RTOS'},
'51': {'OS': 'Disk Manager 4-6','Description': 'R/W partition (Aux 1)'},
'52': {'OS': 'CP/M-80/ System V/AT, V/386','Description': 'CP/M-80'},
'53': {'OS': 'Disk Manager 6','Description': 'Auxiliary 3 (WO)'},
'54': {'OS': 'Disk Manager 6','Description': 'Dynamic Drive Overlay (DDO)'},
'55': {'OS': 'EZ-Drive','Description': 'Maxtor/MaxBlast/DriveGuide'},
'56': {'OS': 'AT&T DOS/EZ-Drive/VFeature','Description': 'FAT12~16/EZ-BIOS/VFeature'},
'57': {'OS': 'DrivePro','Description': 'VNDI partition'},
'5C': {'OS': 'EDISK','Description': 'Priam EDisk Volume'},
'61': {'OS': 'SpeedStor','Description': 'Unknown'},
'63': {'OS': 'Unix','Description': 'Unix,ISC,SysV,ix,BSD,HURD'},
'64': {'OS': 'SpeedStor / NetWare','Description': 'NetWare FS 286/2,PC-ARMOUR'},
'65': {'OS': 'NetWare','Description': 'NetWare File System 386'},
'66': {'OS': 'NetWare / NetWare','Description': 'NetWare FS 386 / SMS'},
'67': {'OS': 'NetWare','Description': 'Wolf Mountain'},
'68': {'OS': 'NetWare','Description': 'Unknown'},
'69': {'OS': 'NetWare 5 / NetWare','Description': 'Novell Storage Services'},
'6E': {'Description': 'Unknown'},
'70': {'OS': 'DiskSecure','Description': 'DiskSecure multiboot'},
'71': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'72': {'OS': 'APTI systems / Unix V7/x86','Description': 'APTI altFAT12 / V7 / x86'},
'73': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'74': {'OS': 'Microsoft, IBM','Description': 'Reserved / Scramdisk'},
'75': {'OS': 'PC/IX','Description': 'Unknown'},
'76': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'77': {'OS': 'Novell','Description': 'VNDI, M2FS, M2CS'},
'78': {'OS': 'Geurt Vos','Description': 'XOSL bootloader file system'},
'79': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16 (CHS, SFN)'},
'7A': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16 (LBA, SFN)'},
'7B': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16B (CHS, SFN)'},
'7C': {'OS': 'APTI conformant systems','Description': 'APTI altFAT32 (LBA, SFN)'},
'7D': {'OS': 'APTI conformant systems','Description': 'APTI altFAT32 (CHS, SFN)'},
'7E': {'OS': 'F.I.X. (claim) / PrimoCache','Description': 'Level 2 cache'},
'7F': {'OS': 'Varies','Description': 'AltOS DevPartition Standard'},
'80': {'OS': 'Minix 1.1-1.4a','Description': 'Minix file system (old)'},
'81': {'OS': 'Minix 1.4b+ / Linux','Description': 'MINIX FS/Mitac AdvDiskManager'},
'82': {'OS': 'Linux / Sun Microsystems','Description': 'Swap / Solaris x86 / Prime'},
'83': {'OS': 'GNU/Linux','Description': 'Any native Linux FS'},
'84': {'OS': 'OS/2 / Windows 7','Description': 'Hibernat/HiddenC/RapidStart'},
'85': {'OS': 'GNU/Linux','Description': 'Linux extended'},
'86': {'OS': 'Windows NT 4 Server / Linux','Description': 'FAT16B mirror/LinuxRAID-old'},
'87': {'OS': 'Windows NT 4 Server','Description': 'HPFS/NTFS mirrored volume'},
'88': {'OS': 'GNU/Linux','Description': 'Plaintext partition table'},
'8A': {'OS': 'AiR-BOOT','Description': 'Linux kernel image'},
'8B': {'OS': 'Windows NT 4 Server','Description': 'FAT32 mirrored volume set'},
'8C': {'OS': 'Windows NT 4 Server','Description': 'FAT32 mirrored volume set'},
'8D': {'OS': 'Free FDISK','Description': 'Hidden FAT12'},
'8E': {'OS': 'Linux','Description': 'Linux LVM'},
'90': {'OS': 'Free FDISK','Description': 'Hidden FAT16'},
'91': {'OS': 'Free FDISK','Description': 'Hidden extended partition'},
'92': {'OS': 'Free FDISK','Description': 'Hidden FAT16B'},
'93': {'OS': 'Amoeba / Linux','Description': 'Amoeba native/Hidden Linux'},
'94': {'OS': 'Amoeba','Description': 'Amoeba bad block table'},
'95': {'OS': 'EXOPC','Description': 'EXOPC native'},
'96': {'OS': 'CHRP','Description': 'ISO-9660 file system'},
'97': {'OS': 'Free FDISK','Description': 'Hidden FAT32'},
'98': {'OS': 'Free FDISK / ROM-DOS','Description': 'Hidden FAT32 / service part'},
'99': {'OS': 'early Unix','Description': 'Unknown'},
'9A': {'OS': 'Free FDISK','Description': 'Hidden FAT16'},
'9B': {'OS': 'Free FDISK','Description': 'Hidden extended partition'},
'9E': {'OS': 'VSTA / ForthOS','Description': 'ForthOS (eForth port)'},
'9F': {'OS': 'BSD/OS 3.0+, BSDI','Description': 'Unknown'},
'A0': {'OS': 'HP/Phoenix/IBM/Toshiba/Sony','Description': 'Diagnostic for HP/Hibernate'},
'A1': {'OS': 'HP / Phoenix, NEC','Description': 'HP Vol Expansion/Hibernate'},
'A2': {'OS': 'Cyclone V','Description': 'Hard Processor System (HPS)'},
'A3': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'},
'A4': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'},
'A5': {'OS': 'BSD','Description': 'BSD slice'},
'A6': {'OS': 'OpenBSD','Description': 'HP Vol Expansion/BSD slice'},
'A7': {'OS': 'NeXT','Description': 'NeXTSTEP'},
'A8': {'OS': 'Darwin, Mac OS X','Description': 'Apple Darwin, Mac OS X UFS'},
'A9': {'OS': 'NetBSD','Description': 'NetBSD slice'},
'AA': {'OS': 'MS-DOS','Description': 'Olivetti DOS FAT12(1.44 MB)'},
'AB': {'OS': 'Darwin, Mac OS X / GO! OS','Description': 'Apple Darwin/OS X boot/GO!'},
'AD': {'OS': 'RISC OS','Description': 'ADFS / FileCore format'},
'AE': {'OS': 'ShagOS','Description': 'ShagOS file system'},
'AF': {'OS': 'ShagOS','Description': 'OS X HFS & HFS+/ShagOS Swap'},
'B0': {'OS': 'Boot-Star','Description': 'Boot-Star dummy partition'},
'B1': {'OS': 'QNX 6.x','Description': 'HPVolExpansion/QNX Neutrino'},
'B2': {'OS': 'QNX 6.x','Description': 'QNX Neutrino power-safe FS'},
'B3': {'OS': 'QNX 6.x','Description': 'HPVolExpansion/QNX Neutrino'},
'B4': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'},
'B6': {'OS': 'Windows NT 4 Server','Description': 'HPVolExpansion/FAT16Bmirror'},
'B7': {'OS': 'BSDI / Windows NT 4 Server','Description': 'BSDI,Swap,HPFS/NTFS mirror'},
'B8': {'OS': 'BSDI (before 3.0)','Description': 'BSDI Swap / native FS'},
'BB': {'OS': 'Acronis/BootWizard/WinNT 4','Description': 'BootWizard/OEM/FAT32 mirror'},
'BC': {'OS': 'Acronis/WinNT/BackupCapsule','Description': 'FAT32RAID/SecureZone/Backup'},
'BD': {'OS': 'BonnyDOS/286','Description': 'Unknown'},
'BE': {'OS': 'Solaris 8','Description': 'Solaris 8 boot'},
'BF': {'OS': 'Solaris','Description': 'Solaris x86'},
'C0': {'OS': 'DR-DOS,MultiuserDOS,REAL/32','Description': 'Secured FAT (under 32 MB)'},
'C1': {'OS': 'DR DOS','Description': 'Secured FAT12'},
'C2': {'OS': 'Power Boot','Description': 'Hidden Linux native FS'},
'C3': {'OS': 'Power Boot','Description': 'Hidden Linux Swap'},
'C4': {'OS': 'DR DOS','Description': 'Secured FAT16'},
'C5': {'OS': 'DR DOS','Description': 'Secured extended partition'},
'C6': {'OS': 'DR DOS / WinNT 4 Server','Description': 'Secured FAT16B/FAT16Bmirror'},
'C7': {'OS': 'Syrinx / WinNT 4 Server','Description': 'Syrinx boot/HPFS/NTFSmirror'},
'C8': {'Description': "DR-DOS Reserved (since '97)"},
'C9': {'Description': "DR-DOS Reserved (since '97)"},
'CA': {'Description': "DR-DOS Reserved (since '97)"},
'CB': {'OS': 'DR-DOSx / WinNT 4 Server','Description': 'Secured FAT32/FAT32 mirror'},
'CC': {'OS': 'DR-DOSx / WinNT 4 Server','Description': 'Secured FAT32/FAT32 mirror'},
'CD': {'OS': 'CTOS','Description': 'Memory dump'},
'CE': {'OS': 'DR-DOSx','Description': 'Secured FAT16B'},
'CF': {'OS': 'DR-DOSx','Description': 'Secured extended partition'},
'D0': {'OS': 'Multiuser DOS, REAL/32','Description': 'Secured FAT (over 32 MB)'},
'D1': {'OS': 'Multiuser DOS','Description': 'Secured FAT12'},
'D4': {'OS': 'Multiuser DOS','Description': 'Secured FAT16'},
'D5': {'OS': 'Multiuser DOS','Description': 'Secured extended partition'},
'D6': {'OS': 'Multiuser DOS','Description': 'Secured FAT16B'},
'D8': {'OS': 'Digital Research','Description': 'CP/M-86 [citation needed]'},
'DA': {'OS': 'Powercopy Backup','Description': 'Non-FS data / Shielded disk'},
'DB': {'OS': 'CP/M-86/CDOS/CTOS/D800/DRMK','Description': 'CP/M-86/ConcDOS/Boot/FAT32'},
'DD': {'OS': 'CTOS','Description': 'Hidden memory dump'},
'DE': {'OS': 'Dell','Description': 'FAT16 utility/diagnostic'},
'DF': {'OS': 'DG/UX / BootIt / Aviion','Description': 'DG/UX Virt DiskMan / EMBRM'},
'E0': {'OS': 'STMicroelectronics','Description': 'ST AVFS'},
'E1': {'OS': 'SpeedStor','Description': 'ExtendedFAT12 >1023cylinder'},
'E2': {'Description': 'DOS read-only (XFDISK)'},
'E3': {'OS': 'SpeedStor','Description': 'DOS read-only'},
'E4': {'OS': 'SpeedStor','Description': 'ExtendedFAT16 <1024cylinder'},
'E5': {'OS': 'Tandy MS-DOS','Description': 'Logical FAT12 or FAT16'},
'E6': {'OS': 'SpeedStor','Description': 'Unknown'},
'E8': {'OS': 'LUKS','Description': 'Linux Unified Key Setup'},
'EB': {'OS': 'BeOS, Haiku','Description': 'BFS'},
'EC': {'OS': 'SkyOS','Description': 'SkyFS'},
'ED': {'OS': 'Sprytix / EDD 4','Description': 'EDC loader / GPT hybrid MBR'},
'EE': {'OS': 'EFI','Description': 'GPT protective MBR'},
'EF': {'OS': 'EFI','Description': 'EFI system partition'},
'F0': {'OS': 'Linux / OS/32','Description': 'PA-RISC Linux boot loader.'},
'F1': {'OS': 'SpeedStor','Description': 'Unknown'},
'F2': {'OS': 'SperryIT DOS/Unisys DOS','Description': 'Logical FAT12/FAT16'},
'F3': {'OS': 'SpeedStor','Description': 'Unknown'},
'F4': {'OS': 'SpeedStor / Prologue','Description': '"large"DOS part/NGF/TwinFS'},
'F5': {'OS': 'Prologue','Description': 'MD0-MD9 part for NGF/TwinFS'},
'F6': {'OS': 'SpeedStor','Description': 'Unknown'},
'F7': {'OS': 'O.S.G. / X1','Description': 'EFAT / Solid State FS'},
'F9': {'OS': 'Linux','Description': 'pCache ext2/ext3 cache'},
'FA': {'OS': 'Bochs','Description': 'x86 emulator'},
'FB': {'OS': 'VMware','Description': 'VMware VMFS partition'},
'FC': {'OS': 'VMware','Description': 'Swap / VMKCORE kernel dump'},
'FD': {'OS': 'Linux / FreeDOS','Description': 'LinuxRAID/Reserved4FreeDOS'},
'FE': {'OS': 'SpeedStor/LANstep/NT/Linux','Description': 'PS/2/DiskAdmin/old LinuxLVM'},
'FF': {'OS': 'XENIX','Description': 'XENIX bad block table'},
'00000000-0000-0000-0000-000000000000': {'Description': 'Unused entry'},
'024DEE41-33E7-11D3-9D69-0008C781F39F': {'Description': 'MBR partition scheme'},
'C12A7328-F81F-11D2-BA4B-00A0C93EC93B': {'Description': 'EFI System partition'},
'21686148-6449-6E6F-744E-656564454649': {'Description': 'BIOS Boot partition'},
'D3BFE2DE-3DAF-11DF-BA40-E3A556D89593': {'Description': 'Intel Fast Flash (iFFS) partition (for Intel Rapid Start technology)'},
'F4019732-066E-4E12-8273-346C5641494F': {'Description': 'Sony boot partition'},
'BFBFAFE7-A34F-448A-9A5B-6213EB736C22': {'Description': 'Lenovo boot partition'},
'E3C9E316-0B5C-4DB8-817D-F92DF00215AE': {'OS': 'Windows', 'Description': 'Microsoft Reserved Partition (MSR)'},
'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7': {'OS': 'Windows', 'Description': 'Basic data partition'},
'5808C8AA-7E8F-42E0-85D2-E1E90434CFB3': {'OS': 'Windows', 'Description': 'Logical Disk Manager (LDM) metadata partition'},
'AF9B60A0-1431-4F62-BC68-3311714A69AD': {'OS': 'Windows', 'Description': 'Logical Disk Manager data partition'},
'DE94BBA4-06D1-4D40-A16A-BFD50179D6AC': {'OS': 'Windows', 'Description': 'Windows Recovery Environment'},
'37AFFC90-EF7D-4E96-91C3-2D7AE055B174': {'OS': 'Windows', 'Description': 'IBM General Parallel File System (GPFS) partition'},
'E75CAF8F-F680-4CEE-AFA3-B001E56EFC2D': {'OS': 'Windows', 'Description': 'Storage Spaces partition'},
'75894C1E-3AEB-11D3-B7C1-7B03A0000000': {'OS': 'HP-UX', 'Description': 'Data partition'},
'E2A1E728-32E3-11D6-A682-7B03A0000000': {'OS': 'HP-UX', 'Description': 'Service Partition'},
'0FC63DAF-8483-4772-8E79-3D69D8477DE4': {'OS': 'Linux', 'Description': 'Linux filesystem data'},
'A19D880F-05FC-4D3B-A006-743F0F84911E': {'OS': 'Linux', 'Description': 'RAID partition'},
'44479540-F297-41B2-9AF7-D131D5F0458A': {'OS': 'Linux', 'Description': 'Root partition (x86)'},
'4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709': {'OS': 'Linux', 'Description': 'Root partition (x86-64)'},
'69DAD710-2CE4-4E3C-B16C-21A1D49ABED3': {'OS': 'Linux', 'Description': 'Root partition (32-bit ARM)'},
'B921B045-1DF0-41C3-AF44-4C6F280D3FAE': {'OS': 'Linux', 'Description': 'Root partition (64-bit ARM)/AArch64)'},
'0657FD6D-A4AB-43C4-84E5-0933C84B4F4F': {'OS': 'Linux', 'Description': 'Swap partition'},
'E6D6D379-F507-44C2-A23C-238F2A3DF928': {'OS': 'Linux', 'Description': 'Logical Volume Manager (LVM) partition'},
'933AC7E1-2EB4-4F13-B844-0E14E2AEF915': {'OS': 'Linux', 'Description': '/home partition'},
'3B8F8425-20E0-4F3B-907F-1A25A76F98E8': {'OS': 'Linux', 'Description': '/srv (server data) partition'},
'7FFEC5C9-2D00-49B7-8941-3EA10A5586B7': {'OS': 'Linux', 'Description': 'Plain dm-crypt partition'},
'CA7D7CCB-63ED-4C53-861C-1742536059CC': {'OS': 'Linux', 'Description': 'LUKS partition'},
'8DA63339-0007-60C0-C436-083AC8230908': {'OS': 'Linux', 'Description': 'Reserved'},
'83BD6B9D-7F41-11DC-BE0B-001560B84F0F': {'OS': 'FreeBSD', 'Description': 'Boot partition'},
'516E7CB4-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Data partition'},
'516E7CB5-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Swap partition'},
'516E7CB6-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Unix File System (UFS) partition'},
'516E7CB8-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Vinum volume manager partition'},
'516E7CBA-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'ZFS partition'},
'48465300-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Hierarchical File System Plus (HFS+) partition'},
'55465300-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple UFS'},
'6A898CC3-1DD2-11B2-99A6-080020736631': {'OS': 'OS X Darwin', 'Description': 'ZFS'},
'52414944-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple RAID partition'},
'52414944-5F4F-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple RAID partition, offline'},
'426F6F74-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Boot partition (Recovery HD)'},
'4C616265-6C00-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Label'},
'5265636F-7665-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple TV Recovery partition'},
'53746F72-6167-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Core Storage (i.e. Lion FileVault) partition'},
'6A82CB45-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Boot partition'},
'6A85CF4D-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Root partition'},
'6A87C46F-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Swap partition'},
'6A8B642B-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Backup partition'},
'6A898CC3-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/usr partition'},
'6A8EF2E9-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/var partition'},
'6A90BA39-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/home partition'},
'6A9283A5-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Alternate sector'},
'6A945A3B-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Reserved partition'},
'6A9630D1-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'},
'6A980767-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'},
'6A96237F-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'},
'6A8D2AC7-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'},
'49F48D32-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Swap partition'},
'49F48D5A-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'FFS partition'},
'49F48D82-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'LFS partition'},
'49F48DAA-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'RAID partition'},
'2DB519C4-B10F-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Concatenated partition'},
'2DB519EC-B10F-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Encrypted partition'},
'FE3A2A5D-4F32-41A7-B725-ACCC3285A309': {'OS': 'ChromeOS', 'Description': 'ChromeOS kernel'},
'3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC': {'OS': 'ChromeOS', 'Description': 'ChromeOS rootfs'},
'2E0A753D-9E48-43B0-8337-B15192CB1B5E': {'OS': 'ChromeOS', 'Description': 'ChromeOS future use'},
'42465331-3BA3-10F1-802A-4861696B7521': {'OS': 'Haiku', 'Description': 'Haiku BFS'},
'85D5E45E-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Boot partition'},
'85D5E45A-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Data partition'},
'85D5E45B-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Swap partition'},
'0394EF8B-237E-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Unix File System (UFS) partition'},
'85D5E45C-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Vinum volume manager partition'},
'85D5E45D-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'ZFS partition'},
'45B0969E-9B03-4F30-B4C6-B4B80CEFF106': {'OS': 'Ceph', 'Description': 'Ceph Journal'},
'45B0969E-9B03-4F30-B4C6-5EC00CEFF106': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt Encrypted Journal'},
'4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D': {'OS': 'Ceph', 'Description': 'Ceph OSD'},
'4FBD7E29-9D25-41B8-AFD0-5EC00CEFF05D': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt OSD'},
'89C57F98-2FE5-4DC0-89C1-F3AD0CEFF2BE': {'OS': 'Ceph', 'Description': 'Ceph disk in creation'},
'89C57F98-2FE5-4DC0-89C1-5EC00CEFF2BE': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt disk in creation'},
'824CC7A0-36A8-11E3-890A-952519AD3F61': {'OS': 'OpenBSD', 'Description': 'Data partition'},
'CEF5A9AD-73BC-4601-89F3-CDEEEEE321A1': {'OS': 'QNX', 'Description': 'Power-safe (QNX6) file system'},
'C91818F9-8025-47AF-89D2-F030D7000C2C': {'OS': 'Plan 9', 'Description': 'Plan 9 partition'},
'9D275380-40AD-11DB-BF97-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'vmkcore (coredump partition)'},
'AA31E02A-400F-11DB-9590-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'VMFS filesystem partition'},
'9198EFFC-31C0-11DB-8F78-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'VMware Reserved'},
'2568845D-2332-4675-BC39-8FA5A4748D15': {'OS': 'Android-IA', 'Description': 'Bootloader'},
'114EAFFE-1552-4022-B26E-9B053604CF84': {'OS': 'Android-IA', 'Description': 'Bootloader2'},
'49A4D17F-93A3-45C1-A0DE-F50B2EBE2599': {'OS': 'Android-IA', 'Description': 'Boot'},
'4177C722-9E92-4AAB-8644-43502BFD5506': {'OS': 'Android-IA', 'Description': 'Recovery'},
'EF32A33B-A409-486C-9141-9FFB711F6266': {'OS': 'Android-IA', 'Description': 'Misc'},
'20AC26BE-20B7-11E3-84C5-6CFDB94711E9': {'OS': 'Android-IA', 'Description': 'Metadata'},
'38F428E6-D326-425D-9140-6E0EA133647C': {'OS': 'Android-IA', 'Description': 'System'},
'A893EF21-E428-470A-9E55-0668FD91A2D9': {'OS': 'Android-IA', 'Description': 'Cache'},
'DC76DDA9-5AC1-491C-AF42-A82591580C0D': {'OS': 'Android-IA', 'Description': 'Data'},
'EBC597D0-2053-4B15-8B64-E0AAC75F4DB1': {'OS': 'Android-IA', 'Description': 'Persistent'},
'8F68CC74-C5E5-48DA-BE91-A0C8C15E9C80': {'OS': 'Android-IA', 'Description': 'Factory'},
'767941D0-2085-11E3-AD3B-6CFDB94711E9': {'OS': 'Android-IA', 'Description': 'Fastboot / Tertiary'},
'AC6D7924-EB71-4DF8-B48D-E267B27148FF': {'OS': 'Android-IA', 'Description': 'OEM'},
'7412F7D5-A156-4B13-81DC-867174929325': {'OS': 'ONIE', 'Description': 'Boot'},
'D4E6E2CD-4469-46F3-B5CB-1BFF57AFC149': {'OS': 'ONIE', 'Description': 'Config'},
'9E1A2D38-C612-4316-AA26-8B49521E5A8B': {'OS': 'PowerPC', 'Description': 'PReP boot'},
'BC13C2FF-59E6-4262-A352-B275FD6F7172': {'OS': 'Freedesktop', 'Description': 'Extended Boot Partition ($BOOT)'},
}
def lookup_guid(guid):
return PARTITION_UIDS.get(guid.upper(), {})
if __name__ == '__main__':
print("This file is not meant to be called directly.")

View file

@ -2,110 +2,119 @@
from functions.common import *
# Regex
REGEX_REGISTRY_DIRS = re.compile(
r'^(config$|RegBack$|System32$|Transfer|Win)',
re.IGNORECASE)
r'^(config$|RegBack$|System32$|Transfer|Win)',
re.IGNORECASE)
REGEX_SOFTWARE_HIVE = re.compile(r'^Software$', re.IGNORECASE)
def extract_keys():
"""Extract keys from provided hives and return a dict."""
keys = {}
"""Extract keys from provided hives and return a dict."""
keys = {}
# Extract keys
extract_item('ProduKey', silent=True)
for hive in find_software_hives():
cmd = [
global_vars['Tools']['ProduKey'],
'/IEKeys', '0',
'/WindowsKeys', '1',
'/OfficeKeys', '1',
'/ExtractEdition', '1',
'/nosavereg',
'/regfile', hive,
'/scomma', '']
try:
out = run_program(cmd)
except subprocess.CalledProcessError:
# Ignore and return empty dict
pass
else:
for line in out.stdout.decode().splitlines():
# Add key to keys under product only if unique
tmp = line.split(',')
product = tmp[0]
key = tmp[2]
if product not in keys:
keys[product] = []
if key not in keys[product]:
keys[product].append(key)
# Extract keys
extract_item('ProduKey', silent=True)
for hive in find_software_hives():
cmd = [
global_vars['Tools']['ProduKey'],
'/IEKeys', '0',
'/WindowsKeys', '1',
'/OfficeKeys', '1',
'/ExtractEdition', '1',
'/nosavereg',
'/regfile', hive,
'/scomma', '']
try:
out = run_program(cmd)
except subprocess.CalledProcessError:
# Ignore and return empty dict
pass
else:
for line in out.stdout.decode().splitlines():
# Add key to keys under product only if unique
tmp = line.split(',')
product = tmp[0]
key = tmp[2]
if product not in keys:
keys[product] = []
if key not in keys[product]:
keys[product].append(key)
# Done
return keys
# Done
return keys
def list_clientdir_keys():
"""List product keys found in hives inside the ClientDir."""
keys = extract_keys()
key_list = []
if keys:
for product in sorted(keys):
key_list.append(product)
for key in sorted(keys[product]):
key_list.append(' {key}'.format(key=key))
else:
key_list.append('No keys found.')
"""List product keys found in hives inside the ClientDir."""
keys = extract_keys()
key_list = []
if keys:
for product in sorted(keys):
key_list.append(product)
for key in sorted(keys[product]):
key_list.append(' {key}'.format(key=key))
else:
key_list.append('No keys found.')
return key_list
return key_list
def find_software_hives():
"""Search for transferred SW hives and return a list."""
hives = []
search_paths = [global_vars['ClientDir']]
"""Search for transferred SW hives and return a list."""
hives = []
search_paths = [global_vars['ClientDir']]
while len(search_paths) > 0:
for item in os.scandir(search_paths.pop(0)):
if item.is_dir() and REGEX_REGISTRY_DIRS.search(item.name):
search_paths.append(item.path)
if item.is_file() and REGEX_SOFTWARE_HIVE.search(item.name):
hives.append(item.path)
while len(search_paths) > 0:
for item in os.scandir(search_paths.pop(0)):
if item.is_dir() and REGEX_REGISTRY_DIRS.search(item.name):
search_paths.append(item.path)
if item.is_file() and REGEX_SOFTWARE_HIVE.search(item.name):
hives.append(item.path)
return hives
return hives
def get_product_keys():
"""List product keys from saved report."""
keys = []
log_file = r'{LogDir}\Product Keys (ProduKey).txt'.format(**global_vars)
with open (log_file, 'r') as f:
for line in f.readlines():
if re.search(r'^Product Name', line):
line = re.sub(r'^Product Name\s+:\s+(.*)', r'\1', line.strip())
keys.append(line)
"""List product keys from saved report."""
keys = []
log_file = r'{LogDir}\Product Keys (ProduKey).txt'.format(**global_vars)
with open (log_file, 'r') as f:
for line in f.readlines():
if re.search(r'^Product Name', line):
line = re.sub(r'^Product Name\s+:\s+(.*)', r'\1', line.strip())
keys.append(line)
if keys:
return keys
else:
return ['No product keys found']
if keys:
return keys
else:
return ['No product keys found']
def run_produkey():
"""Run ProduKey and save report in the ClientDir."""
extract_item('ProduKey', silent=True)
log_file = r'{LogDir}\Product Keys (ProduKey).txt'.format(**global_vars)
if not os.path.exists(log_file):
# Clear current configuration
for config in ['ProduKey.cfg', 'ProduKey64.cfg']:
config = r'{BinDir}\ProduKey\{config}'.format(
config=config, **global_vars)
try:
if os.path.exists(config):
os.remove(config)
except Exception:
pass
cmd = [
global_vars['Tools']['ProduKey'],
'/nosavereg',
'/stext',
log_file]
run_program(cmd, check=False)
"""Run ProduKey and save report in the ClientDir."""
extract_item('ProduKey', silent=True)
log_file = r'{LogDir}\Product Keys (ProduKey).txt'.format(**global_vars)
if not os.path.exists(log_file):
# Clear current configuration
for config in ['ProduKey.cfg', 'ProduKey64.cfg']:
config = r'{BinDir}\ProduKey\{config}'.format(
config=config, **global_vars)
try:
if os.path.exists(config):
os.remove(config)
except Exception:
pass
cmd = [
global_vars['Tools']['ProduKey'],
'/nosavereg',
'/stext',
log_file]
run_program(cmd, check=False)
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -2,125 +2,135 @@
from functions.common import *
def run_chkdsk(repair=False):
"""Run CHKDSK scan or schedule offline repairs."""
if repair:
run_chkdsk_offline()
else:
run_chkdsk_scan()
"""Run CHKDSK scan or schedule offline repairs."""
if repair:
run_chkdsk_offline()
else:
run_chkdsk_scan()
def run_chkdsk_scan():
"""Run CHKDSK in a "split window" and report errors."""
if global_vars['OS']['Version'] in ('8', '8.1', '10'):
cmd = ['chkdsk', global_vars['Env']['SYSTEMDRIVE'], '/scan', '/perf']
else:
cmd = ['chkdsk', global_vars['Env']['SYSTEMDRIVE']]
out = run_program(cmd, check=False)
# retcode == 0: no issues
# retcode == 1: fixed issues (also happens when chkdsk.exe is killed?)
# retcode == 2: issues
if int(out.returncode) > 0:
# print_error(' ERROR: CHKDSK encountered errors')
raise GenericError
"""Run CHKDSK in a "split window" and report errors."""
if global_vars['OS']['Version'] in ('8', '8.1', '10'):
cmd = ['chkdsk', global_vars['Env']['SYSTEMDRIVE'], '/scan', '/perf']
else:
cmd = ['chkdsk', global_vars['Env']['SYSTEMDRIVE']]
out = run_program(cmd, check=False)
# retcode == 0: no issues
# retcode == 1: fixed issues (also happens when chkdsk.exe is killed?)
# retcode == 2: issues
if int(out.returncode) > 0:
# print_error(' ERROR: CHKDSK encountered errors')
raise GenericError
# Save stderr
with open(r'{LogDir}\Tools\CHKDSK.err'.format(**global_vars), 'a') as f:
for line in out.stderr.decode().splitlines():
f.write(line.strip() + '\n')
# Save stdout
with open(r'{LogDir}\Tools\CHKDSK.log'.format(**global_vars), 'a') as f:
for line in out.stdout.decode().splitlines():
f.write(line.strip() + '\n')
# Save stderr
with open(r'{LogDir}\Tools\CHKDSK.err'.format(**global_vars), 'a') as f:
for line in out.stderr.decode().splitlines():
f.write(line.strip() + '\n')
# Save stdout
with open(r'{LogDir}\Tools\CHKDSK.log'.format(**global_vars), 'a') as f:
for line in out.stdout.decode().splitlines():
f.write(line.strip() + '\n')
def run_chkdsk_offline():
"""Set filesystem 'dirty bit' to force a chkdsk during next boot."""
cmd = [
'fsutil', 'dirty',
'set',
global_vars['Env']['SYSTEMDRIVE']]
out = run_program(cmd, check=False)
if int(out.returncode) > 0:
raise GenericError
"""Set filesystem 'dirty bit' to force a chkdsk during next boot."""
cmd = [
'fsutil', 'dirty',
'set',
global_vars['Env']['SYSTEMDRIVE']]
out = run_program(cmd, check=False)
if int(out.returncode) > 0:
raise GenericError
def run_dism(repair=False):
"""Run DISM /RestoreHealth, then /CheckHealth, and then report errors."""
if global_vars['OS']['Version'] in ('8', '8.1', '10'):
if repair:
# Restore Health
cmd = [
'DISM', '/Online',
'/Cleanup-Image', '/RestoreHealth',
r'/LogPath:"{LogDir}\Tools\DISM_RestoreHealth.log"'.format(
**global_vars),
'-new_console:n', '-new_console:s33V']
else:
# Scan Health
cmd = [
'DISM', '/Online',
'/Cleanup-Image', '/ScanHealth',
r'/LogPath:"{LogDir}\Tools\DISM_ScanHealth.log"'.format(
**global_vars),
'-new_console:n', '-new_console:s33V']
run_program(cmd, pipe=False, check=False, shell=True)
wait_for_process('dism')
# Now check health
cmd = [
'DISM', '/Online',
'/Cleanup-Image', '/CheckHealth',
r'/LogPath:"{LogDir}\Tools\DISM_CheckHealth.log"'.format(**global_vars)]
result = run_program(cmd, shell=True).stdout.decode()
# Check result
if 'no component store corruption detected' not in result.lower():
raise GenericError
"""Run DISM to either scan or repair component store health."""
if global_vars['OS']['Version'] in ('8', '8.1', '10'):
if repair:
# Restore Health
cmd = [
'DISM', '/Online',
'/Cleanup-Image', '/RestoreHealth',
r'/LogPath:"{LogDir}\Tools\DISM_RestoreHealth.log"'.format(
**global_vars),
'-new_console:n', '-new_console:s33V']
else:
raise UnsupportedOSError
# Scan Health
cmd = [
'DISM', '/Online',
'/Cleanup-Image', '/ScanHealth',
r'/LogPath:"{LogDir}\Tools\DISM_ScanHealth.log"'.format(
**global_vars),
'-new_console:n', '-new_console:s33V']
run_program(cmd, pipe=False, check=False, shell=True)
wait_for_process('dism')
# Now check health
cmd = [
'DISM', '/Online',
'/Cleanup-Image', '/CheckHealth',
r'/LogPath:"{LogDir}\Tools\DISM_CheckHealth.log"'.format(**global_vars)]
result = run_program(cmd, shell=True).stdout.decode()
# Check result
if 'no component store corruption detected' not in result.lower():
raise GenericError
else:
raise UnsupportedOSError
def run_kvrt():
"""Run KVRT."""
extract_item('KVRT', silent=True)
os.makedirs(global_vars['QuarantineDir'], exist_ok=True)
cmd = [
global_vars['Tools']['KVRT'],
'-accepteula', '-dontcryptsupportinfo', '-fixednames',
'-d', global_vars['QuarantineDir'],
'-processlevel', '3']
popen_program(cmd, pipe=False)
"""Run KVRT."""
extract_item('KVRT', silent=True)
os.makedirs(global_vars['QuarantineDir'], exist_ok=True)
cmd = [
global_vars['Tools']['KVRT'],
'-accepteula', '-dontcryptsupportinfo', '-fixednames',
'-d', global_vars['QuarantineDir'],
'-processlevel', '3']
popen_program(cmd, pipe=False)
def run_sfc_scan():
"""Run SFC in a "split window" and report errors."""
cmd = [
r'{SYSTEMROOT}\System32\sfc.exe'.format(**global_vars['Env']),
'/scannow']
out = run_program(cmd, check=False)
# Save stderr
with open(r'{LogDir}\Tools\SFC.err'.format(**global_vars), 'a') as f:
for line in out.stderr.decode('utf-8', 'ignore').splitlines():
f.write(line.strip() + '\n')
# Save stdout
with open(r'{LogDir}\Tools\SFC.log'.format(**global_vars), 'a') as f:
for line in out.stdout.decode('utf-8', 'ignore').splitlines():
f.write(line.strip() + '\n')
# Check result
log_text = out.stdout.decode('utf-8', 'ignore').replace('\0', '')
if re.findall(r'did\s+not\s+find\s+any\s+integrity\s+violations', log_text):
pass
elif re.findall(r'successfully\s+repaired\s+them', log_text):
raise GenericRepair
else:
raise GenericError
"""Run SFC in a "split window" and report errors."""
cmd = [
r'{SYSTEMROOT}\System32\sfc.exe'.format(**global_vars['Env']),
'/scannow']
out = run_program(cmd, check=False)
# Save stderr
with open(r'{LogDir}\Tools\SFC.err'.format(**global_vars), 'a') as f:
for line in out.stderr.decode('utf-8', 'ignore').splitlines():
f.write(line.strip() + '\n')
# Save stdout
with open(r'{LogDir}\Tools\SFC.log'.format(**global_vars), 'a') as f:
for line in out.stdout.decode('utf-8', 'ignore').splitlines():
f.write(line.strip() + '\n')
# Check result
log_text = out.stdout.decode('utf-8', 'ignore').replace('\0', '')
if re.findall(r'did\s+not\s+find\s+any\s+integrity\s+violations', log_text):
pass
elif re.findall(r'successfully\s+repaired\s+them', log_text):
raise GenericRepair
else:
raise GenericError
def run_tdsskiller():
"""Run TDSSKiller."""
extract_item('TDSSKiller', silent=True)
os.makedirs(r'{QuarantineDir}\TDSSKiller'.format(
**global_vars), exist_ok=True)
cmd = [
global_vars['Tools']['TDSSKiller'],
'-l', r'{LogDir}\Tools\TDSSKiller.log'.format(**global_vars),
'-qpath', r'{QuarantineDir}\TDSSKiller'.format(**global_vars),
'-accepteula', '-accepteulaksn',
'-dcexact', '-tdlfs']
run_program(cmd, pipe=False)
"""Run TDSSKiller."""
extract_item('TDSSKiller', silent=True)
os.makedirs(r'{QuarantineDir}\TDSSKiller'.format(
**global_vars), exist_ok=True)
cmd = [
global_vars['Tools']['TDSSKiller'],
'-l', r'{LogDir}\Tools\TDSSKiller.log'.format(**global_vars),
'-qpath', r'{QuarantineDir}\TDSSKiller'.format(**global_vars),
'-accepteula', '-accepteulaksn',
'-dcexact', '-tdlfs']
run_program(cmd, pipe=False)
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -2,35 +2,44 @@
from functions.common import *
# STATIC VARIABLES
REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer'
def disable_safemode_msi():
"""Disable MSI access under safemode."""
cmd = ['reg', 'delete', REG_MSISERVER, '/f']
run_program(cmd)
"""Disable MSI access under safemode."""
cmd = ['reg', 'delete', REG_MSISERVER, '/f']
run_program(cmd)
def disable_safemode():
"""Edit BCD to remove safeboot value."""
cmd = ['bcdedit', '/deletevalue', '{default}', 'safeboot']
run_program(cmd)
"""Edit BCD to remove safeboot value."""
cmd = ['bcdedit', '/deletevalue', '{default}', 'safeboot']
run_program(cmd)
def enable_safemode_msi():
"""Enable MSI access under safemode."""
cmd = ['reg', 'add', REG_MSISERVER, '/f']
run_program(cmd)
cmd = ['reg', 'add', REG_MSISERVER, '/ve',
'/t', 'REG_SZ', '/d', 'Service', '/f']
run_program(cmd)
"""Enable MSI access under safemode."""
cmd = ['reg', 'add', REG_MSISERVER, '/f']
run_program(cmd)
cmd = ['reg', 'add', REG_MSISERVER, '/ve',
'/t', 'REG_SZ', '/d', 'Service', '/f']
run_program(cmd)
def enable_safemode():
"""Edit BCD to set safeboot as default."""
cmd = ['bcdedit', '/set', '{default}', 'safeboot', 'network']
run_program(cmd)
"""Edit BCD to set safeboot as default."""
cmd = ['bcdedit', '/set', '{default}', 'safeboot', 'network']
run_program(cmd)
def reboot(delay=3):
cmd = ['shutdown', '-r', '-t', '{}'.format(delay)]
run_program(cmd, check=False)
cmd = ['shutdown', '-r', '-t', '{}'.format(delay)]
run_program(cmd, check=False)
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -5,6 +5,7 @@ import re
from functions.tmux import *
# STATIC VARIABLES
TEMP_LIMITS = {
'GREEN': 60,
@ -13,9 +14,11 @@ TEMP_LIMITS = {
'RED': 90,
}
# REGEX
REGEX_COLORS = re.compile(r'\033\[\d+;?1?m')
def clear_temps(sensor_data):
"""Clear saved temps but keep structure, returns dict."""
for _section, _adapters in sensor_data.items():
@ -23,6 +26,7 @@ def clear_temps(sensor_data):
for _source, _data in _sources.items():
_data['Temps'] = []
def fix_sensor_str(s):
"""Cleanup string and return str."""
s = re.sub(r'^(\w+)-(\w+)-(\w+)', r'\1 (\2 \3)', s, re.IGNORECASE)
@ -36,6 +40,7 @@ def fix_sensor_str(s):
s = s.replace(' ', ' ')
return s
def generate_sensor_report(
sensor_data, *temp_labels,
colors=True, core_only=False):
@ -73,6 +78,7 @@ def generate_sensor_report(
# Done
return report
def get_colored_temp_str(temp):
"""Get colored string based on temp, returns str."""
try:
@ -97,6 +103,7 @@ def get_colored_temp_str(temp):
temp = temp,
**COLORS)
def get_raw_sensor_data():
"""Read sensor data and return dict."""
data = {}
@ -110,6 +117,7 @@ def get_raw_sensor_data():
return data
def get_sensor_data():
"""Parse raw sensor data and return new dict."""
json_data = get_raw_sensor_data()
@ -141,6 +149,7 @@ def get_sensor_data():
# Done
return sensor_data
def get_temp_str(temp, colors=True):
"""Get temp string, returns str."""
if colors:
@ -154,6 +163,7 @@ def get_temp_str(temp, colors=True):
'-' if temp < 0 else '',
temp)
def monitor_sensors(monitor_pane, monitor_file):
"""Continually update sensor data and report to screen."""
sensor_data = get_sensor_data()
@ -166,8 +176,9 @@ def monitor_sensors(monitor_pane, monitor_file):
if monitor_pane and not tmux_poll_pane(monitor_pane):
break
def save_average_temp(sensor_data, temp_label, seconds=10):
"""Calculate average temps and record under temp_label, returns dict."""
"""Save average temps under temp_label, returns dict."""
clear_temps(sensor_data)
# Get temps
@ -181,6 +192,7 @@ def save_average_temp(sensor_data, temp_label, seconds=10):
for _source, _data in _sources.items():
_data[temp_label] = sum(_data['Temps']) / len(_data['Temps'])
def update_sensor_data(sensor_data):
"""Read sensors and update existing sensor_data, returns dict."""
json_data = get_raw_sensor_data()
@ -193,12 +205,14 @@ def update_sensor_data(sensor_data):
_data['Max'] = max(_temp, _data['Max'])
_data['Temps'].append(_temp)
def join_columns(column1, column2, width=55):
return '{:<{}}{}'.format(
column1,
55+len(column1)-len(REGEX_COLORS.sub('', column1)),
column2)
if __name__ == '__main__':
print("This file is not meant to be called directly.")

View file

@ -1,321 +1,339 @@
# Wizard Kit: Functions - Setup
from functions.common import *
from functions.update import *
# STATIC VARIABLES
HKU = winreg.HKEY_USERS
HKCR = winreg.HKEY_CLASSES_ROOT
HKCU = winreg.HKEY_CURRENT_USER
HKLM = winreg.HKEY_LOCAL_MACHINE
MOZILLA_FIREFOX_UBO_PATH = r'{}\{}\ublock_origin.xpi'.format(
os.environ.get('PROGRAMFILES'),
r'Mozilla Firefox\distribution\extensions')
os.environ.get('PROGRAMFILES'),
r'Mozilla Firefox\distribution\extensions')
OTHER_RESULTS = {
'Error': {
'CalledProcessError': 'Unknown Error',
'FileNotFoundError': 'File not found',
},
'Warning': {}}
'Error': {
'CalledProcessError': 'Unknown Error',
'FileNotFoundError': 'File not found',
},
'Warning': {}}
SETTINGS_CLASSIC_START = {
r'Software\IvoSoft\ClassicShell\Settings': {},
r'Software\IvoSoft\ClassicStartMenu': {
'DWORD Items': {'ShowedStyle2': 1},
},
r'Software\IvoSoft\ClassicStartMenu\MRU': {},
r'Software\IvoSoft\ClassicStartMenu\Settings': {
'DWORD Items': {'SkipMetro': 1},
'SZ Items': {
'MenuStyle': 'Win7',
'RecentPrograms': 'Recent',
},
},
}
r'Software\IvoSoft\ClassicShell\Settings': {},
r'Software\IvoSoft\ClassicStartMenu': {
'DWORD Items': {'ShowedStyle2': 1},
},
r'Software\IvoSoft\ClassicStartMenu\MRU': {},
r'Software\IvoSoft\ClassicStartMenu\Settings': {
'DWORD Items': {'SkipMetro': 1},
'SZ Items': {
'MenuStyle': 'Win7',
'RecentPrograms': 'Recent',
},
},
}
SETTINGS_EXPLORER_SYSTEM = {
# Disable Location Tracking
r'Software\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}': {
'DWORD Items': {'SensorPermissionState': 0},
},
r'System\CurrentControlSet\Services\lfsvc\Service\Configuration': {
'Status': {'Value': 0},
},
# Disable Telemetry
r'Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection': {
'DWORD Items': {'AllowTelemetry': 0},
},
r'Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection': {
'DWORD Items': {'AllowTelemetry': 0},
'WOW64_32': True,
},
r'Software\Policies\Microsoft\Windows\DataCollection': {
'DWORD Items': {'AllowTelemetry': 0},
},
# Disable Wi-Fi Sense
r'Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting': {
'DWORD Items': {'Value': 0},
},
r'Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots': {
'DWORD Items': {'Value': 0},
},
}
# Disable Location Tracking
r'Software\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}': {
'DWORD Items': {'SensorPermissionState': 0},
},
r'System\CurrentControlSet\Services\lfsvc\Service\Configuration': {
'Status': {'Value': 0},
},
# Disable Telemetry
r'Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection': {
'DWORD Items': {'AllowTelemetry': 0},
},
r'Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection': {
'DWORD Items': {'AllowTelemetry': 0},
'WOW64_32': True,
},
r'Software\Policies\Microsoft\Windows\DataCollection': {
'DWORD Items': {'AllowTelemetry': 0},
},
# Disable Wi-Fi Sense
r'Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting': {
'DWORD Items': {'Value': 0},
},
r'Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots': {
'DWORD Items': {'Value': 0},
},
}
SETTINGS_EXPLORER_USER = {
# Disable silently installed apps
r'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager': {
'DWORD Items': {'SilentInstalledAppsEnabled': 0},
},
# Disable Tips and Tricks
r'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager': {
'DWORD Items': {'SoftLandingEnabled ': 0},
},
# Hide People bar
r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People': {
'DWORD Items': {'PeopleBand': 0},
},
# Hide Search button / box
r'Software\Microsoft\Windows\CurrentVersion\Search': {
'DWORD Items': {'SearchboxTaskbarMode': 0},
},
# Change default Explorer view to "Computer"
r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced': {
'DWORD Items': {'LaunchTo': 1},
},
}
# Disable silently installed apps
r'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager': {
'DWORD Items': {'SilentInstalledAppsEnabled': 0},
},
# Disable Tips and Tricks
r'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager': {
'DWORD Items': {'SoftLandingEnabled ': 0},
},
# Hide People bar
r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People': {
'DWORD Items': {'PeopleBand': 0},
},
# Hide Search button / box
r'Software\Microsoft\Windows\CurrentVersion\Search': {
'DWORD Items': {'SearchboxTaskbarMode': 0},
},
# Change default Explorer view to "Computer"
r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced': {
'DWORD Items': {'LaunchTo': 1},
},
}
SETTINGS_GOOGLE_CHROME = {
r'Software\Google\Chrome\Extensions\cjpalhdlnbpafiamejdnhcphjbkeiagm': {
'SZ Items': {
'update_url': 'https://clients2.google.com/service/update2/crx'},
'WOW64_32': True,
},
r'Software\Google\Chrome\Extensions\pgdnlhfefecpicbbihgmbmffkjpaplco': {
'SZ Items': {
'update_url': 'https://clients2.google.com/service/update2/crx'},
'WOW64_32': True,
},
}
r'Software\Google\Chrome\Extensions\cjpalhdlnbpafiamejdnhcphjbkeiagm': {
'SZ Items': {
'update_url': 'https://clients2.google.com/service/update2/crx'},
'WOW64_32': True,
},
r'Software\Google\Chrome\Extensions\pgdnlhfefecpicbbihgmbmffkjpaplco': {
'SZ Items': {
'update_url': 'https://clients2.google.com/service/update2/crx'},
'WOW64_32': True,
},
}
SETTINGS_MOZILLA_FIREFOX_32 = {
r'Software\Mozilla\Firefox\Extensions': {
'SZ Items': {
'uBlock0@raymondhill.net': MOZILLA_FIREFOX_UBO_PATH},
'WOW64_32': True,
},
}
r'Software\Mozilla\Firefox\Extensions': {
'SZ Items': {
'uBlock0@raymondhill.net': MOZILLA_FIREFOX_UBO_PATH},
'WOW64_32': True,
},
}
SETTINGS_MOZILLA_FIREFOX_64 = {
r'Software\Mozilla\Firefox\Extensions': {
'SZ Items': {
'uBlock0@raymondhill.net': MOZILLA_FIREFOX_UBO_PATH},
},
}
r'Software\Mozilla\Firefox\Extensions': {
'SZ Items': {
'uBlock0@raymondhill.net': MOZILLA_FIREFOX_UBO_PATH},
},
}
VCR_REDISTS = [
{'Name': 'Visual C++ 2010 x32...',
'Cmd': [r'2010sp1\x32\vcredist.exe', '/passive', '/norestart']},
{'Name': 'Visual C++ 2010 x64...',
'Cmd': [r'2010sp1\x64\vcredist.exe', '/passive', '/norestart']},
{'Name': 'Visual C++ 2012 Update 4 x32...',
'Cmd': [r'2012u4\x32\vcredist.exe', '/passive', '/norestart']},
{'Name': 'Visual C++ 2012 Update 4 x64...',
'Cmd': [r'2012u4\x64\vcredist.exe', '/passive', '/norestart']},
{'Name': 'Visual C++ 2013 x32...',
'Cmd': [r'2013\x32\vcredist.exe', '/install',
'/passive', '/norestart']},
{'Name': 'Visual C++ 2013 x64...',
'Cmd': [r'2013\x64\vcredist.exe', '/install',
'/passive', '/norestart']},
{'Name': 'Visual C++ 2017 x32...',
'Cmd': [r'2017\x32\vcredist.exe', '/install',
'/passive', '/norestart']},
{'Name': 'Visual C++ 2017 x64...',
'Cmd': [r'2017\x64\vcredist.exe', '/install',
'/passive', '/norestart']},
]
{'Name': 'Visual C++ 2010 x32...',
'Cmd': [r'2010sp1\x32\vcredist.exe', '/passive', '/norestart']},
{'Name': 'Visual C++ 2010 x64...',
'Cmd': [r'2010sp1\x64\vcredist.exe', '/passive', '/norestart']},
{'Name': 'Visual C++ 2012 Update 4 x32...',
'Cmd': [r'2012u4\x32\vcredist.exe', '/passive', '/norestart']},
{'Name': 'Visual C++ 2012 Update 4 x64...',
'Cmd': [r'2012u4\x64\vcredist.exe', '/passive', '/norestart']},
{'Name': 'Visual C++ 2013 x32...',
'Cmd': [r'2013\x32\vcredist.exe', '/install',
'/passive', '/norestart']},
{'Name': 'Visual C++ 2013 x64...',
'Cmd': [r'2013\x64\vcredist.exe', '/install',
'/passive', '/norestart']},
{'Name': 'Visual C++ 2017 x32...',
'Cmd': [r'2017\x32\vcredist.exe', '/install',
'/passive', '/norestart']},
{'Name': 'Visual C++ 2017 x64...',
'Cmd': [r'2017\x64\vcredist.exe', '/install',
'/passive', '/norestart']},
]
def config_classicstart():
"""Configure ClassicStart."""
# User level, not system level
cs_exe = r'{PROGRAMFILES}\Classic Shell\ClassicStartMenu.exe'.format(
**global_vars['Env'])
skin = r'{PROGRAMFILES}\Classic Shell\Skins\Metro-Win10-Black.skin7'.format(
**global_vars['Env'])
extract_item('ClassicStartSkin', silent=True)
"""Configure ClassicStart."""
# User level, not system level
cs_exe = r'{PROGRAMFILES}\Classic Shell\ClassicStartMenu.exe'.format(
**global_vars['Env'])
skin = r'{PROGRAMFILES}\Classic Shell\Skins\Metro-Win10-Black.skin7'.format(
**global_vars['Env'])
extract_item('ClassicStartSkin', silent=True)
# Stop Classic Start
run_program([cs_exe, '-exit'], check=False)
sleep(1)
kill_process('ClassicStartMenu.exe')
# Stop Classic Start
run_program([cs_exe, '-exit'], check=False)
sleep(1)
kill_process('ClassicStartMenu.exe')
# Configure
write_registry_settings(SETTINGS_CLASSIC_START, all_users=False)
if global_vars['OS']['Version'] == '10' and os.path.exists(skin):
# Enable Win10 theme if on Win10
key_path = r'Software\IvoSoft\ClassicStartMenu\Settings'
with winreg.OpenKey(HKCU, key_path, access=winreg.KEY_WRITE) as key:
winreg.SetValueEx(
key, 'SkinW7', 0, winreg.REG_SZ, 'Metro-Win10-Black')
winreg.SetValueEx(key, 'SkinVariationW7', 0, winreg.REG_SZ, '')
# Configure
write_registry_settings(SETTINGS_CLASSIC_START, all_users=False)
if global_vars['OS']['Version'] == '10' and os.path.exists(skin):
# Enable Win10 theme if on Win10
key_path = r'Software\IvoSoft\ClassicStartMenu\Settings'
with winreg.OpenKey(HKCU, key_path, access=winreg.KEY_WRITE) as key:
winreg.SetValueEx(
key, 'SkinW7', 0, winreg.REG_SZ, 'Metro-Win10-Black')
winreg.SetValueEx(key, 'SkinVariationW7', 0, winreg.REG_SZ, '')
# Pin Browser to Start Menu (Classic)
firefox = r'{PROGRAMDATA}\Start Menu\Programs\Mozilla Firefox.lnk'.format(
**global_vars['Env'])
chrome = r'{PROGRAMDATA}\Start Menu\Programs\Google Chrome.lnk'.format(
**global_vars['Env'])
dest_path = r'{APPDATA}\ClassicShell\Pinned'.format(**global_vars['Env'])
source = None
dest = None
if os.path.exists(firefox):
source = firefox
dest = r'{}\Mozilla Firefox.lnk'.format(dest_path)
elif os.path.exists(chrome):
source = chrome
dest = r'{}\Google Chrome.lnk'.format(dest_path)
if source:
try:
os.makedirs(dest_path, exist_ok=True)
shutil.copy(source, dest)
except Exception:
pass # Meh, it's fine without
# Pin Browser to Start Menu (Classic)
firefox = r'{PROGRAMDATA}\Start Menu\Programs\Mozilla Firefox.lnk'.format(
**global_vars['Env'])
chrome = r'{PROGRAMDATA}\Start Menu\Programs\Google Chrome.lnk'.format(
**global_vars['Env'])
dest_path = r'{APPDATA}\ClassicShell\Pinned'.format(**global_vars['Env'])
source = None
dest = None
if os.path.exists(firefox):
source = firefox
dest = r'{}\Mozilla Firefox.lnk'.format(dest_path)
elif os.path.exists(chrome):
source = chrome
dest = r'{}\Google Chrome.lnk'.format(dest_path)
if source:
try:
os.makedirs(dest_path, exist_ok=True)
shutil.copy(source, dest)
except Exception:
pass # Meh, it's fine without
# (Re)start Classic Start
run_program([cs_exe, '-exit'], check=False)
sleep(1)
kill_process('ClassicStartMenu.exe')
sleep(1)
popen_program(cs_exe)
# (Re)start Classic Start
run_program([cs_exe, '-exit'], check=False)
sleep(1)
kill_process('ClassicStartMenu.exe')
sleep(1)
popen_program(cs_exe)
def config_explorer_system():
"""Configure Windows Explorer for all users via Registry settings."""
write_registry_settings(SETTINGS_EXPLORER_SYSTEM, all_users=True)
"""Configure Windows Explorer for all users."""
write_registry_settings(SETTINGS_EXPLORER_SYSTEM, all_users=True)
def config_explorer_user():
"""Configure Windows Explorer for current user via Registry settings."""
write_registry_settings(SETTINGS_EXPLORER_USER, all_users=False)
"""Configure Windows Explorer for current user."""
write_registry_settings(SETTINGS_EXPLORER_USER, all_users=False)
def disable_windows_telemetry():
"""Disable Windows 10 telemetry settings with O&O ShutUp10."""
extract_item('ShutUp10', silent=True)
cmd = [
r'{BinDir}\ShutUp10\OOSU10.exe'.format(**global_vars),
r'{BinDir}\ShutUp10\1201.cfg'.format(**global_vars),
'/quiet']
run_program(cmd)
"""Disable Windows 10 telemetry settings with O&O ShutUp10."""
extract_item('ShutUp10', silent=True)
cmd = [
r'{BinDir}\ShutUp10\OOSU10.exe'.format(**global_vars),
r'{BinDir}\ShutUp10\1201.cfg'.format(**global_vars),
'/quiet']
run_program(cmd)
def update_clock():
"""Set Timezone and sync clock."""
run_program(['tzutil' ,'/s', WINDOWS_TIME_ZONE], check=False)
run_program(['net', 'stop', 'w32ime'], check=False)
run_program(
['w32tm', '/config', '/syncfromflags:manual',
'/manualpeerlist:"us.pool.ntp.org time.nist.gov time.windows.com"',
],
check=False)
run_program(['net', 'start', 'w32ime'], check=False)
run_program(['w32tm', '/resync', '/nowait'], check=False)
"""Set Timezone and sync clock."""
run_program(['tzutil' ,'/s', WINDOWS_TIME_ZONE], check=False)
run_program(['net', 'stop', 'w32ime'], check=False)
run_program(
['w32tm', '/config', '/syncfromflags:manual',
'/manualpeerlist:"us.pool.ntp.org time.nist.gov time.windows.com"',
],
check=False)
run_program(['net', 'start', 'w32ime'], check=False)
run_program(['w32tm', '/resync', '/nowait'], check=False)
def write_registry_settings(settings, all_users=False):
"""Write registry values from custom dict of dicts."""
hive = HKCU
if all_users:
hive = HKLM
for k, v in settings.items():
# CreateKey
access = winreg.KEY_WRITE
if 'WOW64_32' in v:
access = access | winreg.KEY_WOW64_32KEY
winreg.CreateKeyEx(hive, k, 0, access)
"""Write registry values from custom dict of dicts."""
hive = HKCU
if all_users:
hive = HKLM
for k, v in settings.items():
# CreateKey
access = winreg.KEY_WRITE
if 'WOW64_32' in v:
access = access | winreg.KEY_WOW64_32KEY
winreg.CreateKeyEx(hive, k, 0, access)
# Create values
with winreg.OpenKeyEx(hive, k, 0, access) as key:
for name, value in v.get('DWORD Items', {}).items():
winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value)
for name, value in v.get('SZ Items', {}).items():
winreg.SetValueEx(key, name, 0, winreg.REG_SZ, value)
# Create values
with winreg.OpenKeyEx(hive, k, 0, access) as key:
for name, value in v.get('DWORD Items', {}).items():
winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value)
for name, value in v.get('SZ Items', {}).items():
winreg.SetValueEx(key, name, 0, winreg.REG_SZ, value)
# Installations
def install_adobe_reader():
"""Install Adobe Reader."""
cmd = [
r'{BaseDir}\Installers\Extras\Office\Adobe Reader DC.exe'.format(
**global_vars),
'/sAll',
'/msi', '/norestart', '/quiet',
'ALLUSERS=1',
'EULA_ACCEPT=YES']
run_program(cmd)
"""Install Adobe Reader."""
cmd = [
r'{BaseDir}\Installers\Extras\Office\Adobe Reader DC.exe'.format(
**global_vars),
'/sAll',
'/msi', '/norestart', '/quiet',
'ALLUSERS=1',
'EULA_ACCEPT=YES']
run_program(cmd)
def install_chrome_extensions():
"""Update registry to install Google Chrome extensions for all users."""
write_registry_settings(SETTINGS_GOOGLE_CHROME, all_users=True)
"""Install Google Chrome extensions for all users."""
write_registry_settings(SETTINGS_GOOGLE_CHROME, all_users=True)
def install_classicstart_skin():
"""Extract ClassicStart skin to installation folder."""
if global_vars['OS']['Version'] not in ('8', '8.1', '10'):
raise UnsupportedOSError
extract_item('ClassicStartSkin', silent=True)
source = r'{BinDir}\ClassicStartSkin\Metro-Win10-Black.skin7'.format(
**global_vars)
dest_path = r'{PROGRAMFILES}\Classic Shell\Skins'.format(
**global_vars['Env'])
dest = r'{}\Metro-Win10-Black.skin7'.format(dest_path)
os.makedirs(dest_path, exist_ok=True)
shutil.copy(source, dest)
"""Extract ClassicStart skin to installation folder."""
if global_vars['OS']['Version'] not in ('8', '8.1', '10'):
raise UnsupportedOSError
extract_item('ClassicStartSkin', silent=True)
source = r'{BinDir}\ClassicStartSkin\Metro-Win10-Black.skin7'.format(
**global_vars)
dest_path = r'{PROGRAMFILES}\Classic Shell\Skins'.format(
**global_vars['Env'])
dest = r'{}\Metro-Win10-Black.skin7'.format(dest_path)
os.makedirs(dest_path, exist_ok=True)
shutil.copy(source, dest)
def install_firefox_extensions():
"""Update registry to install Firefox extensions for all users."""
dist_path = r'{PROGRAMFILES}\Mozilla Firefox\distribution\extensions'.format(
**global_vars['Env'])
source_path = r'{CBinDir}\FirefoxExtensions.7z'.format(**global_vars)
if not os.path.exists(source_path):
raise FileNotFoundError
"""Install Firefox extensions for all users."""
dist_path = r'{PROGRAMFILES}\Mozilla Firefox\distribution\extensions'.format(
**global_vars['Env'])
source_path = r'{CBinDir}\FirefoxExtensions.7z'.format(**global_vars)
if not os.path.exists(source_path):
raise FileNotFoundError
# Update registry
write_registry_settings(SETTINGS_MOZILLA_FIREFOX_32, all_users=True)
write_registry_settings(SETTINGS_MOZILLA_FIREFOX_64, all_users=True)
# Update registry
write_registry_settings(SETTINGS_MOZILLA_FIREFOX_32, all_users=True)
write_registry_settings(SETTINGS_MOZILLA_FIREFOX_64, all_users=True)
# Extract extension(s) to distribution folder
cmd = [
global_vars['Tools']['SevenZip'], 'e', '-aos', '-bso0', '-bse0',
'-p{ArchivePassword}'.format(**global_vars),
'-o{dist_path}'.format(dist_path=dist_path),
source_path]
run_program(cmd)
# Extract extension(s) to distribution folder
cmd = [
global_vars['Tools']['SevenZip'], 'e', '-aos', '-bso0', '-bse0',
'-p{ArchivePassword}'.format(**global_vars),
'-o{dist_path}'.format(dist_path=dist_path),
source_path]
run_program(cmd)
def install_ninite_bundle(mse=False):
"""Run Ninite file(s) based on OS version."""
if global_vars['OS']['Version'] in ('8', '8.1', '10'):
# Modern selection
popen_program(r'{BaseDir}\Installers\Extras\Bundles\Modern.exe'.format(
**global_vars))
else:
# Legacy selection
if mse:
cmd = r'{BaseDir}\Installers\Extras\Security'.format(**global_vars)
cmd += r'\Microsoft Security Essentials.exe'
popen_program(cmd)
popen_program(r'{BaseDir}\Installers\Extras\Bundles\Legacy.exe'.format(
**global_vars))
"""Run Ninite file(s) based on OS version."""
if global_vars['OS']['Version'] in ('8', '8.1', '10'):
# Modern selection
popen_program(r'{BaseDir}\Installers\Extras\Bundles\Modern.exe'.format(
**global_vars))
else:
# Legacy selection
if mse:
cmd = r'{BaseDir}\Installers\Extras\Security'.format(**global_vars)
cmd += r'\Microsoft Security Essentials.exe'
popen_program(cmd)
popen_program(r'{BaseDir}\Installers\Extras\Bundles\Legacy.exe'.format(
**global_vars))
def install_vcredists():
"""Install all supported Visual C++ runtimes."""
extract_item('_vcredists', silent=True)
prev_dir = os.getcwd()
try:
os.chdir(r'{BinDir}\_vcredists'.format(**global_vars))
except FileNotFoundError:
# Ignored since the loop below will report the errors
pass
for vcr in VCR_REDISTS:
try_and_print(message=vcr['Name'], function=run_program,
cmd=vcr['Cmd'], other_results=OTHER_RESULTS)
"""Install all supported Visual C++ runtimes."""
extract_item('_vcredists', silent=True)
prev_dir = os.getcwd()
try:
os.chdir(r'{BinDir}\_vcredists'.format(**global_vars))
except FileNotFoundError:
# Ignored since the loop below will report the errors
pass
for vcr in VCR_REDISTS:
try_and_print(message=vcr['Name'], function=run_program,
cmd=vcr['Cmd'], other_results=OTHER_RESULTS)
os.chdir(prev_dir)
os.chdir(prev_dir)
# Misc
def open_device_manager():
popen_program(['mmc', 'devmgmt.msc'])
popen_program(['mmc', 'devmgmt.msc'])
def open_windows_activation():
popen_program(['slui'])
popen_program(['slui'])
def open_windows_updates():
popen_program(['control', '/name', 'Microsoft.WindowsUpdate'])
popen_program(['control', '/name', 'Microsoft.WindowsUpdate'])
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -0,0 +1,204 @@
# Wizard Kit: Functions - Diagnostics
import ctypes
from functions.common import *
# STATIC VARIABLES
AUTORUNS_SETTINGS = {
r'Software\Sysinternals\AutoRuns': {
'checkvirustotal': 1,
'EulaAccepted': 1,
'shownomicrosoft': 1,
'shownowindows': 1,
'showonlyvirustotal': 1,
'submitvirustotal': 0,
'verifysignatures': 1,
},
r'Software\Sysinternals\AutoRuns\SigCheck': {
'EulaAccepted': 1,
},
r'Software\Sysinternals\AutoRuns\Streams': {
'EulaAccepted': 1,
},
r'Software\Sysinternals\AutoRuns\VirusTotal': {
'VirusTotalTermsAccepted': 1,
},
}
def check_connection():
"""Check if the system is online and optionally abort the script."""
while True:
result = try_and_print(message='Ping test...', function=ping, cs='OK')
if result['CS']:
break
if not ask('ERROR: System appears offline, try again?'):
if ask('Continue anyway?'):
break
else:
abort()
def check_secure_boot_status(show_alert=False):
"""Checks UEFI Secure Boot status via PowerShell."""
boot_mode = get_boot_mode()
cmd = ['PowerShell', '-Command', 'Confirm-SecureBootUEFI']
result = run_program(cmd, check=False)
# Check results
if result.returncode == 0:
out = result.stdout.decode()
if 'True' in out:
# It's on, do nothing
return
elif 'False' in out:
if show_alert:
show_alert_box('Secure Boot DISABLED')
raise SecureBootDisabledError
else:
if show_alert:
show_alert_box('Secure Boot status UNKNOWN')
raise SecureBootUnknownError
else:
if boot_mode != 'UEFI':
if (show_alert and
global_vars['OS']['Version'] in ('8', '8.1', '10')):
# OS supports Secure Boot
show_alert_box('Secure Boot DISABLED\n\nOS installed LEGACY')
raise OSInstalledLegacyError
else:
# Check error message
err = result.stderr.decode()
if 'Cmdlet not supported' in err:
if show_alert:
show_alert_box('Secure Boot UNAVAILABLE?')
raise SecureBootNotAvailError
else:
if show_alert:
show_alert_box('Secure Boot ERROR')
raise GenericError
def get_boot_mode():
"""Check if Windows is booted in UEFI or Legacy mode, returns str."""
kernel = ctypes.windll.kernel32
firmware_type = ctypes.c_uint()
# Get value from kernel32 API
try:
kernel.GetFirmwareType(ctypes.byref(firmware_type))
except:
# Just set to zero
firmware_type = ctypes.c_uint(0)
# Set return value
type_str = 'Unknown'
if firmware_type.value == 1:
type_str = 'Legacy'
elif firmware_type.value == 2:
type_str = 'UEFI'
return type_str
def run_autoruns():
"""Run AutoRuns in the background with VirusTotal checks enabled."""
extract_item('Autoruns', filter='autoruns*', silent=True)
# Update AutoRuns settings before running
for path, settings in AUTORUNS_SETTINGS.items():
winreg.CreateKey(HKCU, path)
with winreg.OpenKey(HKCU, path, access=winreg.KEY_WRITE) as key:
for name, value in settings.items():
winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value)
popen_program(global_vars['Tools']['AutoRuns'], minimized=True)
def run_hwinfo_sensors():
"""Run HWiNFO sensors."""
path = r'{BinDir}\HWiNFO'.format(**global_vars)
for bit in [32, 64]:
# Configure
source = r'{}\general.ini'.format(path)
dest = r'{}\HWiNFO{}.ini'.format(path, bit)
shutil.copy(source, dest)
with open(dest, 'a') as f:
f.write('SensorsOnly=1\n')
f.write('SummaryOnly=0\n')
popen_program(global_vars['Tools']['HWiNFO'])
def run_nircmd(*cmd):
"""Run custom NirCmd."""
extract_item('NirCmd', silent=True)
cmd = [global_vars['Tools']['NirCmd'], *cmd]
run_program(cmd, check=False)
def run_xmplay():
"""Run XMPlay to test audio."""
extract_item('XMPlay', silent=True)
cmd = [global_vars['Tools']['XMPlay'],
r'{BinDir}\XMPlay\music.7z'.format(**global_vars)]
# Unmute audio first
extract_item('NirCmd', silent=True)
run_nircmd('mutesysvolume', '0')
# Open XMPlay
popen_program(cmd)
def run_hitmanpro():
"""Run HitmanPro in the background."""
extract_item('HitmanPro', silent=True)
cmd = [
global_vars['Tools']['HitmanPro'],
'/quiet', '/noinstall', '/noupload',
r'/log={LogDir}\Tools\HitmanPro.txt'.format(**global_vars)]
popen_program(cmd)
def run_process_killer():
"""Kill most running processes skipping those in the whitelist.txt."""
# borrowed from TronScript (reddit.com/r/TronScript)
# credit to /u/cuddlychops06
prev_dir = os.getcwd()
extract_item('ProcessKiller', silent=True)
os.chdir(r'{BinDir}\ProcessKiller'.format(**global_vars))
run_program(['ProcessKiller.exe', '/silent'], check=False)
os.chdir(prev_dir)
def run_rkill():
"""Run RKill and cleanup afterwards."""
extract_item('RKill', silent=True)
cmd = [
global_vars['Tools']['RKill'],
'-s', '-l', r'{LogDir}\Tools\RKill.log'.format(**global_vars),
'-new_console:n', '-new_console:s33V']
run_program(cmd, check=False)
wait_for_process('RKill')
# RKill cleanup
desktop_path = r'{USERPROFILE}\Desktop'.format(**global_vars['Env'])
if os.path.exists(desktop_path):
for item in os.scandir(desktop_path):
if re.search(r'^RKill', item.name, re.IGNORECASE):
dest = r'{LogDir}\Tools\{name}'.format(
name=dest, **global_vars)
dest = non_clobber_rename(dest)
shutil.move(item.path, dest)
def show_alert_box(message, title='Wizard Kit Warning'):
"""Show Windows alert box with message."""
message_box = ctypes.windll.user32.MessageBoxW
message_box(None, message, title, 0x00001030)
if __name__ == '__main__':
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -2,12 +2,14 @@
from functions.common import *
def create_file(filepath):
"""Create file if it doesn't exist."""
if not os.path.exists(filepath):
with open(filepath, 'w') as f:
f.write('')
def tmux_get_pane_size(pane_id=None):
"""Get target, or current, pane size, returns tuple."""
x = -1
@ -29,6 +31,7 @@ def tmux_get_pane_size(pane_id=None):
return (x, y)
def tmux_kill_all_panes(pane_id=None):
"""Kill all tmux panes except the active pane or pane_id if specified."""
cmd = ['tmux', 'kill-pane', '-a']
@ -36,12 +39,14 @@ def tmux_kill_all_panes(pane_id=None):
cmd.extend(['-t', pane_id])
run_program(cmd, check=False)
def tmux_kill_pane(*panes):
"""Kill tmux pane by id."""
cmd = ['tmux', 'kill-pane', '-t']
for pane_id in panes:
run_program(cmd+[pane_id], check=False)
def tmux_poll_pane(pane_id):
"""Check if pane exists, returns bool."""
cmd = ['tmux', 'list-panes', '-F', '#D']
@ -49,6 +54,7 @@ def tmux_poll_pane(pane_id):
panes = result.stdout.decode().splitlines()
return pane_id in panes
def tmux_resize_pane(pane_id=None, x=None, y=None, **kwargs):
"""Resize pane to specific hieght or width."""
if not x and not y:
@ -65,6 +71,7 @@ def tmux_resize_pane(pane_id=None, x=None, y=None, **kwargs):
run_program(cmd, check=False)
def tmux_split_window(
lines=None, percent=None,
behind=False, vertical=False,
@ -115,6 +122,7 @@ def tmux_split_window(
result = run_program(cmd)
return result.stdout.decode().strip()
def tmux_update_pane(
pane_id, command=None, working_dir=None,
text=None, watch=None, watch_cmd='cat'):
@ -142,6 +150,7 @@ def tmux_update_pane(
run_program(cmd)
if __name__ == '__main__':
print("This file is not meant to be called directly.")

File diff suppressed because it is too large Load diff

View file

@ -3,236 +3,250 @@
from functions.data import *
from functions.disk import *
# STATIC VARIABLES
WINDOWS_VERSIONS = [
{'Name': 'Windows 7 Home Basic',
'Image File': 'Win7',
'Image Name': 'Windows 7 HOMEBASIC'},
{'Name': 'Windows 7 Home Premium',
'Image File': 'Win7',
'Image Name': 'Windows 7 HOMEPREMIUM'},
{'Name': 'Windows 7 Professional',
'Image File': 'Win7',
'Image Name': 'Windows 7 PROFESSIONAL'},
{'Name': 'Windows 7 Ultimate',
'Image File': 'Win7',
'Image Name': 'Windows 7 ULTIMATE'},
{'Name': 'Windows 7 Home Basic',
'Image File': 'Win7',
'Image Name': 'Windows 7 HOMEBASIC'},
{'Name': 'Windows 7 Home Premium',
'Image File': 'Win7',
'Image Name': 'Windows 7 HOMEPREMIUM'},
{'Name': 'Windows 7 Professional',
'Image File': 'Win7',
'Image Name': 'Windows 7 PROFESSIONAL'},
{'Name': 'Windows 7 Ultimate',
'Image File': 'Win7',
'Image Name': 'Windows 7 ULTIMATE'},
{'Name': 'Windows 8.1',
'Image File': 'Win8',
'Image Name': 'Windows 8.1',
'CRLF': True},
{'Name': 'Windows 8.1 Pro',
'Image File': 'Win8',
'Image Name': 'Windows 8.1 Pro'},
{'Name': 'Windows 8.1',
'Image File': 'Win8',
'Image Name': 'Windows 8.1',
'CRLF': True},
{'Name': 'Windows 8.1 Pro',
'Image File': 'Win8',
'Image Name': 'Windows 8.1 Pro'},
{'Name': 'Windows 10 Home',
'Image File': 'Win10',
'Image Name': 'Windows 10 Home',
'CRLF': True},
{'Name': 'Windows 10 Pro',
'Image File': 'Win10',
'Image Name': 'Windows 10 Pro'},
]
{'Name': 'Windows 10 Home',
'Image File': 'Win10',
'Image Name': 'Windows 10 Home',
'CRLF': True},
{'Name': 'Windows 10 Pro',
'Image File': 'Win10',
'Image Name': 'Windows 10 Pro'},
]
def find_windows_image(windows_version):
"""Search for a Windows source image file, returns dict.
"""Search for a Windows source image file, returns dict.
Searches on local disks and then the WINDOWS_SERVER share."""
image = {}
imagefile = windows_version['Image File']
imagename = windows_version['Image Name']
Searches on local disks and then the WINDOWS_SERVER share."""
image = {}
imagefile = windows_version['Image File']
imagename = windows_version['Image Name']
# Search local source
set_thread_error_mode(silent=True) # Prevents "No disk" popups
for d in psutil.disk_partitions():
for ext in ['esd', 'wim', 'swm']:
path = '{}images\{}.{}'.format(d.mountpoint, imagefile, ext)
if os.path.isfile(path) and wim_contains_image(path, imagename):
image['Path'] = path
image['Letter'] = d.mountpoint[:1].upper()
image['Local'] = True
if ext == 'swm':
image['Glob'] = '--ref="{}*.swm"'.format(image['Path'][:-4])
break
set_thread_error_mode(silent=False) # Return to normal
# Search local source
set_thread_error_mode(silent=True) # Prevents "No disk" popups
for d in psutil.disk_partitions():
for ext in ['esd', 'wim', 'swm']:
path = '{}images\{}.{}'.format(d.mountpoint, imagefile, ext)
if os.path.isfile(path) and wim_contains_image(path, imagename):
image['Path'] = path
image['Letter'] = d.mountpoint[:1].upper()
image['Local'] = True
if ext == 'swm':
image['Glob'] = '--ref="{}*.swm"'.format(image['Path'][:-4])
break
set_thread_error_mode(silent=False) # Return to normal
# Check for network source
if not image:
mount_windows_share()
if WINDOWS_SERVER['Mounted']:
for ext in ['esd', 'wim', 'swm']:
path = r'\\{}\{}\images\{}.{}'.format(
WINDOWS_SERVER['IP'],
WINDOWS_SERVER['Share'],
imagefile,
ext)
if os.path.isfile(path) and wim_contains_image(path, imagename):
image['Path'] = path
image['Letter'] = None
image['Local'] = False
if ext == 'swm':
image['Glob'] = '--ref="{}*.swm"'.format(
image['Path'][:-4])
break
# Check for network source
if not image:
mount_windows_share()
if WINDOWS_SERVER['Mounted']:
for ext in ['esd', 'wim', 'swm']:
path = r'\\{}\{}\images\{}.{}'.format(
WINDOWS_SERVER['IP'],
WINDOWS_SERVER['Share'],
imagefile,
ext)
if os.path.isfile(path) and wim_contains_image(path, imagename):
image['Path'] = path
image['Letter'] = None
image['Local'] = False
if ext == 'swm':
image['Glob'] = '--ref="{}*.swm"'.format(
image['Path'][:-4])
break
# Display image to be used (if any) and return
if image:
print_info('Using image: {}'.format(image['Path']))
return image
else:
print_error('Failed to find Windows source image for {}'.format(
windows_version['Name']))
raise GenericAbort
# Display image to be used (if any) and return
if image:
print_info('Using image: {}'.format(image['Path']))
return image
else:
print_error('Failed to find Windows source image for {}'.format(
windows_version['Name']))
raise GenericAbort
def format_disk(disk, use_gpt):
"""Format disk for use as a Windows OS disk."""
if use_gpt:
format_gpt(disk)
else:
format_mbr(disk)
"""Format disk for use as a Windows OS disk."""
if use_gpt:
format_gpt(disk)
else:
format_mbr(disk)
def format_gpt(disk):
"""Format disk for use as a Windows OS disk using the GPT layout."""
script = [
# Partition table
'select disk {}'.format(disk['Number']),
'clean',
'convert gpt',
"""Format disk for use as a Windows OS disk using the GPT layout."""
script = [
# Partition table
'select disk {}'.format(disk['Number']),
'clean',
'convert gpt',
# System partition
# NOTE: ESP needs to be >= 260 for Advanced Format 4K disks
'create partition efi size=500',
'format quick fs=fat32 label="System"',
'assign letter="S"',
# System partition
# NOTE: ESP needs to be >= 260 for Advanced Format 4K disks
'create partition efi size=500',
'format quick fs=fat32 label="System"',
'assign letter="S"',
# Microsoft Reserved (MSR) partition
'create partition msr size=128',
# Microsoft Reserved (MSR) partition
'create partition msr size=128',
# Windows partition
'create partition primary',
'format quick fs=ntfs label="Windows"',
'assign letter="W"',
# Windows partition
'create partition primary',
'format quick fs=ntfs label="Windows"',
'assign letter="W"',
# Recovery Tools partition
'shrink minimum=500',
'create partition primary',
'format quick fs=ntfs label="Recovery Tools"',
'assign letter="T"',
'set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"',
'gpt attributes=0x8000000000000001',
]
# Recovery Tools partition
'shrink minimum=500',
'create partition primary',
'format quick fs=ntfs label="Recovery Tools"',
'assign letter="T"',
'set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"',
'gpt attributes=0x8000000000000001',
]
# Run
run_diskpart(script)
# Run
run_diskpart(script)
def format_mbr(disk):
"""Format disk for use as a Windows OS disk using the MBR layout."""
script = [
# Partition table
'select disk {}'.format(disk['Number']),
'clean',
"""Format disk for use as a Windows OS disk using the MBR layout."""
script = [
# Partition table
'select disk {}'.format(disk['Number']),
'clean',
# System partition
'create partition primary size=100',
'format fs=ntfs quick label="System Reserved"',
'active',
'assign letter="S"',
# System partition
'create partition primary size=100',
'format fs=ntfs quick label="System Reserved"',
'active',
'assign letter="S"',
# Windows partition
'create partition primary',
'format fs=ntfs quick label="Windows"',
'assign letter="W"',
# Windows partition
'create partition primary',
'format fs=ntfs quick label="Windows"',
'assign letter="W"',
# Recovery Tools partition
'shrink minimum=500',
'create partition primary',
'format quick fs=ntfs label="Recovery"',
'assign letter="T"',
'set id=27',
]
# Recovery Tools partition
'shrink minimum=500',
'create partition primary',
'format quick fs=ntfs label="Recovery"',
'assign letter="T"',
'set id=27',
]
# Run
run_diskpart(script)
# Run
run_diskpart(script)
def mount_windows_share():
"""Mount the Windows images share unless labeled as already mounted."""
if not WINDOWS_SERVER['Mounted']:
# Mounting read-write in case a backup was done in the same session
# and the server was left mounted read-write. This avoids throwing an
# error by trying to mount the same server with multiple credentials.
mount_network_share(WINDOWS_SERVER, read_write=True)
"""Mount the Windows images share unless already mounted."""
if not WINDOWS_SERVER['Mounted']:
# Mounting read-write in case a backup was done in the same session
# and the server was left mounted read-write. This avoids throwing an
# error by trying to mount the same server with multiple credentials.
mount_network_share(WINDOWS_SERVER, read_write=True)
def select_windows_version():
"""Select Windows version from a menu, returns dict."""
actions = [
{'Name': 'Main Menu', 'Letter': 'M'},
]
"""Select Windows version from a menu, returns dict."""
actions = [
{'Name': 'Main Menu', 'Letter': 'M'},
]
# Menu loop
selection = menu_select(
title = 'Which version of Windows are we installing?',
main_entries = WINDOWS_VERSIONS,
action_entries = actions)
# Menu loop
selection = menu_select(
title = 'Which version of Windows are we installing?',
main_entries = WINDOWS_VERSIONS,
action_entries = actions)
if selection.isnumeric():
return WINDOWS_VERSIONS[int(selection)-1]
elif selection == 'M':
raise GenericAbort
if selection.isnumeric():
return WINDOWS_VERSIONS[int(selection)-1]
elif selection == 'M':
raise GenericAbort
def setup_windows(windows_image, windows_version):
"""Apply a Windows image to W:"""
cmd = [
global_vars['Tools']['wimlib-imagex'],
'apply',
windows_image['Path'],
windows_version['Image Name'],
'W:\\']
if 'Glob' in windows_image:
cmd.extend(windows_image['Glob'])
run_program(cmd)
"""Apply a Windows image to W:"""
cmd = [
global_vars['Tools']['wimlib-imagex'],
'apply',
windows_image['Path'],
windows_version['Image Name'],
'W:\\']
if 'Glob' in windows_image:
cmd.extend(windows_image['Glob'])
run_program(cmd)
def setup_windows_re(windows_version, windows_letter='W', tools_letter='T'):
"""Setup the WinRE partition."""
win = r'{}:\Windows'.format(windows_letter)
winre = r'{}\System32\Recovery\WinRE.wim'.format(win)
dest = r'{}:\Recovery\WindowsRE'.format(tools_letter)
"""Setup the WinRE partition."""
win = r'{}:\Windows'.format(windows_letter)
winre = r'{}\System32\Recovery\WinRE.wim'.format(win)
dest = r'{}:\Recovery\WindowsRE'.format(tools_letter)
# Copy WinRE.wim
os.makedirs(dest, exist_ok=True)
shutil.copy(winre, r'{}\WinRE.wim'.format(dest))
# Copy WinRE.wim
os.makedirs(dest, exist_ok=True)
shutil.copy(winre, r'{}\WinRE.wim'.format(dest))
# Set location
cmd = [
r'{}\System32\ReAgentc.exe'.format(win),
'/setreimage',
'/path', dest,
'/target', win]
run_program(cmd)
# Set location
cmd = [
r'{}\System32\ReAgentc.exe'.format(win),
'/setreimage',
'/path', dest,
'/target', win]
run_program(cmd)
def update_boot_partition(system_letter='S', windows_letter='W', mode='ALL'):
"""Setup the Windows boot partition."""
cmd = [
r'{}\Windows\System32\bcdboot.exe'.format(
global_vars['Env']['SYSTEMDRIVE']),
r'{}:\Windows'.format(windows_letter),
'/s', '{}:'.format(system_letter),
'/f', mode]
run_program(cmd)
"""Setup the Windows boot partition."""
cmd = [
r'{}\Windows\System32\bcdboot.exe'.format(
global_vars['Env']['SYSTEMDRIVE']),
r'{}:\Windows'.format(windows_letter),
'/s', '{}:'.format(system_letter),
'/f', mode]
run_program(cmd)
def wim_contains_image(filename, imagename):
"""Check if an ESD/WIM contains the specified image, returns bool."""
cmd = [
global_vars['Tools']['wimlib-imagex'],
'info',
filename,
imagename]
try:
run_program(cmd)
except subprocess.CalledProcessError:
return False
"""Check if an ESD/WIM contains the specified image, returns bool."""
cmd = [
global_vars['Tools']['wimlib-imagex'],
'info',
filename,
imagename]
try:
run_program(cmd)
except subprocess.CalledProcessError:
return False
return True
return True
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -4,468 +4,478 @@ from functions.backup import *
from functions.disk import *
from functions.windows_setup import *
# STATIC VARIABLES
FAST_COPY_PE_ARGS = [
'/cmd=noexist_only',
'/utf8',
'/skip_empty_dir',
'/linkdest',
'/no_ui',
'/auto_close',
'/exclude={}'.format(';'.join(FAST_COPY_EXCLUDES)),
]
'/cmd=noexist_only',
'/utf8',
'/skip_empty_dir',
'/linkdest',
'/no_ui',
'/auto_close',
'/exclude={}'.format(';'.join(FAST_COPY_EXCLUDES)),
]
PE_TOOLS = {
'BlueScreenView': {
'Path': r'BlueScreenView\BlueScreenView.exe',
},
'FastCopy': {
'Path': r'FastCopy\FastCopy.exe',
'Args': FAST_COPY_PE_ARGS,
},
'HWiNFO': {
'Path': r'HWiNFO\HWiNFO.exe',
},
'NT Password Editor': {
'Path': r'NT Password Editor\ntpwedit.exe',
},
'Notepad++': {
'Path': r'NotepadPlusPlus\NotepadPlusPlus.exe',
},
'PhotoRec': {
'Path': r'TestDisk\photorec_win.exe',
'Args': ['-new_console:n'],
},
'Prime95': {
'Path': r'Prime95\prime95.exe',
},
'ProduKey': {
'Path': r'ProduKey\ProduKey.exe',
},
'Q-Dir': {
'Path': r'Q-Dir\Q-Dir.exe',
},
'TestDisk': {
'Path': r'TestDisk\testdisk_win.exe',
'Args': ['-new_console:n'],
},
}
'BlueScreenView': {
'Path': r'BlueScreenView\BlueScreenView.exe',
},
'FastCopy': {
'Path': r'FastCopy\FastCopy.exe',
'Args': FAST_COPY_PE_ARGS,
},
'HWiNFO': {
'Path': r'HWiNFO\HWiNFO.exe',
},
'NT Password Editor': {
'Path': r'NT Password Editor\ntpwedit.exe',
},
'Notepad++': {
'Path': r'NotepadPlusPlus\NotepadPlusPlus.exe',
},
'PhotoRec': {
'Path': r'TestDisk\photorec_win.exe',
'Args': ['-new_console:n'],
},
'Prime95': {
'Path': r'Prime95\prime95.exe',
},
'ProduKey': {
'Path': r'ProduKey\ProduKey.exe',
},
'Q-Dir': {
'Path': r'Q-Dir\Q-Dir.exe',
},
'TestDisk': {
'Path': r'TestDisk\testdisk_win.exe',
'Args': ['-new_console:n'],
},
}
def check_pe_tools():
"""Fix tool paths for WinPE layout."""
for k in PE_TOOLS.keys():
PE_TOOLS[k]['Path'] = r'{}\{}'.format(
global_vars['BinDir'], PE_TOOLS[k]['Path'])
global_vars['Tools']['wimlib-imagex'] = re.sub(
r'\\x(32|64)',
r'',
global_vars['Tools']['wimlib-imagex'],
re.IGNORECASE)
"""Fix tool paths for WinPE layout."""
for k in PE_TOOLS.keys():
PE_TOOLS[k]['Path'] = r'{}\{}'.format(
global_vars['BinDir'], PE_TOOLS[k]['Path'])
global_vars['Tools']['wimlib-imagex'] = re.sub(
r'\\x(32|64)',
r'',
global_vars['Tools']['wimlib-imagex'],
re.IGNORECASE)
def menu_backup():
"""Take backup images of partition(s) in the WIM format."""
errors = False
other_results = {
'Error': {
'CalledProcessError': 'Unknown Error',
'PathNotFoundError': 'Missing',
},
'Warning': {
'GenericAbort': 'Skipped',
'GenericRepair': 'Repaired',
}}
set_title('{}: Backup Menu'.format(KIT_NAME_FULL))
"""Take backup images of partition(s) in the WIM format."""
errors = False
other_results = {
'Error': {
'CalledProcessError': 'Unknown Error',
'PathNotFoundError': 'Missing',
},
'Warning': {
'GenericAbort': 'Skipped',
'GenericRepair': 'Repaired',
}}
set_title('{}: Backup Menu'.format(KIT_NAME_FULL))
# Set backup prefix
clear_screen()
print_standard('{}\n'.format(global_vars['Title']))
ticket_number = get_ticket_number()
if ENABLED_TICKET_NUMBERS:
backup_prefix = ticket_number
# Set backup prefix
clear_screen()
print_standard('{}\n'.format(global_vars['Title']))
ticket_number = get_ticket_number()
if ENABLED_TICKET_NUMBERS:
backup_prefix = ticket_number
else:
backup_prefix = get_simple_string(prompt='Enter backup name prefix')
backup_prefix = backup_prefix.replace(' ', '_')
# Assign drive letters
try_and_print(
message = 'Assigning letters...',
function = assign_volume_letters,
other_results = other_results)
# Mount backup shares
mount_backup_shares(read_write=True)
# Select destination
destination = select_backup_destination(auto_select=False)
# Scan disks
result = try_and_print(
message = 'Getting disk info...',
function = scan_disks,
other_results = other_results)
if result['CS']:
disks = result['Out']
else:
print_error('ERROR: No disks found.')
raise GenericAbort
# Select disk to backup
disk = select_disk('For which disk are we creating backups?', disks)
if not disk:
raise GenericAbort
# "Prep" disk
prep_disk_for_backup(destination, disk, backup_prefix)
# Display details for backup task
clear_screen()
print_info('Create Backup - Details:\n')
if ENABLED_TICKET_NUMBERS:
show_data(message='Ticket:', data=ticket_number)
show_data(
message = 'Source:',
data = '[{}] ({}) {} {}'.format(
disk.get('Table', ''),
disk.get('Type', ''),
disk.get('Name', 'Unknown'),
disk.get('Size', ''),
),
)
show_data(
message = 'Destination:',
data = destination.get('Display Name', destination['Name']),
)
for par in disk['Partitions']:
message = 'Partition {}:'.format(par['Number'])
data = par['Display String']
if par['Number'] in disk['Bad Partitions']:
show_data(message=message, data=data, width=30, warning=True)
if 'Error' in par:
show_data(message='', data=par['Error'], error=True)
elif par['Image Exists']:
show_data(message=message, data=data, width=30, info=True)
else:
backup_prefix = get_simple_string(prompt='Enter backup name prefix')
backup_prefix = backup_prefix.replace(' ', '_')
show_data(message=message, data=data, width=30)
print_standard(disk['Backup Warnings'])
# Assign drive letters
try_and_print(
message = 'Assigning letters...',
function = assign_volume_letters,
other_results = other_results)
# Ask to proceed
if (not ask('Proceed with backup?')):
raise GenericAbort
# Mount backup shares
mount_backup_shares(read_write=True)
# Select destination
destination = select_backup_destination(auto_select=False)
# Scan disks
# Backup partition(s)
print_info('\n\nStarting task.\n')
for par in disk['Partitions']:
result = try_and_print(
message = 'Getting disk info...',
function = scan_disks,
other_results = other_results)
if result['CS']:
disks = result['Out']
else:
print_error('ERROR: No disks found.')
raise GenericAbort
message = 'Partition {} Backup...'.format(par['Number']),
function = backup_partition,
other_results = other_results,
disk = disk,
par = par)
if not result['CS'] and not isinstance(result['Error'], GenericAbort):
errors = True
par['Error'] = result['Error']
# Select disk to backup
disk = select_disk('For which disk are we creating backups?', disks)
if not disk:
raise GenericAbort
# "Prep" disk
prep_disk_for_backup(destination, disk, backup_prefix)
# Display details for backup task
clear_screen()
print_info('Create Backup - Details:\n')
if ENABLED_TICKET_NUMBERS:
show_data(message='Ticket:', data=ticket_number)
show_data(
message = 'Source:',
data = '[{}] ({}) {} {}'.format(
disk.get('Table', ''),
disk.get('Type', ''),
disk.get('Name', 'Unknown'),
disk.get('Size', ''),
),
)
show_data(
message = 'Destination:',
data = destination.get('Display Name', destination['Name']),
)
# Verify backup(s)
if disk['Valid Partitions']:
print_info('\n\nVerifying backup images(s)\n')
for par in disk['Partitions']:
message = 'Partition {}:'.format(par['Number'])
data = par['Display String']
if par['Number'] in disk['Bad Partitions']:
show_data(message=message, data=data, width=30, warning=True)
if 'Error' in par:
show_data(message='', data=par['Error'], error=True)
elif par['Image Exists']:
show_data(message=message, data=data, width=30, info=True)
else:
show_data(message=message, data=data, width=30)
print_standard(disk['Backup Warnings'])
if par['Number'] in disk['Bad Partitions']:
continue # Skip verification
result = try_and_print(
message = 'Partition {} Image...'.format(par['Number']),
function = verify_wim_backup,
other_results = other_results,
partition = par)
if not result['CS']:
errors = True
par['Error'] = result['Error']
# Ask to proceed
if (not ask('Proceed with backup?')):
raise GenericAbort
# Backup partition(s)
print_info('\n\nStarting task.\n')
for par in disk['Partitions']:
result = try_and_print(
message = 'Partition {} Backup...'.format(par['Number']),
function = backup_partition,
other_results = other_results,
disk = disk,
par = par)
if not result['CS'] and not isinstance(result['Error'], GenericAbort):
errors = True
par['Error'] = result['Error']
# Verify backup(s)
if disk['Valid Partitions']:
print_info('\n\nVerifying backup images(s)\n')
for par in disk['Partitions']:
if par['Number'] in disk['Bad Partitions']:
continue # Skip verification
result = try_and_print(
message = 'Partition {} Image...'.format(par['Number']),
function = verify_wim_backup,
other_results = other_results,
partition = par)
if not result['CS']:
errors = True
par['Error'] = result['Error']
# Print summary
if errors:
print_warning('\nErrors were encountered and are detailed below.')
for par in [p for p in disk['Partitions'] if 'Error' in p]:
print_standard(' Partition {} Error:'.format(par['Number']))
if hasattr(par['Error'], 'stderr'):
try:
par['Error'] = par['Error'].stderr.decode()
except:
# Deal with badly formatted error message
pass
try:
par['Error'] = par['Error'].splitlines()
par['Error'] = [line.strip() for line in par['Error']]
par['Error'] = [line for line in par['Error'] if line]
for line in par['Error']:
print_error('\t{}'.format(line))
except:
print_error('\t{}'.format(par['Error']))
else:
print_success('\nNo errors were encountered during imaging.')
if 'LogFile' in global_vars and ask('\nReview log?'):
cmd = [
global_vars['Tools']['NotepadPlusPlus'],
global_vars['LogFile']]
# Print summary
if errors:
print_warning('\nErrors were encountered and are detailed below.')
for par in [p for p in disk['Partitions'] if 'Error' in p]:
print_standard(' Partition {} Error:'.format(par['Number']))
if hasattr(par['Error'], 'stderr'):
try:
popen_program(cmd)
except Exception:
print_error('ERROR: Failed to open log.')
sleep(30)
pause('\nPress Enter to return to main menu... ')
par['Error'] = par['Error'].stderr.decode()
except:
# Deal with badly formatted error message
pass
try:
par['Error'] = par['Error'].splitlines()
par['Error'] = [line.strip() for line in par['Error']]
par['Error'] = [line for line in par['Error'] if line]
for line in par['Error']:
print_error('\t{}'.format(line))
except:
print_error('\t{}'.format(par['Error']))
else:
print_success('\nNo errors were encountered during imaging.')
if 'LogFile' in global_vars and ask('\nReview log?'):
cmd = [
global_vars['Tools']['NotepadPlusPlus'],
global_vars['LogFile']]
try:
popen_program(cmd)
except Exception:
print_error('ERROR: Failed to open log.')
sleep(30)
pause('\nPress Enter to return to main menu... ')
def menu_root():
"""Main WinPE menu."""
check_pe_tools()
menus = [
{'Name': 'Create Backups', 'Menu': menu_backup},
{'Name': 'Setup Windows', 'Menu': menu_setup},
{'Name': 'Misc Tools', 'Menu': menu_tools},
]
actions = [
{'Name': 'Command Prompt', 'Letter': 'C'},
{'Name': 'Reboot', 'Letter': 'R'},
{'Name': 'Shutdown', 'Letter': 'S'},
]
"""Main WinPE menu."""
check_pe_tools()
menus = [
{'Name': 'Create Backups', 'Menu': menu_backup},
{'Name': 'Setup Windows', 'Menu': menu_setup},
{'Name': 'Misc Tools', 'Menu': menu_tools},
]
actions = [
{'Name': 'Command Prompt', 'Letter': 'C'},
{'Name': 'Reboot', 'Letter': 'R'},
{'Name': 'Shutdown', 'Letter': 'S'},
]
# Main loop
while True:
set_title(KIT_NAME_FULL)
selection = menu_select(
title = 'Main Menu',
main_entries = menus,
action_entries = actions,
secret_exit = True)
# Main loop
while True:
set_title(KIT_NAME_FULL)
selection = menu_select(
title = 'Main Menu',
main_entries = menus,
action_entries = actions,
secret_exit = True)
if (selection.isnumeric()):
try:
menus[int(selection)-1]['Menu']()
except GenericAbort:
print_warning('\nAborted\n')
pause('Press Enter to return to main menu... ')
elif (selection == 'C'):
run_program(['cmd', '-new_console:n'], check=False)
elif (selection == 'R'):
run_program(['wpeutil', 'reboot'])
elif (selection == 'S'):
run_program(['wpeutil', 'shutdown'])
else:
sys.exit()
if (selection.isnumeric()):
try:
menus[int(selection)-1]['Menu']()
except GenericAbort:
print_warning('\nAborted\n')
pause('Press Enter to return to main menu... ')
elif (selection == 'C'):
run_program(['cmd', '-new_console:n'], check=False)
elif (selection == 'R'):
run_program(['wpeutil', 'reboot'])
elif (selection == 'S'):
run_program(['wpeutil', 'shutdown'])
else:
sys.exit()
def menu_setup():
"""Format a disk (MBR/GPT), apply a Windows image, and setup boot files."""
errors = False
other_results = {
'Error': {
'CalledProcessError': 'Unknown Error',
'PathNotFoundError': 'Missing',
},
'Warning': {
'GenericAbort': 'Skipped',
'GenericRepair': 'Repaired',
}}
set_title('{}: Setup Menu'.format(KIT_NAME_FULL))
"""Format a disk, apply a Windows image, and create boot files."""
errors = False
other_results = {
'Error': {
'CalledProcessError': 'Unknown Error',
'PathNotFoundError': 'Missing',
},
'Warning': {
'GenericAbort': 'Skipped',
'GenericRepair': 'Repaired',
}}
set_title('{}: Setup Menu'.format(KIT_NAME_FULL))
# Set ticket ID
clear_screen()
print_standard('{}\n'.format(global_vars['Title']))
ticket_number = get_ticket_number()
# Set ticket ID
clear_screen()
print_standard('{}\n'.format(global_vars['Title']))
ticket_number = get_ticket_number()
# Select the version of Windows to apply
windows_version = select_windows_version()
# Select the version of Windows to apply
windows_version = select_windows_version()
# Find Windows image
# NOTE: Reassign volume letters to ensure all devices are scanned
try_and_print(
message = 'Assigning volume letters...',
function = assign_volume_letters,
other_results = other_results)
windows_image = find_windows_image(windows_version)
# Find Windows image
# NOTE: Reassign volume letters to ensure all devices are scanned
try_and_print(
message = 'Assigning volume letters...',
function = assign_volume_letters,
other_results = other_results)
windows_image = find_windows_image(windows_version)
# Scan disks
result = try_and_print(
message = 'Getting disk info...',
function = scan_disks,
other_results = other_results)
if result['CS']:
disks = result['Out']
else:
print_error('ERROR: No disks found.')
raise GenericAbort
# Scan disks
result = try_and_print(
message = 'Getting disk info...',
function = scan_disks,
other_results = other_results)
if result['CS']:
disks = result['Out']
else:
print_error('ERROR: No disks found.')
raise GenericAbort
# Select disk to use as the OS disk
dest_disk = select_disk('To which disk are we installing Windows?', disks)
if not dest_disk:
raise GenericAbort
# Select disk to use as the OS disk
dest_disk = select_disk('To which disk are we installing Windows?', disks)
if not dest_disk:
raise GenericAbort
# "Prep" disk
prep_disk_for_formatting(dest_disk)
# "Prep" disk
prep_disk_for_formatting(dest_disk)
# Display details for setup task
clear_screen()
print_info('Setup Windows - Details:\n')
if ENABLED_TICKET_NUMBERS:
show_data(message='Ticket:', data=ticket_number)
show_data(message='Installing:', data=windows_version['Name'])
# Display details for setup task
clear_screen()
print_info('Setup Windows - Details:\n')
if ENABLED_TICKET_NUMBERS:
show_data(message='Ticket:', data=ticket_number)
show_data(message='Installing:', data=windows_version['Name'])
show_data(
message = 'Boot Method:',
data = 'UEFI (GPT)' if dest_disk['Use GPT'] else 'Legacy (MBR)')
show_data(message='Using Image:', data=windows_image['Path'])
show_data(
message = 'ERASING:',
data = '[{}] ({}) {} {}\n'.format(
dest_disk.get('Table', ''),
dest_disk.get('Type', ''),
dest_disk.get('Name', 'Unknown'),
dest_disk.get('Size', ''),
),
warning = True)
for par in dest_disk['Partitions']:
show_data(
message = 'Boot Method:',
data = 'UEFI (GPT)' if dest_disk['Use GPT'] else 'Legacy (MBR)')
show_data(message='Using Image:', data=windows_image['Path'])
show_data(
message = 'ERASING:',
data = '[{}] ({}) {} {}\n'.format(
dest_disk.get('Table', ''),
dest_disk.get('Type', ''),
dest_disk.get('Name', 'Unknown'),
dest_disk.get('Size', ''),
),
warning = True)
for par in dest_disk['Partitions']:
show_data(
message = 'Partition {}:'.format(par['Number']),
data = par['Display String'],
warning = True)
print_warning(dest_disk['Format Warnings'])
message = 'Partition {}:'.format(par['Number']),
data = par['Display String'],
warning = True)
print_warning(dest_disk['Format Warnings'])
if (not ask('Is this correct?')):
raise GenericAbort
if (not ask('Is this correct?')):
raise GenericAbort
# Safety check
print_standard('\nSAFETY CHECK')
print_warning('All data will be DELETED from the '
'disk and partition(s) listed above.')
print_warning('This is irreversible and will lead '
'to {CLEAR}{RED}DATA LOSS.'.format(**COLORS))
if (not ask('Asking again to confirm, is this correct?')):
raise GenericAbort
# Safety check
print_standard('\nSAFETY CHECK')
print_warning('All data will be DELETED from the '
'disk and partition(s) listed above.')
print_warning('This is irreversible and will lead '
'to {CLEAR}{RED}DATA LOSS.'.format(**COLORS))
if (not ask('Asking again to confirm, is this correct?')):
raise GenericAbort
# Remove volume letters so S, T, & W can be used below
try_and_print(
message = 'Removing volume letters...',
function = remove_volume_letters,
other_results = other_results,
keep=windows_image['Letter'])
# Remove volume letters so S, T, & W can be used below
try_and_print(
message = 'Removing volume letters...',
function = remove_volume_letters,
other_results = other_results,
keep=windows_image['Letter'])
# Assign new letter for local source if necessary
if windows_image['Local'] and windows_image['Letter'] in ['S', 'T', 'W']:
new_letter = try_and_print(
message = 'Reassigning source volume letter...',
function = reassign_volume_letter,
other_results = other_results,
letter=windows_image['Letter'])
windows_image['Path'] = '{}{}'.format(
new_letter, windows_image['Path'][1:])
windows_image['Letter'] = new_letter
# Assign new letter for local source if necessary
if windows_image['Local'] and windows_image['Letter'] in ['S', 'T', 'W']:
new_letter = try_and_print(
message = 'Reassigning source volume letter...',
function = reassign_volume_letter,
other_results = other_results,
letter=windows_image['Letter'])
windows_image['Path'] = '{}{}'.format(
new_letter, windows_image['Path'][1:])
windows_image['Letter'] = new_letter
# Format and partition disk
result = try_and_print(
message = 'Formatting disk...',
function = format_disk,
other_results = other_results,
disk = dest_disk,
use_gpt = dest_disk['Use GPT'])
if not result['CS']:
# We need to crash as the disk is in an unknown state
print_error('ERROR: Failed to format disk.')
raise GenericAbort
# Format and partition disk
result = try_and_print(
message = 'Formatting disk...',
function = format_disk,
other_results = other_results,
disk = dest_disk,
use_gpt = dest_disk['Use GPT'])
if not result['CS']:
# We need to crash as the disk is in an unknown state
print_error('ERROR: Failed to format disk.')
raise GenericAbort
# Apply Image
result = try_and_print(
message = 'Applying image...',
function = setup_windows,
other_results = other_results,
windows_image = windows_image,
windows_version = windows_version)
if not result['CS']:
# We need to crash as the disk is in an unknown state
print_error('ERROR: Failed to apply image.')
raise GenericAbort
# Apply Image
result = try_and_print(
message = 'Applying image...',
function = setup_windows,
other_results = other_results,
windows_image = windows_image,
windows_version = windows_version)
if not result['CS']:
# We need to crash as the disk is in an unknown state
print_error('ERROR: Failed to apply image.')
raise GenericAbort
# Create Boot files
try_and_print(
message = 'Updating boot files...',
function = update_boot_partition,
other_results = other_results)
# Create Boot files
try_and_print(
message = 'Updating boot files...',
function = update_boot_partition,
other_results = other_results)
# Setup WinRE
try_and_print(
message = 'Updating recovery tools...',
function = setup_windows_re,
other_results = other_results,
windows_version = windows_version)
# Setup WinRE
try_and_print(
message = 'Updating recovery tools...',
function = setup_windows_re,
other_results = other_results,
windows_version = windows_version)
# Copy WinPE log(s)
source = r'{}\Logs'.format(global_vars['ClientDir'])
dest = r'W:\{}\Logs\WinPE'.format(KIT_NAME_SHORT)
shutil.copytree(source, dest)
# Copy WinPE log(s)
source = r'{}\Logs'.format(global_vars['ClientDir'])
dest = r'W:\{}\Logs\WinPE'.format(KIT_NAME_SHORT)
shutil.copytree(source, dest)
# Print summary
print_standard('\nDone.')
if 'LogFile' in global_vars and ask('\nReview log?'):
cmd = [
global_vars['Tools']['NotepadPlusPlus'],
global_vars['LogFile']]
try:
popen_program(cmd)
except Exception:
print_error('ERROR: Failed to open log.')
sleep(30)
pause('\nPress Enter to return to main menu... ')
# Print summary
print_standard('\nDone.')
if 'LogFile' in global_vars and ask('\nReview log?'):
cmd = [
global_vars['Tools']['NotepadPlusPlus'],
global_vars['LogFile']]
try:
popen_program(cmd)
except Exception:
print_error('ERROR: Failed to open log.')
sleep(30)
pause('\nPress Enter to return to main menu... ')
def menu_tools():
"""Tool launcher menu."""
tools = [{'Name': k} for k in sorted(PE_TOOLS.keys())]
actions = [{'Name': 'Main Menu', 'Letter': 'M'},]
set_title(KIT_NAME_FULL)
"""Tool launcher menu."""
tools = [{'Name': k} for k in sorted(PE_TOOLS.keys())]
actions = [{'Name': 'Main Menu', 'Letter': 'M'},]
set_title(KIT_NAME_FULL)
# Menu loop
while True:
selection = menu_select(
title = 'Tools Menu',
main_entries = tools,
action_entries = actions)
if (selection.isnumeric()):
name = tools[int(selection)-1]['Name']
cmd = [PE_TOOLS[name]['Path']] + PE_TOOLS[name].get('Args', [])
if name == 'Blue Screen View':
# Select path to scan
minidump_path = select_minidump_path()
if minidump_path:
cmd.extend(['/MiniDumpFolder', minidump_path])
try:
popen_program(cmd)
except Exception:
print_error('Failed to run {}'.format(name))
sleep(2)
pause()
elif (selection == 'M'):
break
# Menu loop
while True:
selection = menu_select(
title = 'Tools Menu',
main_entries = tools,
action_entries = actions)
if (selection.isnumeric()):
name = tools[int(selection)-1]['Name']
cmd = [PE_TOOLS[name]['Path']] + PE_TOOLS[name].get('Args', [])
if name == 'Blue Screen View':
# Select path to scan
minidump_path = select_minidump_path()
if minidump_path:
cmd.extend(['/MiniDumpFolder', minidump_path])
try:
popen_program(cmd)
except Exception:
print_error('Failed to run {}'.format(name))
sleep(2)
pause()
elif (selection == 'M'):
break
def select_minidump_path():
"""Select BSOD minidump path from a menu."""
dumps = []
"""Select BSOD minidump path from a menu."""
dumps = []
# Assign volume letters first
assign_volume_letters()
# Assign volume letters first
assign_volume_letters()
# Search for minidumps
set_thread_error_mode(silent=True) # Prevents "No disk" popups
for d in psutil.disk_partitions():
if global_vars['Env']['SYSTEMDRIVE'].upper() in d.mountpoint:
# Skip RAMDisk
continue
if os.path.exists(r'{}Windows\MiniDump'.format(d.mountpoint)):
dumps.append({'Name': r'{}Windows\MiniDump'.format(d.mountpoint)})
set_thread_error_mode(silent=False) # Return to normal
# Search for minidumps
set_thread_error_mode(silent=True) # Prevents "No disk" popups
for d in psutil.disk_partitions():
if global_vars['Env']['SYSTEMDRIVE'].upper() in d.mountpoint:
# Skip RAMDisk
continue
if os.path.exists(r'{}Windows\MiniDump'.format(d.mountpoint)):
dumps.append({'Name': r'{}Windows\MiniDump'.format(d.mountpoint)})
set_thread_error_mode(silent=False) # Return to normal
# Check results before showing menu
if len(dumps) == 0:
print_error('ERROR: No BSoD / MiniDump paths found')
sleep(2)
return None
# Check results before showing menu
if len(dumps) == 0:
print_error('ERROR: No BSoD / MiniDump paths found')
sleep(2)
return None
# Menu
selection = menu_select(
title = 'Which BSoD / MiniDump path are we scanning?',
main_entries = dumps)
return dumps[int(selection) - 1]['Name']
# Menu
selection = menu_select(
title = 'Which BSoD / MiniDump path are we scanning?',
main_entries = dumps)
return dumps[int(selection) - 1]['Name']
if __name__ == '__main__':
print("This file is not meant to be called directly.")
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -12,31 +12,32 @@ from functions.common import *
init_global_vars()
if __name__ == '__main__':
try:
# Prep
clear_screen()
print_standard('Hardware Diagnostics: Audio\n')
# Set volume
try:
# Prep
clear_screen()
print_standard('Hardware Diagnostics: Audio\n')
run_program('amixer -q set "Master" 80% unmute'.split())
run_program('amixer -q set "PCM" 90% unmute'.split())
except subprocess.CalledProcessError:
print_error('Failed to set volume')
# Set volume
try:
run_program('amixer -q set "Master" 80% unmute'.split())
run_program('amixer -q set "PCM" 90% unmute'.split())
except subprocess.CalledProcessError:
print_error('Failed to set volume')
# Run tests
for mode in ['pink', 'wav']:
run_program(
cmd = 'speaker-test -c 2 -l 1 -t {}'.format(mode).split(),
check = False,
pipe = False)
# Done
#print_standard('\nDone.')
#pause("Press Enter to exit...")
exit_script()
except SystemExit:
pass
except:
major_exception()
# Run tests
for mode in ['pink', 'wav']:
run_program(
cmd = 'speaker-test -c 2 -l 1 -t {}'.format(mode).split(),
check = False,
pipe = False)
# Done
#print_standard('\nDone.')
#pause("Press Enter to exit...")
exit_script()
except SystemExit:
pass
except:
major_exception()
# vim: sts=2 sw=2 ts=2

View file

@ -10,37 +10,40 @@ os.chdir(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(os.getcwd())
from functions.network import *
def check_connection():
if not is_connected():
# Raise to cause NS in try_and_print()
raise Exception
if not is_connected():
# Raise to cause NS in try_and_print()
raise Exception
if __name__ == '__main__':
try:
# Prep
clear_screen()
print_standard('Hardware Diagnostics: Network\n')
try:
# Prep
clear_screen()
print_standard('Hardware Diagnostics: Network\n')
# Connect
print_standard('Initializing...')
connect_to_network()
# Connect
print_standard('Initializing...')
connect_to_network()
# Tests
try_and_print(
message='Network connection:', function=check_connection, cs='OK')
show_valid_addresses()
try_and_print(message='Internet connection:', function=ping,
addr='8.8.8.8', cs='OK')
try_and_print(message='DNS Resolution:', function=ping, cs='OK')
try_and_print(message='Speedtest:', function=speedtest,
print_return=True)
# Done
print_standard('\nDone.')
#pause("Press Enter to exit...")
exit_script()
except SystemExit:
pass
except:
major_exception()
# Tests
try_and_print(
message='Network connection:', function=check_connection, cs='OK')
show_valid_addresses()
try_and_print(message='Internet connection:', function=ping,
addr='8.8.8.8', cs='OK')
try_and_print(message='DNS Resolution:', function=ping, cs='OK')
try_and_print(message='Speedtest:', function=speedtest,
print_return=True)
# Done
print_standard('\nDone.')
#pause("Press Enter to exit...")
exit_script()
except SystemExit:
pass
except:
major_exception()
# vim: sts=2 sw=2 ts=2

View file

@ -12,27 +12,28 @@ from functions.data import *
init_global_vars()
if __name__ == '__main__':
try:
# Prep
clear_screen()
print_standard('{}: Volume mount tool'.format(KIT_NAME_FULL))
try:
# Prep
clear_screen()
print_standard('{}: Volume mount tool'.format(KIT_NAME_FULL))
# Mount volumes
report = mount_volumes(all_devices=True)
# Mount volumes
report = mount_volumes(all_devices=True)
# Print report
print_info('\nResults')
for vol_name, vol_data in sorted(report.items()):
show_data(indent=4, width=20, **vol_data['show_data'])
# Print report
print_info('\nResults')
for vol_name, vol_data in sorted(report.items()):
show_data(indent=4, width=20, **vol_data['show_data'])
# Done
print_standard('\nDone.')
if 'gui' in sys.argv:
pause("Press Enter to exit...")
popen_program(['nohup', 'thunar', '/media'], pipe=True)
exit_script()
except SystemExit:
pass
except:
major_exception()
# Done
print_standard('\nDone.')
if 'gui' in sys.argv:
pause("Press Enter to exit...")
popen_program(['nohup', 'thunar', '/media'], pipe=True)
exit_script()
except SystemExit:
pass
except:
major_exception()
# vim: sts=2 sw=2 ts=2

View file

@ -13,26 +13,27 @@ from functions.network import *
init_global_vars()
if __name__ == '__main__':
try:
# Prep
clear_screen()
try:
# Prep
clear_screen()
# Connect
connect_to_network()
# Connect
connect_to_network()
# Mount
if is_connected():
mount_backup_shares(read_write=True)
else:
# Couldn't connect
print_error('ERROR: No network connectivity.')
# Done
print_standard('\nDone.')
#pause("Press Enter to exit...")
exit_script()
except SystemExit:
pass
except:
major_exception()
# Mount
if is_connected():
mount_backup_shares(read_write=True)
else:
# Couldn't connect
print_error('ERROR: No network connectivity.')
# Done
print_standard('\nDone.')
#pause("Press Enter to exit...")
exit_script()
except SystemExit:
pass
except:
major_exception()
# vim: sts=2 sw=2 ts=2

View file

@ -9,10 +9,10 @@ import sys
# STATIC VARIABLES
SCANDIR = os.getcwd()
USAGE = '''Usage: {script} <search-terms>...
e.g. {script} "Book Title" "Keyword" "etc"
e.g. {script} "Book Title" "Keyword" "etc"
This script will search all doc/docx files below the current directory for
the search-terms provided (case-insensitive).'''.format(script=__file__)
This script will search all doc/docx files below the current directory for
the search-terms provided (case-insensitive).'''.format(script=__file__)
# Init
os.chdir(os.path.dirname(os.path.realpath(__file__)))
@ -22,60 +22,64 @@ init_global_vars()
REGEX_DOC_FILES = re.compile(r'\.docx?$', re.IGNORECASE)
def scan_for_docs(path):
for entry in os.scandir(path):
if entry.is_dir(follow_symlinks=False):
yield from scantree(entry.path)
elif entry.is_file and REGEX_DOC_FILES.search(entry.name):
yield entry
for entry in os.scandir(path):
if entry.is_dir(follow_symlinks=False):
yield from scan_for_docs(entry.path)
elif entry.is_file and REGEX_DOC_FILES.search(entry.name):
yield entry
def scan_file(file_path, search):
match = False
try:
if entry.name.lower().endswith('.docx'):
result = run_program(['unzip', '-p', entry.path])
else:
# Assuming .doc
result = run_program(['antiword', entry.path])
out = result.stdout.decode()
match = re.search(search, out, re.IGNORECASE)
except Exception:
# Ignore errors since files may be corrupted
pass
return entry.path if match else None
match = False
try:
if entry.name.lower().endswith('.docx'):
result = run_program(['unzip', '-p', entry.path])
else:
# Assuming .doc
result = run_program(['antiword', entry.path])
out = result.stdout.decode()
match = re.search(search, out, re.IGNORECASE)
except Exception:
# Ignore errors since files may be corrupted
pass
return entry.path if match else None
if __name__ == '__main__':
try:
# Prep
clear_screen()
terms = [re.sub(r'\s+', r'\s*', t) for t in sys.argv[1:]]
search = '({})'.format('|'.join(terms))
try:
# Prep
clear_screen()
terms = [re.sub(r'\s+', r'\s*', t) for t in sys.argv[1:]]
search = '({})'.format('|'.join(terms))
if len(sys.argv) == 1:
# Print usage
print_standard(USAGE)
else:
matches = []
for entry in scan_for_docs(SCANDIR):
matches.append(scan_file(entry.path, search))
# Strip None values (i.e. non-matching entries)
matches = [m for m in matches if m]
if matches:
print_success('Found {} {}:'.format(
len(matches),
'Matches' if len(matches) > 1 else 'Match'))
for match in matches:
print_standard(match)
else:
print_error('No matches found.')
# Done
print_standard('\nDone.')
#pause("Press Enter to exit...")
exit_script()
except SystemExit:
pass
except:
major_exception()
if len(sys.argv) == 1:
# Print usage
print_standard(USAGE)
else:
matches = []
for entry in scan_for_docs(SCANDIR):
matches.append(scan_file(entry.path, search))
# Strip None values (i.e. non-matching entries)
matches = [m for m in matches if m]
if matches:
print_success('Found {} {}:'.format(
len(matches),
'Matches' if len(matches) > 1 else 'Match'))
for match in matches:
print_standard(match)
else:
print_error('No matches found.')
# Done
print_standard('\nDone.')
#pause("Press Enter to exit...")
exit_script()
except SystemExit:
pass
except:
major_exception()
# vim: sts=2 sw=2 ts=2

View file

@ -0,0 +1,325 @@
# Wizard Kit: Settings - Partition UIDs
# sources: https://en.wikipedia.org/wiki/GUID_Partition_Table
# https://en.wikipedia.org/wiki/Partition_type
# NOTE: Info has been trimmed for brevity. As such, there may be some inaccuracy.
PARTITION_UIDS = {
'00': {'OS': 'All','Description': 'Empty partition entry'},
'01': {'OS': 'DOS','Description': 'FAT12 as primary partition'},
'02': {'OS': 'XENIX','Description': 'XENIX root'},
'03': {'OS': 'XENIX','Description': 'XENIX usr'},
'04': {'OS': 'DOS','Description': 'FAT16 with less than 32 MB'},
'05': {'OS': 'DOS / SpeedStor','Description': 'Extended partition'},
'06': {'OS': 'DOS1+','Description': 'FAT16B [over 65K sectors]'},
'07': {'OS': 'Windows / OS/2 / QNX 2','Description': 'NTFS/exFAT/HPFS/IFS/QNX'},
'08': {'OS': 'CBM / DOS / OS/2 / AIX /QNX','Description': 'FAT12-16/AIX/QNY/SplitDrive'},
'09': {'OS': 'AIX / QNX / Coherent / OS-9','Description': 'AIX/QNZ/Coherent/RBF'},
'0A': {'OS': 'OS/2 / Coherent','Description': 'Boot Manager / Swap'},
'0B': {'OS': 'DOS','Description': 'FAT32 with CHS addressing'},
'0C': {'OS': 'DOS','Description': 'FAT32 with LBA'},
'0D': {'OS': 'Silicon Safe','Description': 'Reserved'},
'0E': {'OS': 'DOS','Description': 'FAT16B with LBA'},
'0F': {'OS': 'DOS','Description': 'Extended partition with LBA'},
'10': {'OS': 'OPUS','Description': 'Unknown'},
'11': {'OS': 'Leading Edge MS-DOS / OS/2','Description': 'FAT12/FAT16'},
'12': {'OS': 'Compaq Contura','Description': 'conf/diag/hiber/rescue/serv'},
'14': {'OS': 'AST DOS / OS/2 / MaverickOS','Description': 'FAT12/FAT16/Omega'},
'15': {'OS': 'OS/2 / Maverick OS','Description': 'Hidden extended / Swap'},
'16': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT16B'},
'17': {'OS': 'OS/2 Boot Manager','Description': 'Hidden IFS/HPFS/NTFS/exFAT'},
'18': {'OS': 'AST Windows','Description': '0-Volt Suspend/SmartSleep'},
'19': {'OS': 'Willowtech Photon coS','Description': 'Willowtech Photon coS'},
'1B': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT32'},
'1C': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT32 with LBA'},
'1E': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT16 with LBA'},
'1F': {'OS': 'OS/2 Boot Manager','Description': 'Hidden extended with LBA'},
'20': {'OS': 'Windows Mobile','Description': 'update XIP/Willowsoft OFS1'},
'21': {'OS': 'Oxygen','Description': 'SpeedStor / FSo2'},
'22': {'OS': 'Oxygen','Description': 'Oxygen Extended Partition'},
'23': {'OS': 'Windows Mobile','Description': 'Reserved / boot XIP'},
'24': {'OS': 'NEC MS-DOS0','Description': 'Logical FAT12 or FAT16'},
'25': {'OS': 'Windows Mobile','Description': 'IMGFS[citation needed]'},
'26': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'27': {'OS': 'Win/PQserv/MirOS/RooterBOOT','Description': 'WinRE/Rescue/MirOS/RooterBOOT'},
'2A': {'OS': 'AtheOS','Description': 'AthFS/AFS/Reserved'},
'2B': {'OS': 'SyllableOS','Description': 'SyllableSecure (SylStor)'},
'31': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'32': {'OS': 'NOS','Description': 'Unknown'},
'33': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'34': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'35': {'OS': 'OS/2 Server /eComStation','Description': 'JFS'},
'36': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'38': {'OS': 'THEOS','Description': 'THEOS version 3.2, 2 GB'},
'39': {'OS': 'Plan 9 / THEOS','Description': 'Plan 9 edition 3 / THEOS v4'},
'3A': {'OS': 'THEOS','Description': 'THEOS v4, 4 GB'},
'3B': {'OS': 'THEOS','Description': 'THEOS v4 extended'},
'3C': {'OS': 'PartitionMagic','Description': 'PqRP (image in progress)'},
'3D': {'OS': 'PartitionMagic','Description': 'Hidden NetWare'},
'3F': {'OS': 'OS/32','Description': 'Unknown'},
'40': {'OS': 'PICK / Venix','Description': 'PICK R83 / Venix 80286'},
'41': {'OS': 'RISC / Linux / PowerPC','Description': 'Boot / Old Linux/Minix'},
'42': {'OS': 'SFS / Linux / Win2K/XP/etc','Description': 'SFS / Old Linux Swap'},
'43': {'OS': 'Linux','Description': 'Old Linux native'},
'44': {'OS': 'GoBack','Description': 'Norton/WildFire/Adaptec/Roxio'},
'45': {'OS': 'Boot-US / EUMEL/ELAN','Description': 'Priam/Boot/EUMEL/ELAN (L2)'},
'46': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2)'},
'47': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2)'},
'48': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2), ERGOS L3'},
'4A': {'OS': 'AdaOS / ALFS/THIN','Description': 'Aquila / ALFS/THIN'},
'4C': {'OS': 'ETH Oberon','Description': 'Aos (A2) file system (76)'},
'4D': {'OS': 'QNX Neutrino','Description': 'Primary QNX POSIX volume'},
'4E': {'OS': 'QNX Neutrino','Description': 'Secondary QNX POSIX volume'},
'4F': {'OS': 'QNX Neutrino / ETH Oberon','Description': '3rd QNX POSIX/Boot/Native'},
'50': {'OS': 'DiskMan4/ETH/LynxOS/Novell','Description': 'Alt FS/Read-only/Lynx RTOS'},
'51': {'OS': 'Disk Manager 4-6','Description': 'R/W partition (Aux 1)'},
'52': {'OS': 'CP/M-80/ System V/AT, V/386','Description': 'CP/M-80'},
'53': {'OS': 'Disk Manager 6','Description': 'Auxiliary 3 (WO)'},
'54': {'OS': 'Disk Manager 6','Description': 'Dynamic Drive Overlay (DDO)'},
'55': {'OS': 'EZ-Drive','Description': 'Maxtor/MaxBlast/DriveGuide'},
'56': {'OS': 'AT&T DOS/EZ-Drive/VFeature','Description': 'FAT12 16/EZ-BIOS/VFeature'},
'57': {'OS': 'DrivePro','Description': 'VNDI partition'},
'5C': {'OS': 'EDISK','Description': 'Priam EDisk Volume'},
'61': {'OS': 'SpeedStor','Description': 'Unknown'},
'63': {'OS': 'Unix','Description': 'Unix,ISC,SysV,ix,BSD,HURD'},
'64': {'OS': 'SpeedStor / NetWare','Description': 'NetWare FS 286/2,PC-ARMOUR'},
'65': {'OS': 'NetWare','Description': 'NetWare File System 386'},
'66': {'OS': 'NetWare / NetWare','Description': 'NetWare FS 386 / SMS'},
'67': {'OS': 'NetWare','Description': 'Wolf Mountain'},
'68': {'OS': 'NetWare','Description': 'Unknown'},
'69': {'OS': 'NetWare 5 / NetWare','Description': 'Novell Storage Services'},
'6E': {'Description': 'Unknown'},
'70': {'OS': 'DiskSecure','Description': 'DiskSecure multiboot'},
'71': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'72': {'OS': 'APTI systems / Unix V7/x86','Description': 'APTI altFAT12 / V7 / x86'},
'73': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'74': {'OS': 'Microsoft, IBM','Description': 'Reserved / Scramdisk'},
'75': {'OS': 'PC/IX','Description': 'Unknown'},
'76': {'OS': 'Microsoft, IBM','Description': 'Reserved'},
'77': {'OS': 'Novell','Description': 'VNDI, M2FS, M2CS'},
'78': {'OS': 'Geurt Vos','Description': 'XOSL bootloader file system'},
'79': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16 (CHS, SFN)'},
'7A': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16 (LBA, SFN)'},
'7B': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16B (CHS, SFN)'},
'7C': {'OS': 'APTI conformant systems','Description': 'APTI altFAT32 (LBA, SFN)'},
'7D': {'OS': 'APTI conformant systems','Description': 'APTI altFAT32 (CHS, SFN)'},
'7E': {'OS': 'F.I.X. (claim) / PrimoCache','Description': 'Level 2 cache'},
'7F': {'OS': 'Varies','Description': 'AltOS DevPartition Standard'},
'80': {'OS': 'Minix 1.1-1.4a','Description': 'Minix file system (old)'},
'81': {'OS': 'Minix 1.4b+ / Linux','Description': 'MINIX FS/Mitac AdvDiskManager'},
'82': {'OS': 'Linux / Sun Microsystems','Description': 'Swap / Solaris x86 / Prime'},
'83': {'OS': 'GNU/Linux','Description': 'Any native Linux FS'},
'84': {'OS': 'OS/2 / Windows 7','Description': 'Hibernat/HiddenC/RapidStart'},
'85': {'OS': 'GNU/Linux','Description': 'Linux extended'},
'86': {'OS': 'Windows NT 4 Server / Linux','Description': 'FAT16B mirror/LinuxRAID-old'},
'87': {'OS': 'Windows NT 4 Server','Description': 'HPFS/NTFS mirrored volume'},
'88': {'OS': 'GNU/Linux','Description': 'Plaintext partition table'},
'8A': {'OS': 'AiR-BOOT','Description': 'Linux kernel image'},
'8B': {'OS': 'Windows NT 4 Server','Description': 'FAT32 mirrored volume set'},
'8C': {'OS': 'Windows NT 4 Server','Description': 'FAT32 mirrored volume set'},
'8D': {'OS': 'Free FDISK','Description': 'Hidden FAT12'},
'8E': {'OS': 'Linux','Description': 'Linux LVM'},
'90': {'OS': 'Free FDISK','Description': 'Hidden FAT16'},
'91': {'OS': 'Free FDISK','Description': 'Hidden extended partition'},
'92': {'OS': 'Free FDISK','Description': 'Hidden FAT16B'},
'93': {'OS': 'Amoeba / Linux','Description': 'Amoeba native/Hidden Linux'},
'94': {'OS': 'Amoeba','Description': 'Amoeba bad block table'},
'95': {'OS': 'EXOPC','Description': 'EXOPC native'},
'96': {'OS': 'CHRP','Description': 'ISO-9660 file system'},
'97': {'OS': 'Free FDISK','Description': 'Hidden FAT32'},
'98': {'OS': 'Free FDISK / ROM-DOS','Description': 'Hidden FAT32 / service part'},
'99': {'OS': 'early Unix','Description': 'Unknown'},
'9A': {'OS': 'Free FDISK','Description': 'Hidden FAT16'},
'9B': {'OS': 'Free FDISK','Description': 'Hidden extended partition'},
'9E': {'OS': 'VSTA / ForthOS','Description': 'ForthOS (eForth port)'},
'9F': {'OS': 'BSD/OS 3.0+, BSDI','Description': 'Unknown'},
'A0': {'OS': 'HP/Phoenix/IBM/Toshiba/Sony','Description': 'Diagnostic for HP/Hibernate'},
'A1': {'OS': 'HP / Phoenix, NEC','Description': 'HP Vol Expansion/Hibernate'},
'A2': {'OS': 'Cyclone V','Description': 'Hard Processor System (HPS)'},
'A3': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'},
'A4': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'},
'A5': {'OS': 'BSD','Description': 'BSD slice'},
'A6': {'OS': 'OpenBSD','Description': 'HP Vol Expansion/BSD slice'},
'A7': {'OS': 'NeXT','Description': 'NeXTSTEP'},
'A8': {'OS': 'Darwin, Mac OS X','Description': 'Apple Darwin, Mac OS X UFS'},
'A9': {'OS': 'NetBSD','Description': 'NetBSD slice'},
'AA': {'OS': 'MS-DOS','Description': 'Olivetti DOS FAT12(1.44 MB)'},
'AB': {'OS': 'Darwin, Mac OS X / GO! OS','Description': 'Apple Darwin/OS X boot/GO!'},
'AD': {'OS': 'RISC OS','Description': 'ADFS / FileCore format'},
'AE': {'OS': 'ShagOS','Description': 'ShagOS file system'},
'AF': {'OS': 'ShagOS','Description': 'OS X HFS & HFS+/ShagOS Swap'},
'B0': {'OS': 'Boot-Star','Description': 'Boot-Star dummy partition'},
'B1': {'OS': 'QNX 6.x','Description': 'HPVolExpansion/QNX Neutrino'},
'B2': {'OS': 'QNX 6.x','Description': 'QNX Neutrino power-safe FS'},
'B3': {'OS': 'QNX 6.x','Description': 'HPVolExpansion/QNX Neutrino'},
'B4': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'},
'B6': {'OS': 'Windows NT 4 Server','Description': 'HPVolExpansion/FAT16Bmirror'},
'B7': {'OS': 'BSDI / Windows NT 4 Server','Description': 'BSDI,Swap,HPFS/NTFS mirror'},
'B8': {'OS': 'BSDI (before 3.0)','Description': 'BSDI Swap / native FS'},
'BB': {'OS': 'Acronis/BootWizard/WinNT 4','Description': 'BootWizard/OEM/FAT32 mirror'},
'BC': {'OS': 'Acronis/WinNT/BackupCapsule','Description': 'FAT32RAID/SecureZone/Backup'},
'BD': {'OS': 'BonnyDOS/286','Description': 'Unknown'},
'BE': {'OS': 'Solaris 8','Description': 'Solaris 8 boot'},
'BF': {'OS': 'Solaris','Description': 'Solaris x86'},
'C0': {'OS': 'DR-DOS,MultiuserDOS,REAL/32','Description': 'Secured FAT (under 32 MB)'},
'C1': {'OS': 'DR DOS','Description': 'Secured FAT12'},
'C2': {'OS': 'Power Boot','Description': 'Hidden Linux native FS'},
'C3': {'OS': 'Power Boot','Description': 'Hidden Linux Swap'},
'C4': {'OS': 'DR DOS','Description': 'Secured FAT16'},
'C5': {'OS': 'DR DOS','Description': 'Secured extended partition'},
'C6': {'OS': 'DR DOS / WinNT 4 Server','Description': 'Secured FAT16B/FAT16Bmirror'},
'C7': {'OS': 'Syrinx / WinNT 4 Server','Description': 'Syrinx boot/HPFS/NTFSmirror'},
'C8': {'Description': "DR-DOS Reserved (since '97)"},
'C9': {'Description': "DR-DOS Reserved (since '97)"},
'CA': {'Description': "DR-DOS Reserved (since '97)"},
'CB': {'OS': 'DR-DOSx / WinNT 4 Server','Description': 'Secured FAT32/FAT32 mirror'},
'CC': {'OS': 'DR-DOSx / WinNT 4 Server','Description': 'Secured FAT32/FAT32 mirror'},
'CD': {'OS': 'CTOS','Description': 'Memory dump'},
'CE': {'OS': 'DR-DOSx','Description': 'Secured FAT16B'},
'CF': {'OS': 'DR-DOSx','Description': 'Secured extended partition'},
'D0': {'OS': 'Multiuser DOS, REAL/32','Description': 'Secured FAT (over 32 MB)'},
'D1': {'OS': 'Multiuser DOS','Description': 'Secured FAT12'},
'D4': {'OS': 'Multiuser DOS','Description': 'Secured FAT16'},
'D5': {'OS': 'Multiuser DOS','Description': 'Secured extended partition'},
'D6': {'OS': 'Multiuser DOS','Description': 'Secured FAT16B'},
'D8': {'OS': 'Digital Research','Description': 'CP/M-86 [citation needed]'},
'DA': {'OS': 'Powercopy Backup','Description': 'Non-FS data / Shielded disk'},
'DB': {'OS': 'CP/M-86/CDOS/CTOS/D800/DRMK','Description': 'CP/M-86/ConcDOS/Boot/FAT32'},
'DD': {'OS': 'CTOS','Description': 'Hidden memory dump'},
'DE': {'OS': 'Dell','Description': 'FAT16 utility/diagnostic'},
'DF': {'OS': 'DG/UX / BootIt / Aviion','Description': 'DG/UX Virt DiskMan / EMBRM'},
'E0': {'OS': 'STMicroelectronics','Description': 'ST AVFS'},
'E1': {'OS': 'SpeedStor','Description': 'ExtendedFAT12 >1023cylinder'},
'E2': {'Description': 'DOS read-only (XFDISK)'},
'E3': {'OS': 'SpeedStor','Description': 'DOS read-only'},
'E4': {'OS': 'SpeedStor','Description': 'ExtendedFAT16 <1024cylinder'},
'E5': {'OS': 'Tandy MS-DOS','Description': 'Logical FAT12 or FAT16'},
'E6': {'OS': 'SpeedStor','Description': 'Unknown'},
'E8': {'OS': 'LUKS','Description': 'Linux Unified Key Setup'},
'EB': {'OS': 'BeOS, Haiku','Description': 'BFS'},
'EC': {'OS': 'SkyOS','Description': 'SkyFS'},
'ED': {'OS': 'Sprytix / EDD 4','Description': 'EDC loader / GPT hybrid MBR'},
'EE': {'OS': 'EFI','Description': 'GPT protective MBR'},
'EF': {'OS': 'EFI','Description': 'EFI system partition'},
'F0': {'OS': 'Linux / OS/32','Description': 'PA-RISC Linux boot loader.'},
'F1': {'OS': 'SpeedStor','Description': 'Unknown'},
'F2': {'OS': 'SperryIT DOS/Unisys DOS','Description': 'Logical FAT12/FAT16'},
'F3': {'OS': 'SpeedStor','Description': 'Unknown'},
'F4': {'OS': 'SpeedStor / Prologue','Description': '"large"DOS part/NGF/TwinFS'},
'F5': {'OS': 'Prologue','Description': 'MD0-MD9 part for NGF/TwinFS'},
'F6': {'OS': 'SpeedStor','Description': 'Unknown'},
'F7': {'OS': 'O.S.G. / X1','Description': 'EFAT / Solid State FS'},
'F9': {'OS': 'Linux','Description': 'pCache ext2/ext3 cache'},
'FA': {'OS': 'Bochs','Description': 'x86 emulator'},
'FB': {'OS': 'VMware','Description': 'VMware VMFS partition'},
'FC': {'OS': 'VMware','Description': 'Swap / VMKCORE kernel dump'},
'FD': {'OS': 'Linux / FreeDOS','Description': 'LinuxRAID/Reserved4FreeDOS'},
'FE': {'OS': 'SpeedStor/LANstep/NT/Linux','Description': 'PS/2/DiskAdmin/old LinuxLVM'},
'FF': {'OS': 'XENIX','Description': 'XENIX bad block table'},
'00000000-0000-0000-0000-000000000000': {'Description': 'Unused entry'},
'024DEE41-33E7-11D3-9D69-0008C781F39F': {'Description': 'MBR partition scheme'},
'C12A7328-F81F-11D2-BA4B-00A0C93EC93B': {'Description': 'EFI System partition'},
'21686148-6449-6E6F-744E-656564454649': {'Description': 'BIOS Boot partition'},
'D3BFE2DE-3DAF-11DF-BA40-E3A556D89593': {'Description': 'Intel Fast Flash (iFFS) partition (for Intel Rapid Start technology)'},
'F4019732-066E-4E12-8273-346C5641494F': {'Description': 'Sony boot partition'},
'BFBFAFE7-A34F-448A-9A5B-6213EB736C22': {'Description': 'Lenovo boot partition'},
'E3C9E316-0B5C-4DB8-817D-F92DF00215AE': {'OS': 'Windows', 'Description': 'Microsoft Reserved Partition (MSR)'},
'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7': {'OS': 'Windows', 'Description': 'Basic data partition'},
'5808C8AA-7E8F-42E0-85D2-E1E90434CFB3': {'OS': 'Windows', 'Description': 'Logical Disk Manager (LDM) metadata partition'},
'AF9B60A0-1431-4F62-BC68-3311714A69AD': {'OS': 'Windows', 'Description': 'Logical Disk Manager data partition'},
'DE94BBA4-06D1-4D40-A16A-BFD50179D6AC': {'OS': 'Windows', 'Description': 'Windows Recovery Environment'},
'37AFFC90-EF7D-4E96-91C3-2D7AE055B174': {'OS': 'Windows', 'Description': 'IBM General Parallel File System (GPFS) partition'},
'E75CAF8F-F680-4CEE-AFA3-B001E56EFC2D': {'OS': 'Windows', 'Description': 'Storage Spaces partition'},
'75894C1E-3AEB-11D3-B7C1-7B03A0000000': {'OS': 'HP-UX', 'Description': 'Data partition'},
'E2A1E728-32E3-11D6-A682-7B03A0000000': {'OS': 'HP-UX', 'Description': 'Service Partition'},
'0FC63DAF-8483-4772-8E79-3D69D8477DE4': {'OS': 'Linux', 'Description': 'Linux filesystem data'},
'A19D880F-05FC-4D3B-A006-743F0F84911E': {'OS': 'Linux', 'Description': 'RAID partition'},
'44479540-F297-41B2-9AF7-D131D5F0458A': {'OS': 'Linux', 'Description': 'Root partition (x86)'},
'4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709': {'OS': 'Linux', 'Description': 'Root partition (x86-64)'},
'69DAD710-2CE4-4E3C-B16C-21A1D49ABED3': {'OS': 'Linux', 'Description': 'Root partition (32-bit ARM)'},
'B921B045-1DF0-41C3-AF44-4C6F280D3FAE': {'OS': 'Linux', 'Description': 'Root partition (64-bit ARM)/AArch64)'},
'0657FD6D-A4AB-43C4-84E5-0933C84B4F4F': {'OS': 'Linux', 'Description': 'Swap partition'},
'E6D6D379-F507-44C2-A23C-238F2A3DF928': {'OS': 'Linux', 'Description': 'Logical Volume Manager (LVM) partition'},
'933AC7E1-2EB4-4F13-B844-0E14E2AEF915': {'OS': 'Linux', 'Description': '/home partition'},
'3B8F8425-20E0-4F3B-907F-1A25A76F98E8': {'OS': 'Linux', 'Description': '/srv (server data) partition'},
'7FFEC5C9-2D00-49B7-8941-3EA10A5586B7': {'OS': 'Linux', 'Description': 'Plain dm-crypt partition'},
'CA7D7CCB-63ED-4C53-861C-1742536059CC': {'OS': 'Linux', 'Description': 'LUKS partition'},
'8DA63339-0007-60C0-C436-083AC8230908': {'OS': 'Linux', 'Description': 'Reserved'},
'83BD6B9D-7F41-11DC-BE0B-001560B84F0F': {'OS': 'FreeBSD', 'Description': 'Boot partition'},
'516E7CB4-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Data partition'},
'516E7CB5-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Swap partition'},
'516E7CB6-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Unix File System (UFS) partition'},
'516E7CB8-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Vinum volume manager partition'},
'516E7CBA-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'ZFS partition'},
'48465300-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Hierarchical File System Plus (HFS+) partition'},
'55465300-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple UFS'},
'6A898CC3-1DD2-11B2-99A6-080020736631': {'OS': 'OS X Darwin', 'Description': 'ZFS'},
'52414944-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple RAID partition'},
'52414944-5F4F-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple RAID partition, offline'},
'426F6F74-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Boot partition (Recovery HD)'},
'4C616265-6C00-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Label'},
'5265636F-7665-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple TV Recovery partition'},
'53746F72-6167-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Core Storage (i.e. Lion FileVault) partition'},
'6A82CB45-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Boot partition'},
'6A85CF4D-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Root partition'},
'6A87C46F-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Swap partition'},
'6A8B642B-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Backup partition'},
'6A898CC3-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/usr partition'},
'6A8EF2E9-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/var partition'},
'6A90BA39-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/home partition'},
'6A9283A5-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Alternate sector'},
'6A945A3B-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Reserved partition'},
'6A9630D1-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'},
'6A980767-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'},
'6A96237F-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'},
'6A8D2AC7-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'},
'49F48D32-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Swap partition'},
'49F48D5A-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'FFS partition'},
'49F48D82-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'LFS partition'},
'49F48DAA-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'RAID partition'},
'2DB519C4-B10F-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Concatenated partition'},
'2DB519EC-B10F-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Encrypted partition'},
'FE3A2A5D-4F32-41A7-B725-ACCC3285A309': {'OS': 'ChromeOS', 'Description': 'ChromeOS kernel'},
'3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC': {'OS': 'ChromeOS', 'Description': 'ChromeOS rootfs'},
'2E0A753D-9E48-43B0-8337-B15192CB1B5E': {'OS': 'ChromeOS', 'Description': 'ChromeOS future use'},
'42465331-3BA3-10F1-802A-4861696B7521': {'OS': 'Haiku', 'Description': 'Haiku BFS'},
'85D5E45E-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Boot partition'},
'85D5E45A-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Data partition'},
'85D5E45B-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Swap partition'},
'0394EF8B-237E-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Unix File System (UFS) partition'},
'85D5E45C-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Vinum volume manager partition'},
'85D5E45D-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'ZFS partition'},
'45B0969E-9B03-4F30-B4C6-B4B80CEFF106': {'OS': 'Ceph', 'Description': 'Ceph Journal'},
'45B0969E-9B03-4F30-B4C6-5EC00CEFF106': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt Encrypted Journal'},
'4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D': {'OS': 'Ceph', 'Description': 'Ceph OSD'},
'4FBD7E29-9D25-41B8-AFD0-5EC00CEFF05D': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt OSD'},
'89C57F98-2FE5-4DC0-89C1-F3AD0CEFF2BE': {'OS': 'Ceph', 'Description': 'Ceph disk in creation'},
'89C57F98-2FE5-4DC0-89C1-5EC00CEFF2BE': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt disk in creation'},
'824CC7A0-36A8-11E3-890A-952519AD3F61': {'OS': 'OpenBSD', 'Description': 'Data partition'},
'CEF5A9AD-73BC-4601-89F3-CDEEEEE321A1': {'OS': 'QNX', 'Description': 'Power-safe (QNX6) file system'},
'C91818F9-8025-47AF-89D2-F030D7000C2C': {'OS': 'Plan 9', 'Description': 'Plan 9 partition'},
'9D275380-40AD-11DB-BF97-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'vmkcore (coredump partition)'},
'AA31E02A-400F-11DB-9590-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'VMFS filesystem partition'},
'9198EFFC-31C0-11DB-8F78-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'VMware Reserved'},
'2568845D-2332-4675-BC39-8FA5A4748D15': {'OS': 'Android-IA', 'Description': 'Bootloader'},
'114EAFFE-1552-4022-B26E-9B053604CF84': {'OS': 'Android-IA', 'Description': 'Bootloader2'},
'49A4D17F-93A3-45C1-A0DE-F50B2EBE2599': {'OS': 'Android-IA', 'Description': 'Boot'},
'4177C722-9E92-4AAB-8644-43502BFD5506': {'OS': 'Android-IA', 'Description': 'Recovery'},
'EF32A33B-A409-486C-9141-9FFB711F6266': {'OS': 'Android-IA', 'Description': 'Misc'},
'20AC26BE-20B7-11E3-84C5-6CFDB94711E9': {'OS': 'Android-IA', 'Description': 'Metadata'},
'38F428E6-D326-425D-9140-6E0EA133647C': {'OS': 'Android-IA', 'Description': 'System'},
'A893EF21-E428-470A-9E55-0668FD91A2D9': {'OS': 'Android-IA', 'Description': 'Cache'},
'DC76DDA9-5AC1-491C-AF42-A82591580C0D': {'OS': 'Android-IA', 'Description': 'Data'},
'EBC597D0-2053-4B15-8B64-E0AAC75F4DB1': {'OS': 'Android-IA', 'Description': 'Persistent'},
'8F68CC74-C5E5-48DA-BE91-A0C8C15E9C80': {'OS': 'Android-IA', 'Description': 'Factory'},
'767941D0-2085-11E3-AD3B-6CFDB94711E9': {'OS': 'Android-IA', 'Description': 'Fastboot / Tertiary'},
'AC6D7924-EB71-4DF8-B48D-E267B27148FF': {'OS': 'Android-IA', 'Description': 'OEM'},
'7412F7D5-A156-4B13-81DC-867174929325': {'OS': 'ONIE', 'Description': 'Boot'},
'D4E6E2CD-4469-46F3-B5CB-1BFF57AFC149': {'OS': 'ONIE', 'Description': 'Config'},
'9E1A2D38-C612-4316-AA26-8B49521E5A8B': {'OS': 'PowerPC', 'Description': 'PReP boot'},
'BC13C2FF-59E6-4262-A352-B275FD6F7172': {'OS': 'Freedesktop', 'Description': 'Extended Boot Partition ($BOOT)'},
}
if __name__ == '__main__':
print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2

View file

@ -8,10 +8,10 @@ os.chdir(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(os.getcwd())
from functions.activation import *
from functions.cleanup import *
from functions.diags import *
from functions.info import *
from functions.product_keys import *
from functions.setup import *
from functions.sw_diags import *
init_global_vars()
os.system('title {}: System Checklist Tool'.format(KIT_NAME_FULL))
set_log_file('System Checklist.log')

View file

@ -7,10 +7,10 @@ import sys
os.chdir(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(os.getcwd())
from functions.browsers import *
from functions.diags import *
from functions.info import *
from functions.product_keys import *
from functions.repairs import *
from functions.sw_diags import *
init_global_vars()
os.system('title {}: System Diagnostics Tool'.format(KIT_NAME_FULL))
set_log_file('System Diagnostics.log')