Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2015 The Swarming Authors. All rights reserved. | 1 # Copyright 2015 The Swarming Authors. All rights reserved. |
| 2 # Use of this source code is governed by the Apache v2.0 license that can be | 2 # Use of this source code is governed by the Apache v2.0 license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Windows specific utility functions.""" | 5 """Windows specific utility functions.""" |
| 6 | 6 |
| 7 import ctypes | 7 import ctypes |
| 8 import logging | 8 import logging |
| 9 import os | 9 import os |
| 10 import platform | 10 import platform |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 # win32com is included in pywin32, which is an optional package that is | 75 # win32com is included in pywin32, which is an optional package that is |
| 76 # installed by Swarming devs. If you find yourself needing it to run without | 76 # installed by Swarming devs. If you find yourself needing it to run without |
| 77 # pywin32, for example in cygwin, please send us a CL with the | 77 # pywin32, for example in cygwin, please send us a CL with the |
| 78 # implementation that doesn't use pywin32. | 78 # implementation that doesn't use pywin32. |
| 79 return None | 79 return None |
| 80 | 80 |
| 81 wmi_service = win32com.client.Dispatch('WbemScripting.SWbemLocator') | 81 wmi_service = win32com.client.Dispatch('WbemScripting.SWbemLocator') |
| 82 return wmi_service.ConnectServer('.', 'root\\cimv2') | 82 return wmi_service.ConnectServer('.', 'root\\cimv2') |
| 83 | 83 |
| 84 | 84 |
| 85 @tools.cached | |
| 86 def _get_os_numbers(): | |
| 87 """Returns the normalized OS version and build numbers as strings. | |
| 88 | |
| 89 Actively work around AppCompat version lie shim. | |
| 90 | |
| 91 Returns: | |
| 92 - 5.1, 6.1, etc. There is no way to distinguish between Windows 7 | |
| 93 and Windows Server 2008R2 since they both report 6.1. | |
| 94 """ | |
| 95 # Windows is lying to us until python adds to its manifest: | |
| 96 # <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> | |
| 97 # and it doesn't. | |
| 98 # So ask nicely to cmd.exe instead, which will always happily report the right | |
| 99 # version. Here's some sample output: | |
| 100 # - XP: Microsoft Windows XP [Version 5.1.2600] | |
| 101 # - Win10: Microsoft Windows [Version 10.0.10240] | |
| 102 # - Win7 or Win2K8R2: Microsoft Windows [Version 6.1.7601] | |
| 103 out = subprocess.check_output(['cmd.exe', '/c', 'ver']).strip() | |
| 104 match = re.search(r'\[Version (\d+\.\d+)\.(\d+)\]', out, re.IGNORECASE) | |
| 105 return match.group(1), match.group(2) | |
| 106 | |
| 107 | |
| 85 ## Public API. | 108 ## Public API. |
| 86 | 109 |
| 87 | 110 |
| 88 def from_cygwin_path(path): | 111 def from_cygwin_path(path): |
| 89 """Converts an absolute cygwin path to a standard Windows path.""" | 112 """Converts an absolute cygwin path to a standard Windows path.""" |
| 90 if not path.startswith('/cygdrive/'): | 113 if not path.startswith('/cygdrive/'): |
| 91 logging.error('%s is not a cygwin path', path) | 114 logging.error('%s is not a cygwin path', path) |
| 92 return None | 115 return None |
| 93 | 116 |
| 94 # Remove the cygwin path identifier. | 117 # Remove the cygwin path identifier. |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 105 # TODO(maruel): Accept \\?\ and \??\ if necessary. | 128 # TODO(maruel): Accept \\?\ and \??\ if necessary. |
| 106 logging.error('%s is not a win32 path', path) | 129 logging.error('%s is not a win32 path', path) |
| 107 return None | 130 return None |
| 108 return '/cygdrive/%s/%s' % (path[0].lower(), path[3:].replace('\\', '/')) | 131 return '/cygdrive/%s/%s' % (path[0].lower(), path[3:].replace('\\', '/')) |
| 109 | 132 |
| 110 | 133 |
| 111 @tools.cached | 134 @tools.cached |
| 112 def get_os_version_number(): | 135 def get_os_version_number(): |
| 113 """Returns the normalized OS version number as a string. | 136 """Returns the normalized OS version number as a string. |
| 114 | 137 |
| 115 Actively work around AppCompat version lie shim. | |
| 116 | |
| 117 Returns: | 138 Returns: |
| 118 - 5.1, 6.1, etc. There is no way to distinguish between Windows 7 | 139 - '5.1', '6.1', '10.0', etc. There is no way to distinguish between Windows |
| 119 and Windows Server 2008R2 since they both report 6.1. | 140 7 and Windows Server 2008R2 since they both report 6.1. |
| 120 """ | 141 """ |
| 121 # Windows is lying to us until python adds to its manifest: | 142 return _get_os_numbers()[0] |
| 122 # <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> | |
| 123 # and it doesn't. | |
| 124 # So ask nicely to cmd.exe instead, which will always happily report the right | |
| 125 # version. Here's some sample output: | |
| 126 # - XP: Microsoft Windows XP [Version 5.1.2600] | |
| 127 # - Win10: Microsoft Windows [Version 10.0.10240] | |
| 128 # - Win7 or Win2K8R2: Microsoft Windows [Version 6.1.7601] | |
| 129 out = subprocess.check_output(['cmd.exe', '/c', 'ver']).strip() | |
| 130 return re.search(r'\[Version (\d+\.\d+)\.\d+\]', out, re.IGNORECASE).group(1) | |
| 131 | 143 |
| 132 | 144 |
| 133 @tools.cached | 145 @tools.cached |
| 134 def get_os_version_name(): | 146 def get_os_version_name(): |
| 135 """Returns the marketing name of the OS including the service pack.""" | 147 """Returns the marketing name of the OS including the service pack. |
| 148 | |
| 149 On Windows 10, use the build number since there will be no service pack. | |
| 150 """ | |
| 136 # Python keeps a local map in platform.py and it is updated at newer python | 151 # Python keeps a local map in platform.py and it is updated at newer python |
| 137 # release. Since our python release is a bit old, do not rely on it. | 152 # release. Since our python release is a bit old, do not rely on it. |
| 138 is_server = sys.getwindowsversion().product_type == 3 | 153 is_server = sys.getwindowsversion().product_type == 3 |
| 139 lookup = _WIN32_SERVER_NAMES if is_server else _WIN32_CLIENT_NAMES | 154 lookup = _WIN32_SERVER_NAMES if is_server else _WIN32_CLIENT_NAMES |
| 140 version_number = get_os_version_number() | 155 version_number, build_number = _get_os_numbers() |
| 141 marketing_name = lookup.get(version_number, version_number) | 156 marketing_name = lookup.get(version_number, version_number) |
| 157 # Windows 10 doesn't have service packs, the build number now is the reference | |
| 158 # number. | |
|
tandrii(chromium)
2016/03/29 15:46:27
I think this comment should be after line 160.
M-A Ruel
2016/03/29 15:51:53
Agreed, moved both the line and the comment.
| |
| 142 service_pack = platform.win32_ver()[2] or 'SP0' | 159 service_pack = platform.win32_ver()[2] or 'SP0' |
| 160 if version_number == '10.0': | |
| 161 return '%s-%s' % (marketing_name, build_number) | |
| 143 return '%s-%s' % (marketing_name, service_pack) | 162 return '%s-%s' % (marketing_name, service_pack) |
| 144 | 163 |
| 145 | 164 |
| 146 def get_startup_dir(): | 165 def get_startup_dir(): |
| 147 # Do not use environment variables since it wouldn't work reliably on cygwin. | 166 # Do not use environment variables since it wouldn't work reliably on cygwin. |
| 148 # TODO(maruel): Stop hardcoding the values and use the proper function | 167 # TODO(maruel): Stop hardcoding the values and use the proper function |
| 149 # described below. Postponed to a later CL since I'll have to spend quality | 168 # described below. Postponed to a later CL since I'll have to spend quality |
| 150 # time on Windows to ensure it works well. | 169 # time on Windows to ensure it works well. |
| 151 # https://msdn.microsoft.com/library/windows/desktop/bb762494.aspx | 170 # https://msdn.microsoft.com/library/windows/desktop/bb762494.aspx |
| 152 # CSIDL_STARTUP = 7 | 171 # CSIDL_STARTUP = 7 |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 385 | 404 |
| 386 def get_uptime(): | 405 def get_uptime(): |
| 387 """Return uptime for Windows 7 and later. | 406 """Return uptime for Windows 7 and later. |
| 388 | 407 |
| 389 Excludes sleep time. | 408 Excludes sleep time. |
| 390 """ | 409 """ |
| 391 val = ctypes.c_ulonglong(0) | 410 val = ctypes.c_ulonglong(0) |
| 392 if ctypes.windll.kernel32.QueryUnbiasedInterruptTime(ctypes.byref(val)) != 0: | 411 if ctypes.windll.kernel32.QueryUnbiasedInterruptTime(ctypes.byref(val)) != 0: |
| 393 return val.value / 10000000. | 412 return val.value / 10000000. |
| 394 return 0. | 413 return 0. |
| OLD | NEW |