diff options
-rw-r--r-- | gtk/Makefile.am | 26 | ||||
-rw-r--r-- | gtk/generate-uac-manifest.py | 110 | ||||
-rw-r--r-- | gtk/meson.build | 23 |
3 files changed, 138 insertions, 21 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 1d22172522..ee740de47c 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -1710,27 +1710,10 @@ GTK_UPDATE_ICON_CACHE_MANIFEST = gtk-update-icon-cache.exe.manifest GTK_UPDATE_ICON_CACHE_RC = gtk-update-icon-cache.rc GTK_UPDATE_ICON_CACHE_MANIFEST_OBJECT = gtk-update-icon-cache_manifest.o -$(GTK_UPDATE_ICON_CACHE_MANIFEST): - (echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' ; \ - echo '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">' ; \ - echo ' <assemblyIdentity version="1.0.0.0"' ; \ - echo ' processorArchitecture="'$(EXE_MANIFEST_ARCHITECTURE)'"' ; \ - echo ' name="gtk-update-icon-cache.exe"' ; \ - echo ' type="win32"/>' ; \ - echo ' <!-- Identify the application security requirements. -->' ; \ - echo ' <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">' ; \ - echo ' <security>' ; \ - echo ' <requestedPrivileges>' ; \ - echo ' <requestedExecutionLevel' ; \ - echo ' level="asInvoker"' ; \ - echo ' uiAccess="false"/>' ; \ - echo ' </requestedPrivileges>' ; \ - echo ' </security>' ; \ - echo ' </trustInfo>' ; \ - echo '</assembly>' ) >$@ - -$(GTK_UPDATE_ICON_CACHE_RC): - (echo -e '#include <winuser.h>\nCREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST '$(GTK_UPDATE_ICON_CACHE_MANIFEST)) >$@ +$(GTK_UPDATE_ICON_CACHE_MANIFEST): Makefile generate-uac-manifest.py + $(PYTHON) $(srcdir)/generate-uac-manifest.py -p=gtk3 -n=gtk-update-icon-cache --pkg-version=$(GTK_VERSION) --output-dir=$(builddir) + +$(GTK_UPDATE_ICON_CACHE_RC): $(GTK_UPDATE_ICON_CACHE_MANIFEST) $(GTK_UPDATE_ICON_CACHE_MANIFEST_OBJECT): $(GTK_UPDATE_ICON_CACHE_RC) $(GTK_UPDATE_ICON_CACHE_MANIFEST) $(WINDRES) --input $< --output $@ --output-format=coff @@ -1793,6 +1776,7 @@ EXTRA_DIST += \ meson.build \ gen-gtk-gresources-xml.py \ gen-rc.py \ + generate-uac-manifest.py \ gentypefuncs.py \ a11y/meson.build \ deprecated/meson.build \ diff --git a/gtk/generate-uac-manifest.py b/gtk/generate-uac-manifest.py new file mode 100644 index 0000000000..ede6ba5044 --- /dev/null +++ b/gtk/generate-uac-manifest.py @@ -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() diff --git a/gtk/meson.build b/gtk/meson.build index 2a72b91047..43a6e2bfef 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -1065,9 +1065,32 @@ gtk_builder_tool = executable( install: true ) +extra_update_icon_cache_objs = [] +if win32_enabled + gen_uac_manifest = find_program('generate-uac-manifest.py') + + uac_exe_pkg = 'gtk3' + uac_exe_name = 'gtk-update-icon-cache' + + # 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( + 'gtk/@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_update_icon_cache = executable( 'gtk-update-icon-cache', 'updateiconcache.c', + extra_update_icon_cache_objs, c_args: gtk_cargs, dependencies: libgtk_dep, install: true |