summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-02-03 15:42:32 +0000
committerMatthias Clasen <mclasen@redhat.com>2021-02-03 15:42:32 +0000
commit89f3273651cd073f1745e6842e1f5f747fe27eef (patch)
tree3584b42674c622e839ede583be55ab3d47828659
parentddb9bae3d460dbeeac89d9ee9cac2d367706e5f1 (diff)
parenta612a42c1107fcf0999b75a53114d77fcd6e4f25 (diff)
downloadgtk+-89f3273651cd073f1745e6842e1f5f747fe27eef.tar.gz
Merge branch 'uac.meson.3' into 'gtk-3-24'
Meson: Avoid UAC on 32-bit Windows for gtk-update-icon-cache See merge request GNOME/gtk!3147
-rw-r--r--gtk/Makefile.am26
-rw-r--r--gtk/generate-uac-manifest.py110
-rw-r--r--gtk/meson.build23
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