1#!/usr/bin/env python
2
3# Copyright 2013 Google Inc. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""
8Verifies that embedding UAC information into the manifest works.
9"""
10
11import TestGyp
12
13import sys
14from xml.dom.minidom import parseString
15
16if sys.platform == 'win32':
17  import pywintypes
18  import win32api
19  import winerror
20
21  RT_MANIFEST = 24
22
23  class LoadLibrary(object):
24    """Context manager for loading and releasing binaries in Windows.
25    Yields the handle of the binary loaded."""
26    def __init__(self, path):
27      self._path = path
28      self._handle = None
29
30    def __enter__(self):
31      self._handle = win32api.LoadLibrary(self._path)
32      return self._handle
33
34    def __exit__(self, type, value, traceback):
35      win32api.FreeLibrary(self._handle)
36
37
38  def extract_manifest(path, resource_name):
39    """Reads manifest from |path| and returns it as a string.
40    Returns None is there is no such manifest."""
41    with LoadLibrary(path) as handle:
42      try:
43        return win32api.LoadResource(handle, RT_MANIFEST, resource_name)
44      except pywintypes.error as error:
45        if error.args[0] == winerror.ERROR_RESOURCE_DATA_NOT_FOUND:
46          return None
47        else:
48          raise
49
50  test = TestGyp.TestGyp(formats=['msvs', 'ninja'])
51  CHDIR = 'linker-flags'
52  test.run_gyp('enable-uac.gyp', chdir=CHDIR)
53  test.build('enable-uac.gyp', test.ALL, chdir=CHDIR)
54
55  # The following binaries must contain a manifest embedded.
56  test.fail_test(not extract_manifest(test.built_file_path(
57    'enable_uac.exe', chdir=CHDIR), 1))
58  test.fail_test(not extract_manifest(test.built_file_path(
59    'enable_uac_no.exe', chdir=CHDIR), 1))
60  test.fail_test(not extract_manifest(test.built_file_path(
61    'enable_uac_admin.exe', chdir=CHDIR), 1))
62
63  # Verify that <requestedExecutionLevel level="asInvoker" uiAccess="false" />
64  # is present.
65  manifest = parseString(extract_manifest(
66      test.built_file_path('enable_uac.exe', chdir=CHDIR), 1))
67  execution_level = manifest.getElementsByTagName('requestedExecutionLevel')
68  test.fail_test(len(execution_level) != 1)
69  execution_level = execution_level[0].attributes
70  test.fail_test(not (
71      execution_level.has_key('level') and
72      execution_level.has_key('uiAccess') and
73      execution_level['level'].nodeValue == 'asInvoker' and
74      execution_level['uiAccess'].nodeValue == 'false'))
75
76  # Verify that <requestedExecutionLevel> is not in the menifest.
77  manifest = parseString(extract_manifest(
78      test.built_file_path('enable_uac_no.exe', chdir=CHDIR), 1))
79  execution_level = manifest.getElementsByTagName('requestedExecutionLevel')
80  test.fail_test(len(execution_level) != 0)
81
82  # Verify that <requestedExecutionLevel level="requireAdministrator"
83  # uiAccess="true" /> is present.
84  manifest = parseString(extract_manifest(
85      test.built_file_path('enable_uac_admin.exe', chdir=CHDIR), 1))
86  execution_level = manifest.getElementsByTagName('requestedExecutionLevel')
87  test.fail_test(len(execution_level) != 1)
88  execution_level = execution_level[0].attributes
89  test.fail_test(not (
90      execution_level.has_key('level') and
91      execution_level.has_key('uiAccess') and
92      execution_level['level'].nodeValue == 'requireAdministrator' and
93      execution_level['uiAccess'].nodeValue == 'true'))
94
95  test.pass_test()
96