4988.10.3
by John Arbash Meinel
Merge bzr.dev 5007, resolve conflict, update NEWS |
1 |
# Copyright (C) 2005-2010 Canonical Ltd
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
2 |
#
|
2052.3.1
by John Arbash Meinel
Add tests to cleanup the copyright of all source files |
3 |
# This program is free software; you can redistribute it and/or modify
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
#
|
|
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
#
|
|
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
4183.7.1
by Sabin Iacob
update FSF mailing address |
15 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
2052.3.1
by John Arbash Meinel
Add tests to cleanup the copyright of all source files |
16 |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
17 |
"""Win32-specific helper functions
|
18 |
||
19 |
Only one dependency: ctypes should be installed.
|
|
20 |
"""
|
|
21 |
||
6379.6.7
by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear. |
22 |
from __future__ import absolute_import |
23 |
||
4786.1.1
by John Arbash Meinel
Work on doing globbing, etc for all commands on Windows. |
24 |
import glob |
6362.2.3
by Martin Packman
Always return username and hostname as unicode in win32utils |
25 |
import operator |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
26 |
import os |
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
27 |
import struct |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
28 |
import sys |
29 |
||
6362.2.2
by Martin Packman
Use get_environ_unicode throughout win32utils and always return unicode paths |
30 |
from bzrlib import ( |
31 |
cmdline, |
|
32 |
symbol_versioning, |
|
33 |
)
|
|
6138.3.4
by Jonathan Riddell
add gettext() to uses of trace.note() |
34 |
from bzrlib.i18n import gettext |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
35 |
|
36 |
# Windows version
|
|
37 |
if sys.platform == 'win32': |
|
38 |
_major,_minor,_build,_platform,_text = sys.getwindowsversion() |
|
2245.4.11
by Alexander Belchenko
Small fixes after John's review; added NEWS entry |
39 |
# from MSDN:
|
40 |
# dwPlatformId
|
|
41 |
# The operating system platform.
|
|
42 |
# This member can be one of the following values.
|
|
43 |
# ========================== ======================================
|
|
44 |
# Value Meaning
|
|
45 |
# -------------------------- --------------------------------------
|
|
46 |
# VER_PLATFORM_WIN32_NT The operating system is Windows Vista,
|
|
47 |
# 2 Windows Server "Longhorn",
|
|
48 |
# Windows Server 2003, Windows XP,
|
|
49 |
# Windows 2000, or Windows NT.
|
|
50 |
#
|
|
51 |
# VER_PLATFORM_WIN32_WINDOWS The operating system is Windows Me,
|
|
52 |
# 1 Windows 98, or Windows 95.
|
|
53 |
# ========================== ======================================
|
|
54 |
if _platform == 2: |
|
55 |
winver = 'Windows NT' |
|
56 |
else: |
|
57 |
# don't care about real Windows name, just to force safe operations
|
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
58 |
winver = 'Windows 98' |
59 |
else: |
|
60 |
winver = None |
|
61 |
||
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
62 |
|
1773.4.1
by Martin Pool
Add pyflakes makefile target; fix many warnings |
63 |
# We can cope without it; use a separate variable to help pyflakes
|
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
64 |
try: |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
65 |
import ctypes |
66 |
has_ctypes = True |
|
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
67 |
except ImportError: |
1773.4.1
by Martin Pool
Add pyflakes makefile target; fix many warnings |
68 |
has_ctypes = False |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
69 |
else: |
70 |
if winver == 'Windows 98': |
|
71 |
create_buffer = ctypes.create_string_buffer |
|
6362.2.3
by Martin Packman
Always return username and hostname as unicode in win32utils |
72 |
def extract_buffer(buf): |
6362.2.5
by Martin Packman
Tweaks including those suggested by vila in review |
73 |
return buf.value.decode("mbcs") |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
74 |
suffix = 'A' |
75 |
else: |
|
76 |
create_buffer = ctypes.create_unicode_buffer |
|
6362.2.3
by Martin Packman
Always return username and hostname as unicode in win32utils |
77 |
extract_buffer = operator.attrgetter("value") |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
78 |
suffix = 'W' |
3023.1.2
by Alexander Belchenko
Martin's review. |
79 |
try: |
4505.2.1
by Alexander Belchenko
Set hidden attribute on .bzr directory below unicode path should never fail with error. The operation should succeed even if bzr unable to set the attribute. (related to bug #335362). |
80 |
import pywintypes |
6336.2.2
by Martin Packman
Tweak how pywin32 is imported in win32utils to fix test failure edge case |
81 |
has_pywintypes = True |
82 |
except ImportError: |
|
6336.2.3
by Martin Packman
Set all has_win32* to False if pywintypes can't be imported |
83 |
has_pywintypes = has_win32file = has_win32api = False |
6336.2.2
by Martin Packman
Tweak how pywin32 is imported in win32utils to fix test failure edge case |
84 |
else: |
85 |
try: |
|
86 |
import win32file |
|
87 |
has_win32file = True |
|
88 |
except ImportError: |
|
89 |
has_win32file = False |
|
90 |
try: |
|
91 |
import win32api |
|
92 |
has_win32api = True |
|
93 |
except ImportError: |
|
94 |
has_win32api = False |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
95 |
|
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
96 |
# pulling in win32com.shell is a bit of overhead, and normally we don't need
|
97 |
# it as ctypes is preferred and common. lazy_imports and "optional"
|
|
98 |
# modules don't work well, so we do our own lazy thing...
|
|
99 |
has_win32com_shell = None # Set to True or False once we know for sure... |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
100 |
|
101 |
# Special Win32 API constants
|
|
102 |
# Handles of std streams
|
|
1704.2.3
by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander) |
103 |
WIN32_STDIN_HANDLE = -10 |
104 |
WIN32_STDOUT_HANDLE = -11 |
|
105 |
WIN32_STDERR_HANDLE = -12 |
|
106 |
||
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
107 |
# CSIDL constants (from MSDN 2003)
|
108 |
CSIDL_APPDATA = 0x001A # Application Data folder |
|
3638.4.10
by Aaron Bentley
Correct spelling of 'Application Data' |
109 |
CSIDL_LOCAL_APPDATA = 0x001c# <user name>\Local Settings\Application Data (non roaming) |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
110 |
CSIDL_PERSONAL = 0x0005 # My Documents folder |
111 |
||
112 |
# from winapi C headers
|
|
113 |
MAX_PATH = 260 |
|
114 |
UNLEN = 256 |
|
115 |
MAX_COMPUTERNAME_LENGTH = 31 |
|
116 |
||
4476.2.1
by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ). |
117 |
# Registry data type ids
|
118 |
REG_SZ = 1 |
|
119 |
REG_EXPAND_SZ = 2 |
|
120 |
||
1704.2.3
by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander) |
121 |
|
4011.1.1
by John Arbash Meinel
Implement -Dmemory for win32 |
122 |
def debug_memory_win32api(message='', short=True): |
123 |
"""Use trace.note() to dump the running memory info."""
|
|
124 |
from bzrlib import trace |
|
4011.1.2
by John Arbash Meinel
Fix some small bugs, and prefer the ctypes form. |
125 |
if has_ctypes: |
4011.1.1
by John Arbash Meinel
Implement -Dmemory for win32 |
126 |
class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure): |
127 |
"""Used by GetProcessMemoryInfo"""
|
|
128 |
_fields_ = [('cb', ctypes.c_ulong), |
|
129 |
('PageFaultCount', ctypes.c_ulong), |
|
130 |
('PeakWorkingSetSize', ctypes.c_size_t), |
|
131 |
('WorkingSetSize', ctypes.c_size_t), |
|
132 |
('QuotaPeakPagedPoolUsage', ctypes.c_size_t), |
|
133 |
('QuotaPagedPoolUsage', ctypes.c_size_t), |
|
134 |
('QuotaPeakNonPagedPoolUsage', ctypes.c_size_t), |
|
135 |
('QuotaNonPagedPoolUsage', ctypes.c_size_t), |
|
136 |
('PagefileUsage', ctypes.c_size_t), |
|
137 |
('PeakPagefileUsage', ctypes.c_size_t), |
|
138 |
('PrivateUsage', ctypes.c_size_t), |
|
139 |
]
|
|
140 |
cur_process = ctypes.windll.kernel32.GetCurrentProcess() |
|
141 |
mem_struct = PROCESS_MEMORY_COUNTERS_EX() |
|
142 |
ret = ctypes.windll.psapi.GetProcessMemoryInfo(cur_process, |
|
143 |
ctypes.byref(mem_struct), |
|
144 |
ctypes.sizeof(mem_struct)) |
|
145 |
if not ret: |
|
6138.3.4
by Jonathan Riddell
add gettext() to uses of trace.note() |
146 |
trace.note(gettext('Failed to GetProcessMemoryInfo()')) |
4011.1.1
by John Arbash Meinel
Implement -Dmemory for win32 |
147 |
return
|
148 |
info = {'PageFaultCount': mem_struct.PageFaultCount, |
|
149 |
'PeakWorkingSetSize': mem_struct.PeakWorkingSetSize, |
|
150 |
'WorkingSetSize': mem_struct.WorkingSetSize, |
|
151 |
'QuotaPeakPagedPoolUsage': mem_struct.QuotaPeakPagedPoolUsage, |
|
152 |
'QuotaPagedPoolUsage': mem_struct.QuotaPagedPoolUsage, |
|
4989.1.6
by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used. |
153 |
'QuotaPeakNonPagedPoolUsage': |
154 |
mem_struct.QuotaPeakNonPagedPoolUsage, |
|
4011.1.1
by John Arbash Meinel
Implement -Dmemory for win32 |
155 |
'QuotaNonPagedPoolUsage': mem_struct.QuotaNonPagedPoolUsage, |
156 |
'PagefileUsage': mem_struct.PagefileUsage, |
|
157 |
'PeakPagefileUsage': mem_struct.PeakPagefileUsage, |
|
158 |
'PrivateUsage': mem_struct.PrivateUsage, |
|
159 |
}
|
|
4011.1.2
by John Arbash Meinel
Fix some small bugs, and prefer the ctypes form. |
160 |
elif has_win32api: |
161 |
import win32process |
|
162 |
# win32process does not return PrivateUsage, because it doesn't use
|
|
163 |
# PROCESS_MEMORY_COUNTERS_EX (it uses the one without _EX).
|
|
164 |
proc = win32process.GetCurrentProcess() |
|
165 |
info = win32process.GetProcessMemoryInfo(proc) |
|
4011.1.1
by John Arbash Meinel
Implement -Dmemory for win32 |
166 |
else: |
6138.3.4
by Jonathan Riddell
add gettext() to uses of trace.note() |
167 |
trace.note(gettext('Cannot debug memory on win32 without ctypes' |
168 |
' or win32process')) |
|
4011.1.1
by John Arbash Meinel
Implement -Dmemory for win32 |
169 |
return
|
4163.1.1
by John Arbash Meinel
Some small fixes for the win32 'trace.debug_mem()' code. |
170 |
if short: |
4989.1.6
by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used. |
171 |
# using base-2 units (see HACKING.txt).
|
6147.1.1
by Jonathan Riddell
use .format() instead of % for string formatting where there are multiple formats in one string to allow for translations |
172 |
trace.note(gettext('WorkingSize {0:>7}KiB' |
173 |
'\tPeakWorking {1:>7}KiB\t{2}').format( |
|
4163.1.1
by John Arbash Meinel
Some small fixes for the win32 'trace.debug_mem()' code. |
174 |
info['WorkingSetSize'] / 1024, |
175 |
info['PeakWorkingSetSize'] / 1024, |
|
6147.1.1
by Jonathan Riddell
use .format() instead of % for string formatting where there are multiple formats in one string to allow for translations |
176 |
message)) |
4163.1.1
by John Arbash Meinel
Some small fixes for the win32 'trace.debug_mem()' code. |
177 |
return
|
178 |
if message: |
|
179 |
trace.note('%s', message) |
|
6138.3.4
by Jonathan Riddell
add gettext() to uses of trace.note() |
180 |
trace.note(gettext('WorkingSize %8d KiB'), info['WorkingSetSize'] / 1024) |
181 |
trace.note(gettext('PeakWorking %8d KiB'), info['PeakWorkingSetSize'] / 1024) |
|
182 |
trace.note(gettext('PagefileUsage %8d KiB'), info.get('PagefileUsage', 0) / 1024) |
|
183 |
trace.note(gettext('PeakPagefileUsage %8d KiB'), |
|
4989.1.6
by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used. |
184 |
info.get('PeakPagefileUsage', 0) / 1024) |
6138.3.4
by Jonathan Riddell
add gettext() to uses of trace.note() |
185 |
trace.note(gettext('PrivateUsage %8d KiB'), info.get('PrivateUsage', 0) / 1024) |
186 |
trace.note(gettext('PageFaultCount %8d'), info.get('PageFaultCount', 0)) |
|
4011.1.1
by John Arbash Meinel
Implement -Dmemory for win32 |
187 |
|
188 |
||
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
189 |
def get_console_size(defaultx=80, defaulty=25): |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
190 |
"""Return size of current console.
|
191 |
||
192 |
This function try to determine actual size of current working
|
|
193 |
console window and return tuple (sizex, sizey) if success,
|
|
194 |
or default size (defaultx, defaulty) otherwise.
|
|
195 |
"""
|
|
196 |
if not has_ctypes: |
|
197 |
# no ctypes is found
|
|
198 |
return (defaultx, defaulty) |
|
199 |
||
200 |
# To avoid problem with redirecting output via pipe
|
|
4747.3.6
by Vincent Ladeuil
terminal_width can now returns None. |
201 |
# we need to use stderr instead of stdout
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
202 |
h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE) |
203 |
csbi = ctypes.create_string_buffer(22) |
|
204 |
res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) |
|
205 |
||
206 |
if res: |
|
207 |
(bufx, bufy, curx, cury, wattr, |
|
4989.1.6
by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used. |
208 |
left, top, right, bottom, maxx, maxy) = struct.unpack( |
209 |
"hhhhHhhhhhh", csbi.raw) |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
210 |
sizex = right - left + 1 |
211 |
sizey = bottom - top + 1 |
|
212 |
return (sizex, sizey) |
|
213 |
else: |
|
214 |
return (defaultx, defaulty) |
|
215 |
||
216 |
||
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
217 |
def _get_sh_special_folder_path(csidl): |
218 |
"""Call SHGetSpecialFolderPathW if available, or return None.
|
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
219 |
|
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
220 |
Result is always unicode (or None).
|
221 |
"""
|
|
222 |
if has_ctypes: |
|
223 |
try: |
|
224 |
SHGetSpecialFolderPath = \ |
|
225 |
ctypes.windll.shell32.SHGetSpecialFolderPathW |
|
226 |
except AttributeError: |
|
227 |
pass
|
|
228 |
else: |
|
229 |
buf = ctypes.create_unicode_buffer(MAX_PATH) |
|
230 |
if SHGetSpecialFolderPath(None,buf,csidl,0): |
|
231 |
return buf.value |
|
232 |
||
233 |
global has_win32com_shell |
|
234 |
if has_win32com_shell is None: |
|
235 |
try: |
|
236 |
from win32com.shell import shell |
|
237 |
has_win32com_shell = True |
|
238 |
except ImportError: |
|
239 |
has_win32com_shell = False |
|
240 |
if has_win32com_shell: |
|
241 |
# still need to bind the name locally, but this is fast.
|
|
242 |
from win32com.shell import shell |
|
243 |
try: |
|
244 |
return shell.SHGetSpecialFolderPath(0, csidl, 0) |
|
245 |
except shell.error: |
|
246 |
# possibly E_NOTIMPL meaning we can't load the function pointer,
|
|
247 |
# or E_FAIL meaning the function failed - regardless, just ignore it
|
|
248 |
pass
|
|
249 |
return None |
|
250 |
||
251 |
||
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
252 |
def get_appdata_location(): |
253 |
"""Return Application Data location.
|
|
254 |
Return None if we cannot obtain location.
|
|
255 |
||
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
256 |
Windows defines two 'Application Data' folders per user - a 'roaming'
|
257 |
one that moves with the user as they logon to different machines, and
|
|
258 |
a 'local' one that stays local to the machine. This returns the 'roaming'
|
|
259 |
directory, and thus is suitable for storing user-preferences, etc.
|
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
260 |
"""
|
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
261 |
appdata = _get_sh_special_folder_path(CSIDL_APPDATA) |
262 |
if appdata: |
|
263 |
return appdata |
|
6362.2.2
by Martin Packman
Use get_environ_unicode throughout win32utils and always return unicode paths |
264 |
# Use APPDATA if defined, will return None if not
|
265 |
return get_environ_unicode('APPDATA') |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
266 |
|
267 |
||
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
268 |
def get_local_appdata_location(): |
269 |
"""Return Local Application Data location.
|
|
270 |
Return the same as get_appdata_location() if we cannot obtain location.
|
|
271 |
||
272 |
Windows defines two 'Application Data' folders per user - a 'roaming'
|
|
273 |
one that moves with the user as they logon to different machines, and
|
|
274 |
a 'local' one that stays local to the machine. This returns the 'local'
|
|
275 |
directory, and thus is suitable for caches, temp files and other things
|
|
276 |
which don't need to move with the user.
|
|
277 |
"""
|
|
278 |
local = _get_sh_special_folder_path(CSIDL_LOCAL_APPDATA) |
|
279 |
if local: |
|
280 |
return local |
|
281 |
# Vista supplies LOCALAPPDATA, but XP and earlier do not.
|
|
6362.2.2
by Martin Packman
Use get_environ_unicode throughout win32utils and always return unicode paths |
282 |
local = get_environ_unicode('LOCALAPPDATA') |
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
283 |
if local: |
284 |
return local |
|
285 |
return get_appdata_location() |
|
286 |
||
287 |
||
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
288 |
def get_home_location(): |
289 |
"""Return user's home location.
|
|
290 |
Assume on win32 it's the <My Documents> folder.
|
|
291 |
If location cannot be obtained return system drive root,
|
|
292 |
i.e. C:\
|
|
293 |
"""
|
|
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
294 |
home = _get_sh_special_folder_path(CSIDL_PERSONAL) |
295 |
if home: |
|
296 |
return home |
|
6362.2.2
by Martin Packman
Use get_environ_unicode throughout win32utils and always return unicode paths |
297 |
home = get_environ_unicode('HOME') |
298 |
if home is not None: |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
299 |
return home |
6362.2.2
by Martin Packman
Use get_environ_unicode throughout win32utils and always return unicode paths |
300 |
homepath = get_environ_unicode('HOMEPATH') |
301 |
if homepath is not None: |
|
302 |
return os.path.join(get_environ_unicode('HOMEDIR', ''), home) |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
303 |
# at least return windows root directory
|
6362.2.2
by Martin Packman
Use get_environ_unicode throughout win32utils and always return unicode paths |
304 |
windir = get_environ_unicode('WINDIR') |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
305 |
if windir: |
2610.1.1
by Martin Pool
Fix get_home_location on Win98 (gzlist,r=john,r=alexander) |
306 |
return os.path.splitdrive(windir)[0] + '/' |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
307 |
# otherwise C:\ is good enough for 98% users
|
6362.2.2
by Martin Packman
Use get_environ_unicode throughout win32utils and always return unicode paths |
308 |
return unicode('C:/') |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
309 |
|
310 |
||
311 |
def get_user_name(): |
|
312 |
"""Return user name as login name.
|
|
313 |
If name cannot be obtained return None.
|
|
314 |
"""
|
|
315 |
if has_ctypes: |
|
316 |
try: |
|
317 |
advapi32 = ctypes.windll.advapi32 |
|
318 |
GetUserName = getattr(advapi32, 'GetUserName'+suffix) |
|
319 |
except AttributeError: |
|
320 |
pass
|
|
321 |
else: |
|
322 |
buf = create_buffer(UNLEN+1) |
|
323 |
n = ctypes.c_int(UNLEN+1) |
|
324 |
if GetUserName(buf, ctypes.byref(n)): |
|
6362.2.3
by Martin Packman
Always return username and hostname as unicode in win32utils |
325 |
return extract_buffer(buf) |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
326 |
# otherwise try env variables
|
6362.2.2
by Martin Packman
Use get_environ_unicode throughout win32utils and always return unicode paths |
327 |
return get_environ_unicode('USERNAME') |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
328 |
|
329 |
||
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
330 |
# 1 == ComputerNameDnsHostname, which returns "The DNS host name of the local
|
331 |
# computer or the cluster associated with the local computer."
|
|
332 |
_WIN32_ComputerNameDnsHostname = 1 |
|
333 |
||
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
334 |
def get_host_name(): |
335 |
"""Return host machine name.
|
|
336 |
If name cannot be obtained return None.
|
|
337 |
||
6362.2.3
by Martin Packman
Always return username and hostname as unicode in win32utils |
338 |
:return: A unicode string representing the host name.
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
339 |
"""
|
3626.1.2
by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars |
340 |
if has_win32api: |
341 |
try: |
|
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
342 |
return win32api.GetComputerNameEx(_WIN32_ComputerNameDnsHostname) |
3626.1.2
by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars |
343 |
except (NotImplementedError, win32api.error): |
344 |
# NotImplemented will happen on win9x...
|
|
345 |
pass
|
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
346 |
if has_ctypes: |
347 |
try: |
|
348 |
kernel32 = ctypes.windll.kernel32 |
|
349 |
except AttributeError: |
|
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
350 |
pass # Missing the module we need |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
351 |
else: |
352 |
buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1) |
|
353 |
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1) |
|
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
354 |
|
355 |
# Try GetComputerNameEx which gives a proper Unicode hostname
|
|
356 |
GetComputerNameEx = getattr(kernel32, 'GetComputerNameEx'+suffix, |
|
357 |
None) |
|
358 |
if (GetComputerNameEx is not None |
|
359 |
and GetComputerNameEx(_WIN32_ComputerNameDnsHostname, |
|
360 |
buf, ctypes.byref(n))): |
|
6362.2.3
by Martin Packman
Always return username and hostname as unicode in win32utils |
361 |
return extract_buffer(buf) |
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
362 |
|
363 |
# Try GetComputerName in case GetComputerNameEx wasn't found
|
|
364 |
# It returns the NETBIOS name, which isn't as good, but still ok.
|
|
365 |
# The first GetComputerNameEx might have changed 'n', so reset it
|
|
366 |
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1) |
|
367 |
GetComputerName = getattr(kernel32, 'GetComputerName'+suffix, |
|
368 |
None) |
|
369 |
if (GetComputerName is not None |
|
370 |
and GetComputerName(buf, ctypes.byref(n))): |
|
6362.2.3
by Martin Packman
Always return username and hostname as unicode in win32utils |
371 |
return extract_buffer(buf) |
6362.2.2
by Martin Packman
Use get_environ_unicode throughout win32utils and always return unicode paths |
372 |
return get_environ_unicode('COMPUTERNAME') |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
373 |
|
374 |
||
6362.4.1
by Martin Packman
Fix breakage from using wrong deprecation function |
375 |
@symbol_versioning.deprecated_function( |
6362.2.3
by Martin Packman
Always return username and hostname as unicode in win32utils |
376 |
symbol_versioning.deprecated_in((2, 5, 0))) |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
377 |
def _ensure_unicode(s): |
378 |
if s and type(s) != unicode: |
|
3788.1.1
by John Arbash Meinel
Fix a missing import |
379 |
from bzrlib import osutils |
3224.5.4
by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding. |
380 |
s = s.decode(osutils.get_user_encoding()) |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
381 |
return s |
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
382 |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
383 |
|
6362.4.1
by Martin Packman
Fix breakage from using wrong deprecation function |
384 |
get_appdata_location_unicode = symbol_versioning.deprecated_function( |
6362.2.2
by Martin Packman
Use get_environ_unicode throughout win32utils and always return unicode paths |
385 |
symbol_versioning.deprecated_in((2, 5, 0)))(get_appdata_location) |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
386 |
|
6362.4.1
by Martin Packman
Fix breakage from using wrong deprecation function |
387 |
get_home_location_unicode = symbol_versioning.deprecated_function( |
6362.2.2
by Martin Packman
Use get_environ_unicode throughout win32utils and always return unicode paths |
388 |
symbol_versioning.deprecated_in((2, 5, 0)))(get_home_location) |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
389 |
|
6362.4.1
by Martin Packman
Fix breakage from using wrong deprecation function |
390 |
get_user_name_unicode = symbol_versioning.deprecated_function( |
6362.2.3
by Martin Packman
Always return username and hostname as unicode in win32utils |
391 |
symbol_versioning.deprecated_in((2, 5, 0)))(get_user_name) |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
392 |
|
6362.4.1
by Martin Packman
Fix breakage from using wrong deprecation function |
393 |
get_host_name_unicode = symbol_versioning.deprecated_function( |
6362.2.3
by Martin Packman
Always return username and hostname as unicode in win32utils |
394 |
symbol_versioning.deprecated_in((2, 5, 0)))(get_host_name) |
2568.2.2
by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class |
395 |
|
396 |
||
2617.5.8
by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range |
397 |
def _ensure_with_dir(path): |
4989.1.6
by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used. |
398 |
if (not os.path.split(path)[0] or path.startswith(u'*') |
399 |
or path.startswith(u'?')): |
|
2617.5.8
by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range |
400 |
return u'./' + path, True |
401 |
else: |
|
402 |
return path, False |
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
403 |
|
2617.5.8
by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range |
404 |
def _undo_ensure_with_dir(path, corrected): |
405 |
if corrected: |
|
406 |
return path[2:] |
|
407 |
else: |
|
408 |
return path |
|
409 |
||
410 |
||
4786.1.2
by John Arbash Meinel
Refactor the glob_expand code a bit, making the inner function more reusable. |
411 |
def glob_one(possible_glob): |
412 |
"""Same as glob.glob().
|
|
413 |
||
414 |
work around bugs in glob.glob()
|
|
415 |
- Python bug #1001604 ("glob doesn't return unicode with ...")
|
|
416 |
- failing expansion for */* with non-iso-8859-* chars
|
|
417 |
"""
|
|
418 |
corrected_glob, corrected = _ensure_with_dir(possible_glob) |
|
419 |
glob_files = glob.glob(corrected_glob) |
|
420 |
||
421 |
if not glob_files: |
|
422 |
# special case to let the normal code path handle
|
|
423 |
# files that do not exist, etc.
|
|
424 |
glob_files = [possible_glob] |
|
425 |
elif corrected: |
|
426 |
glob_files = [_undo_ensure_with_dir(elem, corrected) |
|
427 |
for elem in glob_files] |
|
428 |
return [elem.replace(u'\\', u'/') for elem in glob_files] |
|
429 |
||
430 |
||
2598.3.1
by Kuno Meyer
fix method rename glob_expand_for_win32 -> win32utils.glob_expand |
431 |
def glob_expand(file_list): |
2568.2.2
by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class |
432 |
"""Replacement for glob expansion by the shell.
|
433 |
||
434 |
Win32's cmd.exe does not do glob expansion (eg ``*.py``), so we do our own
|
|
435 |
here.
|
|
436 |
||
437 |
:param file_list: A list of filenames which may include shell globs.
|
|
438 |
:return: An expanded list of filenames.
|
|
439 |
||
440 |
Introduced in bzrlib 0.18.
|
|
441 |
"""
|
|
442 |
if not file_list: |
|
443 |
return [] |
|
444 |
expanded_file_list = [] |
|
445 |
for possible_glob in file_list: |
|
4786.1.2
by John Arbash Meinel
Refactor the glob_expand code a bit, making the inner function more reusable. |
446 |
expanded_file_list.extend(glob_one(possible_glob)) |
447 |
return expanded_file_list |
|
2681.4.1
by Alexander Belchenko
win32: looking for full path of mail client executable in registry |
448 |
|
449 |
||
450 |
def get_app_path(appname): |
|
5891.1.2
by Andrew Bennetts
Fix a bunch of docstring formatting nits, making pydoctor a bit happier. |
451 |
r"""Look up in Windows registry for full path to application executable. |
4031.3.1
by Frank Aspell
Fixing various typos |
452 |
Typically, applications create subkey with their basename
|
2681.4.1
by Alexander Belchenko
win32: looking for full path of mail client executable in registry |
453 |
in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
|
454 |
||
455 |
:param appname: name of application (if no filename extension
|
|
456 |
is specified, .exe used)
|
|
457 |
:return: full path to aplication executable from registry,
|
|
458 |
or appname itself if nothing found.
|
|
459 |
"""
|
|
2681.4.3
by Alexander Belchenko
move import _winreg into function get_app_path to avoid ImportError on non-win32 platforms |
460 |
import _winreg |
4476.2.1
by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ). |
461 |
|
462 |
basename = appname |
|
463 |
if not os.path.splitext(basename)[1]: |
|
464 |
basename = appname + '.exe' |
|
465 |
||
2681.4.1
by Alexander Belchenko
win32: looking for full path of mail client executable in registry |
466 |
try: |
467 |
hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, |
|
4476.2.1
by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ). |
468 |
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\' + |
469 |
basename) |
|
2681.4.1
by Alexander Belchenko
win32: looking for full path of mail client executable in registry |
470 |
except EnvironmentError: |
471 |
return appname |
|
472 |
||
473 |
try: |
|
474 |
try: |
|
4476.2.1
by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ). |
475 |
path, type_id = _winreg.QueryValueEx(hkey, '') |
2681.4.1
by Alexander Belchenko
win32: looking for full path of mail client executable in registry |
476 |
except WindowsError: |
4476.2.1
by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ). |
477 |
return appname |
2681.4.1
by Alexander Belchenko
win32: looking for full path of mail client executable in registry |
478 |
finally: |
479 |
_winreg.CloseKey(hkey) |
|
480 |
||
4476.2.1
by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ). |
481 |
if type_id == REG_SZ: |
482 |
return path |
|
483 |
if type_id == REG_EXPAND_SZ and has_win32api: |
|
484 |
fullpath = win32api.ExpandEnvironmentStrings(path) |
|
4476.2.2
by Alexander Belchenko
remove quotes around value only if there is pair of quotes (igc review) |
485 |
if len(fullpath) > 1 and fullpath[0] == '"' and fullpath[-1] == '"': |
4476.2.1
by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ). |
486 |
fullpath = fullpath[1:-1] # remove quotes around value |
487 |
return fullpath |
|
488 |
return appname |
|
3023.1.2
by Alexander Belchenko
Martin's review. |
489 |
|
490 |
||
491 |
def set_file_attr_hidden(path): |
|
492 |
"""Set file attributes to hidden if possible"""
|
|
493 |
if has_win32file: |
|
4505.2.1
by Alexander Belchenko
Set hidden attribute on .bzr directory below unicode path should never fail with error. The operation should succeed even if bzr unable to set the attribute. (related to bug #335362). |
494 |
if winver != 'Windows 98': |
495 |
SetFileAttributes = win32file.SetFileAttributesW |
|
496 |
else: |
|
497 |
SetFileAttributes = win32file.SetFileAttributes |
|
498 |
try: |
|
499 |
SetFileAttributes(path, win32file.FILE_ATTRIBUTE_HIDDEN) |
|
500 |
except pywintypes.error, e: |
|
4505.2.2
by Alexander Belchenko
forgotten import |
501 |
from bzrlib import trace |
4505.2.1
by Alexander Belchenko
Set hidden attribute on .bzr directory below unicode path should never fail with error. The operation should succeed even if bzr unable to set the attribute. (related to bug #335362). |
502 |
trace.mutter('Unable to set hidden attribute on %r: %s', path, e) |
4355.2.1
by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments. |
503 |
|
504 |
||
5274.4.12
by Martin
Change interface of _command_line_to_argv so old tests can still be used with new stripping logic |
505 |
def _command_line_to_argv(command_line, argv, single_quotes_allowed=False): |
4913.5.2
by Gordon Tyler
Changed shlex_split_unicode to prevent wildcard expansion in the win32 codepath. |
506 |
"""Convert a Unicode command line into a list of argv arguments.
|
507 |
||
4913.5.25
by Gordon Tyler
Simplified win32utils.command_line_to_argv and made it private since it's no longer used outside of the module. |
508 |
It performs wildcard expansion to make wildcards act closer to how they
|
509 |
work in posix shells, versus how they work by default on Windows. Quoted
|
|
510 |
arguments are left untouched.
|
|
4913.5.2
by Gordon Tyler
Changed shlex_split_unicode to prevent wildcard expansion in the win32 codepath. |
511 |
|
512 |
:param command_line: The unicode string to split into an arg list.
|
|
4913.5.11
by Gordon Tyler
Added optional single quote support to UnicodeShlex and thus command_line_to_argv (defaults to disabled). |
513 |
:param single_quotes_allowed: Whether single quotes are accepted as quoting
|
514 |
characters like double quotes. False by
|
|
515 |
default.
|
|
4913.5.2
by Gordon Tyler
Changed shlex_split_unicode to prevent wildcard expansion in the win32 codepath. |
516 |
:return: A list of unicode strings.
|
4786.1.1
by John Arbash Meinel
Work on doing globbing, etc for all commands on Windows. |
517 |
"""
|
6437.65.1
by Scanferlato
Fix two typos in docs and comment |
518 |
# First, split the command line
|
4913.5.23
by Gordon Tyler
Renamed cmdline.Parser to Splitter to better match its usage. |
519 |
s = cmdline.Splitter(command_line, single_quotes_allowed=single_quotes_allowed) |
5274.4.1
by Jason Spashett
Initial Fix for 587868 |
520 |
|
5274.4.8
by Jason Spashett
Reverse merge -r 5280..5279 |
521 |
# Bug #587868 Now make sure that the length of s agrees with sys.argv
|
522 |
# we do this by simply counting the number of arguments in each. The counts should
|
|
523 |
# agree no matter what encoding sys.argv is in (AFAIK)
|
|
524 |
# len(arguments) < len(sys.argv) should be an impossibility since python gets
|
|
525 |
# args from the very same PEB as does GetCommandLineW
|
|
526 |
arguments = list(s) |
|
527 |
||
528 |
# Now shorten the command line we get from GetCommandLineW to match sys.argv
|
|
5274.4.12
by Martin
Change interface of _command_line_to_argv so old tests can still be used with new stripping logic |
529 |
if len(arguments) < len(argv): |
5274.4.11
by Martin
Minor cleanup, use plain AssertionError and revert needless variable rename |
530 |
raise AssertionError("Split command line can't be shorter than argv") |
5274.4.12
by Martin
Change interface of _command_line_to_argv so old tests can still be used with new stripping logic |
531 |
arguments = arguments[len(arguments) - len(argv):] |
5274.4.8
by Jason Spashett
Reverse merge -r 5280..5279 |
532 |
|
5274.4.2
by Jason Spashett
Tidied up fix for 587868. Put assert in for impossible case in command line lengths. |
533 |
# Carry on to process globs (metachars) in the command line
|
5274.4.1
by Jason Spashett
Initial Fix for 587868 |
534 |
# expand globs if necessary
|
4786.1.1
by John Arbash Meinel
Work on doing globbing, etc for all commands on Windows. |
535 |
# TODO: Use 'globbing' instead of 'glob.glob', this gives us stuff like
|
536 |
# '**/' style globs
|
|
5274.4.11
by Martin
Minor cleanup, use plain AssertionError and revert needless variable rename |
537 |
args = [] |
5274.4.8
by Jason Spashett
Reverse merge -r 5280..5279 |
538 |
for is_quoted, arg in arguments: |
4913.5.25
by Gordon Tyler
Simplified win32utils.command_line_to_argv and made it private since it's no longer used outside of the module. |
539 |
if is_quoted or not glob.has_magic(arg): |
5274.4.11
by Martin
Minor cleanup, use plain AssertionError and revert needless variable rename |
540 |
args.append(arg) |
4786.1.1
by John Arbash Meinel
Work on doing globbing, etc for all commands on Windows. |
541 |
else: |
5274.4.11
by Martin
Minor cleanup, use plain AssertionError and revert needless variable rename |
542 |
args.extend(glob_one(arg)) |
543 |
return args |
|
5274.4.3
by Jason Spashett
Merge from lp:bzr. Remove code for fix 588277 (revs 5274.3.1 - 5274.3.2) as this bug also fixes that issue. Make changes as per code review. |
544 |
|
4786.1.1
by John Arbash Meinel
Work on doing globbing, etc for all commands on Windows. |
545 |
|
6339.2.4
by Martin Packman
Bind name get_environ_unicode to None if function is unsupported |
546 |
if has_ctypes and winver == 'Windows NT': |
4355.2.1
by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments. |
547 |
def get_unicode_argv(): |
4913.5.15
by Gordon Tyler
Python < 2.6 doesn't support use_last_error. |
548 |
prototype = ctypes.WINFUNCTYPE(ctypes.c_wchar_p) |
4913.5.1
by Gordon Tyler
Changed shlex_split_unicode in commands.py to use win32utils.command_line_to_argv on win32 and cleaned up win32utils.get_unicode_argv. |
549 |
GetCommandLineW = prototype(("GetCommandLineW", |
550 |
ctypes.windll.kernel32)) |
|
551 |
command_line = GetCommandLineW() |
|
552 |
if command_line is None: |
|
553 |
raise ctypes.WinError() |
|
5274.4.8
by Jason Spashett
Reverse merge -r 5280..5279 |
554 |
# Skip the first argument, since we only care about parameters
|
5274.4.12
by Martin
Change interface of _command_line_to_argv so old tests can still be used with new stripping logic |
555 |
argv = _command_line_to_argv(command_line, sys.argv)[1:] |
4355.2.1
by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments. |
556 |
return argv |
6339.2.1
by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access |
557 |
|
558 |
||
6339.2.3
by Martin Packman
Remove ability to specify a maximum buffer size as it serves no particular purpose |
559 |
def get_environ_unicode(key, default=None): |
6339.2.1
by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access |
560 |
"""Get `key` from environment as unicode or `default` if unset
|
561 |
||
6362.2.5
by Martin Packman
Tweaks including those suggested by vila in review |
562 |
The environment is natively unicode on modern windows versions but
|
563 |
Python 2 only accesses it through the legacy bytestring api.
|
|
564 |
||
565 |
Environmental variable names are case insenstive on Windows.
|
|
566 |
||
6339.2.3
by Martin Packman
Remove ability to specify a maximum buffer size as it serves no particular purpose |
567 |
A large enough buffer will be allocated to retrieve the value, though
|
568 |
it may take two calls to the underlying library function.
|
|
6339.2.1
by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access |
569 |
|
570 |
This needs ctypes because pywin32 does not expose the wide version.
|
|
571 |
"""
|
|
6339.2.2
by Martin Packman
Variable name changes and docstring fix suggested by vila in review |
572 |
cfunc = getattr(get_environ_unicode, "_c_function", None) |
573 |
if cfunc is None: |
|
6339.2.1
by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access |
574 |
from ctypes.wintypes import DWORD, LPCWSTR, LPWSTR |
6339.2.2
by Martin Packman
Variable name changes and docstring fix suggested by vila in review |
575 |
cfunc = ctypes.WINFUNCTYPE(DWORD, LPCWSTR, LPWSTR, DWORD)( |
6339.2.1
by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access |
576 |
("GetEnvironmentVariableW", ctypes.windll.kernel32)) |
6339.2.2
by Martin Packman
Variable name changes and docstring fix suggested by vila in review |
577 |
get_environ_unicode._c_function = cfunc |
6339.2.3
by Martin Packman
Remove ability to specify a maximum buffer size as it serves no particular purpose |
578 |
buffer_size = 256 # heuristic, 256 characters often enough |
6339.2.1
by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access |
579 |
while True: |
580 |
buffer = ctypes.create_unicode_buffer(buffer_size) |
|
6339.2.2
by Martin Packman
Variable name changes and docstring fix suggested by vila in review |
581 |
length = cfunc(key, buffer, buffer_size) |
6339.2.1
by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access |
582 |
if not length: |
583 |
code = ctypes.GetLastError() |
|
584 |
if code == 203: # ERROR_ENVVAR_NOT_FOUND |
|
585 |
return default |
|
586 |
raise ctypes.WinError(code) |
|
587 |
if buffer_size > length: |
|
588 |
return buffer[:length] |
|
589 |
buffer_size = length |
|
4355.2.2
by Alexander Belchenko
osutils.py: get_unicode_argv function (to obtain unicode command line arguments from sys.argv) moved to the beginning of module based on suggestions from review of John Meinel. |
590 |
else: |
6362.2.1
by Martin Packman
Add path_from_environ function for getting unicode paths from envvars |
591 |
get_unicode_argv = None |
592 |
def get_environ_unicode(key, default=None): |
|
593 |
"""Get `key` from environment as unicode or `default` if unset
|
|
594 |
||
595 |
Fallback version that should basically never be needed.
|
|
596 |
"""
|
|
6362.2.7
by Martin Packman
Give in and use get_user_encoding() over 'mbcs' for fallback decoding so can test on nix |
597 |
from bzrlib import osutils |
6362.2.1
by Martin Packman
Add path_from_environ function for getting unicode paths from envvars |
598 |
try: |
6362.2.7
by Martin Packman
Give in and use get_user_encoding() over 'mbcs' for fallback decoding so can test on nix |
599 |
return os.environ[key].decode(osutils.get_user_encoding()) |
6362.2.1
by Martin Packman
Add path_from_environ function for getting unicode paths from envvars |
600 |
except KeyError: |
601 |
return default |
|
5425.5.5
by Martin
Quick implementation of dead process detection on win32 |
602 |
|
603 |
||
604 |
if has_win32api: |
|
605 |
def _pywin32_is_local_pid_dead(pid): |
|
606 |
"""True if pid doesn't correspond to live process on this machine"""
|
|
607 |
try: |
|
608 |
handle = win32api.OpenProcess(1, False, pid) # PROCESS_TERMINATE |
|
609 |
except pywintypes.error, e: |
|
5425.5.7
by Martin
Get the code for ERROR_ACCESS_DENIED right |
610 |
if e[0] == 5: # ERROR_ACCESS_DENIED |
5425.5.5
by Martin
Quick implementation of dead process detection on win32 |
611 |
# Probably something alive we're not allowed to kill
|
612 |
return False |
|
613 |
elif e[0] == 87: # ERROR_INVALID_PARAMETER |
|
614 |
return True |
|
615 |
raise
|
|
616 |
handle.close() |
|
617 |
return False |
|
618 |
is_local_pid_dead = _pywin32_is_local_pid_dead |
|
5425.4.29
by Martin Pool
Don't try to get ctypes access to OpenProcess on non-win32 platforms |
619 |
elif has_ctypes and sys.platform == 'win32': |
5425.5.5
by Martin
Quick implementation of dead process detection on win32 |
620 |
from ctypes.wintypes import BOOL, DWORD, HANDLE |
621 |
_kernel32 = ctypes.windll.kernel32 |
|
622 |
_CloseHandle = ctypes.WINFUNCTYPE(BOOL, HANDLE)( |
|
623 |
("CloseHandle", _kernel32)) |
|
624 |
_OpenProcess = ctypes.WINFUNCTYPE(HANDLE, DWORD, BOOL, DWORD)( |
|
625 |
("OpenProcess", _kernel32)) |
|
626 |
def _ctypes_is_local_pid_dead(pid): |
|
627 |
"""True if pid doesn't correspond to live process on this machine"""
|
|
628 |
handle = _OpenProcess(1, False, pid) # PROCESS_TERMINATE |
|
629 |
if not handle: |
|
630 |
errorcode = ctypes.GetLastError() |
|
5425.5.7
by Martin
Get the code for ERROR_ACCESS_DENIED right |
631 |
if errorcode == 5: # ERROR_ACCESS_DENIED |
5425.5.5
by Martin
Quick implementation of dead process detection on win32 |
632 |
# Probably something alive we're not allowed to kill
|
633 |
return False |
|
634 |
elif errorcode == 87: # ERROR_INVALID_PARAMETER |
|
635 |
return True |
|
636 |
raise ctypes.WinError(errorcode) |
|
637 |
_CloseHandle(handle) |
|
638 |
return False |
|
639 |
is_local_pid_dead = _ctypes_is_local_pid_dead |
|
6336.2.1
by Martin Packman
Add is_environment_error() and switch trace to using it |
640 |
|
641 |
||
642 |
def _is_pywintypes_error(evalue): |
|
6336.2.2
by Martin Packman
Tweak how pywin32 is imported in win32utils to fix test failure edge case |
643 |
"""True if exception instance is an error from pywin32"""
|
644 |
if has_pywintypes and isinstance(evalue, pywintypes.error): |
|
6336.2.1
by Martin Packman
Add is_environment_error() and switch trace to using it |
645 |
return True |
646 |
return False |