Delete installcab.py
This commit is contained in:
parent
cbe5e25716
commit
c5a0b17137
@ -1,308 +0,0 @@
|
|||||||
#! /usr/bin/env python2
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import subprocess
|
|
||||||
import tempfile
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
import xml.etree.ElementTree
|
|
||||||
import re
|
|
||||||
|
|
||||||
tmpdir = None
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Utils
|
|
||||||
|
|
||||||
def cleanup():
|
|
||||||
if not tmpdir:
|
|
||||||
return
|
|
||||||
if options['nocleanup']:
|
|
||||||
print("Not cleaning up. Find the files at %s" % tmpdir)
|
|
||||||
else:
|
|
||||||
shutil.rmtree(tmpdir)
|
|
||||||
|
|
||||||
def bad_exit(text):
|
|
||||||
print(text)
|
|
||||||
cleanup()
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
def print_debug(text):
|
|
||||||
if options['debug']:
|
|
||||||
print(text)
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Architecture helpers
|
|
||||||
|
|
||||||
arch_map = {
|
|
||||||
"amd64": "win64",
|
|
||||||
"x86": "win32",
|
|
||||||
"wow64": "wow64"
|
|
||||||
}
|
|
||||||
|
|
||||||
dest_map = {
|
|
||||||
"win64:win32": "Syswow64",
|
|
||||||
"win64:win64": "System32",
|
|
||||||
"win64:wow64": "System32",
|
|
||||||
"win32:win32": "System32"
|
|
||||||
}
|
|
||||||
|
|
||||||
def check_wineprefix_arch(prefix_path):
|
|
||||||
if not os.path.exists(prefix_path):
|
|
||||||
bad_exit("Wineprefix path does not exist! (%s)" % prefix_path)
|
|
||||||
system_reg_file = os.path.join(prefix_path, 'system.reg')
|
|
||||||
with open(system_reg_file) as f:
|
|
||||||
for line in f.readlines():
|
|
||||||
if line.startswith("#arch=win32"):
|
|
||||||
return 'win32'
|
|
||||||
elif line.startswith("#arch=win64"):
|
|
||||||
return 'win64'
|
|
||||||
bad_exit("Could not determine wineprefix arch!")
|
|
||||||
|
|
||||||
def get_system32_realdir(arch):
|
|
||||||
return dest_map[winearch+':'+arch]
|
|
||||||
|
|
||||||
def get_dll_destdir(dll_path):
|
|
||||||
arch = check_dll_arch(dll_path)
|
|
||||||
if arch == 'win32' and winearch == 'win64':
|
|
||||||
dest_dir = syswow64_path
|
|
||||||
elif arch == 'win64' and winearch == 'win32':
|
|
||||||
bad_exit("Invalid win64 assembly for win32 wineprefix!")
|
|
||||||
else:
|
|
||||||
dest_dir = system32_path
|
|
||||||
return dest_dir
|
|
||||||
|
|
||||||
def get_winebin(arch):
|
|
||||||
if (arch == 'win64' or arch == 'wow64') and winearch == 'win32':
|
|
||||||
bad_exit("Invalid win64 assembly for win32 wineprefix!")
|
|
||||||
elif arch == 'win32' or arch == 'wow64':
|
|
||||||
winebin = 'wine'
|
|
||||||
else:
|
|
||||||
winebin = 'wine64'
|
|
||||||
return winebin
|
|
||||||
|
|
||||||
def check_dll_arch(dll_path):
|
|
||||||
out = subprocess.check_output(['file', dll_path])
|
|
||||||
if 'x86-64' in out:
|
|
||||||
return 'win64'
|
|
||||||
else:
|
|
||||||
return 'win32'
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Manifest processing
|
|
||||||
|
|
||||||
def replace_variables(value, arch):
|
|
||||||
if "$(" in value:
|
|
||||||
value = value.replace("$(runtime.help)", "C:\\windows\\help")
|
|
||||||
value = value.replace("$(runtime.inf)", "C:\\windows\\inf")
|
|
||||||
value = value.replace("$(runtime.wbem)", "C:\\windows\\wbem")
|
|
||||||
value = value.replace("$(runtime.windows)", "C:\\windows")
|
|
||||||
value = value.replace("$(runtime.ProgramFiles)", "C:\\windows\\Program Files")
|
|
||||||
value = value.replace("$(runtime.programFiles)", "C:\\windows\\Program Files")
|
|
||||||
value = value.replace("$(runtime.programFilesX86)", "C:\\windows\\Program Files (x86)")
|
|
||||||
value = value.replace("$(runtime.system32)", "C:\\windows\\%s" % get_system32_realdir(arch))
|
|
||||||
value = value.replace("$(runtime.drivers)", "C:\\windows\\%s\\drivers" % get_system32_realdir(arch))
|
|
||||||
value = value.replace("\\", "\\\\")
|
|
||||||
return value
|
|
||||||
|
|
||||||
def process_value(rv, arch):
|
|
||||||
attrs = rv.attrib
|
|
||||||
name = attrs["name"]
|
|
||||||
value = attrs["value"]
|
|
||||||
value_type = attrs["valueType"]
|
|
||||||
if not name.strip():
|
|
||||||
name = "@"
|
|
||||||
else:
|
|
||||||
name = "\"%s\"" % name
|
|
||||||
name = replace_variables(name, arch)
|
|
||||||
if value_type == 'REG_BINARY':
|
|
||||||
value = re.findall('..',value)
|
|
||||||
value = 'hex:'+",".join(value)
|
|
||||||
elif value_type == 'REG_DWORD':
|
|
||||||
value = "dword:%s" % value.replace("0x", "")
|
|
||||||
elif value_type == 'REG_QWORD':
|
|
||||||
value = "qword:%s" % value.replace("0x", "")
|
|
||||||
elif value_type == 'REG_NONE':
|
|
||||||
value = None
|
|
||||||
elif value_type == 'REG_EXPAND_SZ':
|
|
||||||
# not sure if we should replace this ones at this point:
|
|
||||||
# caps can vary in the pattern
|
|
||||||
value = value.replace("%SystemRoot%", "C:\\windows")
|
|
||||||
value = value.replace("%ProgramFiles%", "C:\\windows\\Program Files")
|
|
||||||
value = value.replace("%WinDir%", "C:\\windows")
|
|
||||||
value = value.replace("%ResourceDir%", "C:\\windows")
|
|
||||||
value = value.replace("%Public%", "C:\\users\\Public")
|
|
||||||
value = value.replace("%LocalAppData%", "C:\\windows\\Public\\Local Settings\\Application Data")
|
|
||||||
value = value.replace("%AllUsersProfile%", "C:\\windows")
|
|
||||||
value = value.replace("%UserProfile%", "C:\\windows")
|
|
||||||
value = value.replace("%ProgramData%", "C:\\ProgramData")
|
|
||||||
value = "\"%s\"" % value
|
|
||||||
elif value_type == 'REG_SZ':
|
|
||||||
value = "\"%s\"" % value
|
|
||||||
else:
|
|
||||||
print("warning unkown type: %s" % value_type)
|
|
||||||
value = "\"%s\"" % value
|
|
||||||
if value:
|
|
||||||
value = replace_variables(value, arch)
|
|
||||||
if options["stripdllpath"]:
|
|
||||||
if '.dll' in value:
|
|
||||||
value = value.lower().replace("c:\\\\windows\\\\system32\\\\", "")
|
|
||||||
value = value.lower().replace("c:\\\\windows\\\\syswow64\\\\", "")
|
|
||||||
return name, value
|
|
||||||
|
|
||||||
def process_key(key):
|
|
||||||
key = key.strip("\\")
|
|
||||||
key = key.replace("HKEY_CLASSES_ROOT", "HKEY_LOCAL_MACHINE\\Software\\Classes")
|
|
||||||
return key
|
|
||||||
|
|
||||||
def parse_manifest_arch(elmt):
|
|
||||||
registry_keys = elmt.findall("{urn:schemas-microsoft-com:asm.v3}assemblyIdentity")
|
|
||||||
if not len(registry_keys):
|
|
||||||
bad_exit("Can't find processor architecture")
|
|
||||||
arch = registry_keys[0].attrib["processorArchitecture"]
|
|
||||||
if not arch in arch_map:
|
|
||||||
bad_exit("Unknown processor architecture %s" % arch)
|
|
||||||
arch = arch_map[arch]
|
|
||||||
if (arch == 'win64' or arch == 'wow64') and winearch == 'win32':
|
|
||||||
bad_exit("Invalid 64 bit assembly for 32 bit system!")
|
|
||||||
return arch
|
|
||||||
|
|
||||||
def process_manifest(file_name):
|
|
||||||
out = ""
|
|
||||||
elmt = xml.etree.ElementTree.parse(file_name).getroot()
|
|
||||||
arch = parse_manifest_arch(elmt)
|
|
||||||
registry_keys = elmt.findall("{urn:schemas-microsoft-com:asm.v3}registryKeys")
|
|
||||||
if len(registry_keys):
|
|
||||||
for registry_key in registry_keys[0].getchildren():
|
|
||||||
key = process_key(registry_key.attrib["keyName"])
|
|
||||||
out += "[%s]\n" % key
|
|
||||||
for rv in registry_key.findall("{urn:schemas-microsoft-com:asm.v3}registryValue"):
|
|
||||||
name, value = process_value(rv, arch)
|
|
||||||
if not value is None:
|
|
||||||
out += "%s=%s\n"%(name,value)
|
|
||||||
out += "\n"
|
|
||||||
return (out, arch)
|
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Installer Processing
|
|
||||||
|
|
||||||
def extract_from_installer(orig_file, dest_dir, component):
|
|
||||||
filter_str = "*%s*" % component
|
|
||||||
print("%s" % component.strip("_"))
|
|
||||||
cmd = ["cabextract", "-F", filter_str, "-d", dest_dir, orig_file]
|
|
||||||
subprocess.check_output(cmd)
|
|
||||||
output_files = [os.path.join(r,file) for r,d,f in os.walk(dest_dir) for file in f]
|
|
||||||
return output_files
|
|
||||||
|
|
||||||
def load_manifest(file_path):
|
|
||||||
file_name = os.path.basename(file_path)
|
|
||||||
reg_data, arch = process_manifest(file_path)
|
|
||||||
print("- %s (%s)" % (file_name, arch))
|
|
||||||
return reg_data, arch
|
|
||||||
|
|
||||||
def register_dll(dll_path):
|
|
||||||
if not options["register"]:
|
|
||||||
return
|
|
||||||
arch = check_dll_arch(dll_path)
|
|
||||||
winebin = get_winebin(arch)
|
|
||||||
cmd = ["regsvr32", os.path.basename(dll_path)]
|
|
||||||
subprocess.call(cmd)
|
|
||||||
|
|
||||||
def install_dll(dll_path):
|
|
||||||
if options["nodll"]:
|
|
||||||
return
|
|
||||||
dest_dir = get_dll_destdir(dll_path)
|
|
||||||
file_name = os.path.basename(dll_path)
|
|
||||||
print("- %s -> %s" % (file_name, dest_dir))
|
|
||||||
shutil.copy(dll_path, dest_dir)
|
|
||||||
register_dll(os.path.join(dest_dir, file_name))
|
|
||||||
|
|
||||||
def install_regfile(path, reg_file, arch):
|
|
||||||
if options["noreg"]:
|
|
||||||
return
|
|
||||||
winebin = get_winebin(arch)
|
|
||||||
print_debug(" install reg %s with %s" % (reg_file, winebin))
|
|
||||||
cmd = [winebin, "regedit", os.path.join(path, reg_file)]
|
|
||||||
subprocess.call(cmd)
|
|
||||||
|
|
||||||
def process_files(output_files):
|
|
||||||
reg_files = []
|
|
||||||
for file_path in output_files:
|
|
||||||
if file_path.endswith(".manifest"):
|
|
||||||
out = "Windows Registry Editor Version 5.00\n\n"
|
|
||||||
outdata, arch = load_manifest(file_path)
|
|
||||||
if outdata:
|
|
||||||
out += outdata
|
|
||||||
print_debug(" %s assembly" % arch)
|
|
||||||
with open(os.path.join(tmpdir, file_path+".reg"), "w") as f:
|
|
||||||
f.write(out)
|
|
||||||
reg_files.append((file_path, arch))
|
|
||||||
|
|
||||||
for file_path in output_files:
|
|
||||||
if file_path.endswith(".dll"):
|
|
||||||
install_dll(file_path)
|
|
||||||
|
|
||||||
for file_path, arch in reg_files:
|
|
||||||
install_regfile(tmpdir, file_path+".reg", arch)
|
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Command line options
|
|
||||||
|
|
||||||
options = {'register': False, 'nocleanup': False, 'nodll': False, 'noreg': False, 'stripdllpath': False, 'debug': False}
|
|
||||||
|
|
||||||
def parse_command_line_opts(options):
|
|
||||||
app_argv = list(sys.argv)
|
|
||||||
for opt_key in options.keys():
|
|
||||||
opt_command = "--%s" % opt_key
|
|
||||||
if opt_command in app_argv:
|
|
||||||
options[opt_key] = True
|
|
||||||
app_argv.remove(opt_command)
|
|
||||||
return app_argv
|
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Main
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app_argv = parse_command_line_opts(options)
|
|
||||||
# sanity checks
|
|
||||||
if len(app_argv) < 3:
|
|
||||||
print("usage:")
|
|
||||||
print(" installcab.py [options] cabfile component [wineprefix_path]")
|
|
||||||
print("")
|
|
||||||
print("example:")
|
|
||||||
print(" installcab.py ~/.cache/winetricks/win7sp1/windows6.1-KB976932-X86.exe wmvdecod")
|
|
||||||
print("")
|
|
||||||
print("options:")
|
|
||||||
print(" --nocleanup: do not perform cleanup")
|
|
||||||
print(" --noreg: do not import registry entries")
|
|
||||||
print(" --nodll: do not install dlls into system dir")
|
|
||||||
print(" --register: register dlls with regsrv32")
|
|
||||||
print(" --stripdllpath: strip full path for dlls in registry so wine can find them anywhere")
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
if len(app_argv) < 4 and not "WINEPREFIX" in os.environ:
|
|
||||||
bad_exit("You need to set WINEPREFIX for this to work!")
|
|
||||||
|
|
||||||
# setup
|
|
||||||
if len(app_argv) < 4:
|
|
||||||
wineprefix = os.environ["WINEPREFIX"]
|
|
||||||
else:
|
|
||||||
wineprefix = app_argv[3]
|
|
||||||
|
|
||||||
winearch = check_wineprefix_arch(wineprefix)
|
|
||||||
|
|
||||||
system32_path = os.path.join(wineprefix, 'drive_c', 'windows', 'system32')
|
|
||||||
syswow64_path = os.path.join(wineprefix, 'drive_c', 'windows', 'syswow64')
|
|
||||||
|
|
||||||
tmpdir = tempfile.mkdtemp()
|
|
||||||
cabfile = app_argv[1]
|
|
||||||
component = app_argv[2]
|
|
||||||
|
|
||||||
# processing
|
|
||||||
output_files = extract_from_installer(cabfile, tmpdir, component)
|
|
||||||
process_files(output_files)
|
|
||||||
|
|
||||||
# clean up
|
|
||||||
cleanup()
|
|
Loading…
Reference in New Issue
Block a user