mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-24 12:41:16 +00:00
gtk4-update-icon-cache: Avoid UAC on 32-bit Windows
As the program executable name has 'update' in its filename, gtk4-update-icon-cache.exe is considered to be an installer program on 32-bit Windows [1], which will cause the program to fail to run unless it is running with elevated privileges (i.e. UAC). Avoid this situation by embedding a manifest file into the final executable that tells Windows that this is not a program that requires elevation. Fixes issue #3632. [1]: https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc709628(v=ws.10)?redirectedfrom=MSDN, under section "Installer Detection Technology"
This commit is contained in:
parent
3d85d53e5d
commit
f0967fa5e4
110
tools/generate-uac-manifest.py
Normal file
110
tools/generate-uac-manifest.py
Normal file
@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
This script generates a Windows manifest file and optionally a resource file to
|
||||
determine whether a specified program requires UAC elevation
|
||||
"""
|
||||
|
||||
import os
|
||||
import argparse
|
||||
|
||||
DOMAIN_NAME='gnome'
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__)
|
||||
parser.add_argument('-p', '--package', required=True,
|
||||
help='package name of the executable')
|
||||
parser.add_argument('-n', '--name', required=True,
|
||||
help='name of executable')
|
||||
parser.add_argument('--pkg-version', required=True, dest='version',
|
||||
help='version of package')
|
||||
parser.add_argument('--require-admin', action='store_true', dest='admin',
|
||||
default=False,
|
||||
help='require admin access to application')
|
||||
parser.add_argument('--input-resource-file', dest='resource',
|
||||
default=None,
|
||||
help='existing .rc file to embed UAC manifest (do not generate a new .rc file), must have included winuser.h in it')
|
||||
parser.add_argument('--output-dir', dest='outdir',
|
||||
default=None,
|
||||
help='directory to output resulting files')
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.resource is not None:
|
||||
if not os.path.isfile(args.resource):
|
||||
raise FileNotFoundError("Specified resource file '%s' does not exist" % args.resource)
|
||||
|
||||
generate_manifest(args.package, args.name, args.version, args.admin, args.outdir)
|
||||
write_rc_file(args.name, args.resource, args.outdir)
|
||||
|
||||
def generate_manifest(package, name, version, admin, outdir):
|
||||
if version.count('.') == 0:
|
||||
manifest_package_version = version + '.0.0.0'
|
||||
elif version.count('.') == 1:
|
||||
manifest_package_version = version + '.0.0'
|
||||
elif version.count('.') == 2:
|
||||
manifest_package_version = version + '.0'
|
||||
elif version.count('.') == 3:
|
||||
manifest_package_version = version
|
||||
else:
|
||||
parts = version.split('.')
|
||||
manifest_package_version = ''
|
||||
for x in (0, 1, 2, 3):
|
||||
if x == 0:
|
||||
manifest_package_version += parts[x]
|
||||
else:
|
||||
manifest_package_version += '.' + parts[x]
|
||||
|
||||
if outdir is not None:
|
||||
output_file_base_name = os.path.join(outdir, name)
|
||||
else:
|
||||
output_file_base_name = name
|
||||
|
||||
outfile = open(output_file_base_name + '.exe.manifest', 'w+')
|
||||
outfile.write('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n')
|
||||
outfile.write('<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">\n')
|
||||
outfile.write(' <assemblyIdentity version="%s"\n' % manifest_package_version)
|
||||
outfile.write(' processorArchitecture="*"\n')
|
||||
outfile.write(' name="%s.%s.%s.exe"\n' % (DOMAIN_NAME, package, name))
|
||||
outfile.write(' type="win32" />\n')
|
||||
outfile.write(' <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">\n')
|
||||
outfile.write(' <security>\n')
|
||||
outfile.write(' <requestedPrivileges>\n')
|
||||
outfile.write(' <requestedExecutionLevel\n')
|
||||
|
||||
if admin:
|
||||
outfile.write(' level="requireAdministrator"\n')
|
||||
else:
|
||||
outfile.write(' level="asInvoker"\n')
|
||||
|
||||
outfile.write(' uiAccess="false" />\n')
|
||||
outfile.write(' </requestedPrivileges>\n')
|
||||
outfile.write(' </security>\n')
|
||||
outfile.write(' </trustInfo>\n')
|
||||
outfile.write('</assembly>\n')
|
||||
outfile.close()
|
||||
|
||||
def write_rc_file(name, resource, outdir):
|
||||
if outdir is not None:
|
||||
output_file_base_name = os.path.join(outdir, name)
|
||||
else:
|
||||
output_file_base_name = name
|
||||
|
||||
if resource is None:
|
||||
outfile = open(output_file_base_name + '.rc', 'w+')
|
||||
outfile.write('#include <winuser.h>')
|
||||
else:
|
||||
if resource != output_file_base_name + '.rc':
|
||||
outfile = open(output_file_base_name + '.rc', 'w+')
|
||||
else:
|
||||
outfile = open(output_file_base_name + '.final.rc', 'w+')
|
||||
srcfile = open(resource, 'r')
|
||||
outfile.write(srcfile.read())
|
||||
srcfile.close()
|
||||
|
||||
outfile.write('\n')
|
||||
outfile.write('CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "%s.exe.manifest"' % name)
|
||||
outfile.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -1,4 +1,27 @@
|
||||
# Installed tools
|
||||
|
||||
extra_update_icon_cache_objs = []
|
||||
if win32_enabled
|
||||
gen_uac_manifest = find_program('generate-uac-manifest.py')
|
||||
|
||||
uac_exe_pkg = 'gtk4'
|
||||
uac_exe_name = '@0@-update-icon-cache'.format(uac_exe_pkg)
|
||||
|
||||
# Well, we have to forgo the xxx.exe.manifest in the output listing, since
|
||||
# compile_resources doesn't like to consume targets with multiple outputs,
|
||||
# and the xxx.exe.manifest and xxx.rc are tied together
|
||||
uac_rc = custom_target(
|
||||
'tools/@0@.rc'.format(uac_exe_name),
|
||||
output: ['@0@.rc'.format(uac_exe_name)],
|
||||
command: [gen_uac_manifest,
|
||||
'-p=@0@'.format(uac_exe_pkg),
|
||||
'-n=@0@'.format(uac_exe_name),
|
||||
'--pkg-version=@0@'.format(meson.project_version()),
|
||||
'--output-dir=@OUTDIR@'],
|
||||
)
|
||||
extra_update_icon_cache_objs = import('windows').compile_resources(uac_rc)
|
||||
endif
|
||||
|
||||
gtk_tools = [
|
||||
['gtk4-query-settings', ['gtk-query-settings.c'], [libgtk_dep]],
|
||||
['gtk4-builder-tool', ['gtk-builder-tool.c',
|
||||
@ -6,7 +29,7 @@ gtk_tools = [
|
||||
'gtk-builder-tool-validate.c',
|
||||
'gtk-builder-tool-enumerate.c',
|
||||
'gtk-builder-tool-preview.c'], [libgtk_dep] ],
|
||||
['gtk4-update-icon-cache', ['updateiconcache.c'], [ libgtk_static_dep ] ],
|
||||
['gtk4-update-icon-cache', ['updateiconcache.c'] + extra_update_icon_cache_objs, [ libgtk_static_dep ] ],
|
||||
['gtk4-encode-symbolic-svg', ['encodesymbolic.c'], [ libgtk_static_dep ] ],
|
||||
]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user