2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
1 |
# Copyright (C) 2006, 2007 Canonical Ltd
|
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 |
||
22 |
import os |
|
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
23 |
import struct |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
24 |
import sys |
25 |
||
26 |
||
27 |
# Windows version
|
|
28 |
if sys.platform == 'win32': |
|
29 |
_major,_minor,_build,_platform,_text = sys.getwindowsversion() |
|
2245.4.11
by Alexander Belchenko
Small fixes after John's review; added NEWS entry |
30 |
# from MSDN:
|
31 |
# dwPlatformId
|
|
32 |
# The operating system platform.
|
|
33 |
# This member can be one of the following values.
|
|
34 |
# ========================== ======================================
|
|
35 |
# Value Meaning
|
|
36 |
# -------------------------- --------------------------------------
|
|
37 |
# VER_PLATFORM_WIN32_NT The operating system is Windows Vista,
|
|
38 |
# 2 Windows Server "Longhorn",
|
|
39 |
# Windows Server 2003, Windows XP,
|
|
40 |
# Windows 2000, or Windows NT.
|
|
41 |
#
|
|
42 |
# VER_PLATFORM_WIN32_WINDOWS The operating system is Windows Me,
|
|
43 |
# 1 Windows 98, or Windows 95.
|
|
44 |
# ========================== ======================================
|
|
45 |
if _platform == 2: |
|
46 |
winver = 'Windows NT' |
|
47 |
else: |
|
48 |
# 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 |
49 |
winver = 'Windows 98' |
50 |
else: |
|
51 |
winver = None |
|
52 |
||
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
53 |
|
1773.4.1
by Martin Pool
Add pyflakes makefile target; fix many warnings |
54 |
# 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 |
55 |
try: |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
56 |
import ctypes |
57 |
has_ctypes = True |
|
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
58 |
except ImportError: |
1773.4.1
by Martin Pool
Add pyflakes makefile target; fix many warnings |
59 |
has_ctypes = False |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
60 |
else: |
61 |
if winver == 'Windows 98': |
|
62 |
create_buffer = ctypes.create_string_buffer |
|
63 |
suffix = 'A' |
|
64 |
else: |
|
65 |
create_buffer = ctypes.create_unicode_buffer |
|
66 |
suffix = 'W' |
|
3023.1.2
by Alexander Belchenko
Martin's review. |
67 |
try: |
68 |
import win32file |
|
69 |
has_win32file = True |
|
70 |
except ImportError: |
|
71 |
has_win32file = False |
|
3626.1.2
by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars |
72 |
try: |
73 |
import win32api |
|
74 |
has_win32api = True |
|
75 |
except ImportError: |
|
76 |
has_win32api = False |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
77 |
|
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
78 |
# pulling in win32com.shell is a bit of overhead, and normally we don't need
|
79 |
# it as ctypes is preferred and common. lazy_imports and "optional"
|
|
80 |
# modules don't work well, so we do our own lazy thing...
|
|
81 |
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 |
82 |
|
83 |
# Special Win32 API constants
|
|
84 |
# Handles of std streams
|
|
1704.2.3
by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander) |
85 |
WIN32_STDIN_HANDLE = -10 |
86 |
WIN32_STDOUT_HANDLE = -11 |
|
87 |
WIN32_STDERR_HANDLE = -12 |
|
88 |
||
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
89 |
# CSIDL constants (from MSDN 2003)
|
90 |
CSIDL_APPDATA = 0x001A # Application Data folder |
|
3638.4.10
by Aaron Bentley
Correct spelling of 'Application Data' |
91 |
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 |
92 |
CSIDL_PERSONAL = 0x0005 # My Documents folder |
93 |
||
94 |
# from winapi C headers
|
|
95 |
MAX_PATH = 260 |
|
96 |
UNLEN = 256 |
|
97 |
MAX_COMPUTERNAME_LENGTH = 31 |
|
98 |
||
1704.2.3
by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander) |
99 |
|
4011.1.1
by John Arbash Meinel
Implement -Dmemory for win32 |
100 |
def debug_memory_win32api(message='', short=True): |
101 |
"""Use trace.note() to dump the running memory info."""
|
|
102 |
from bzrlib import trace |
|
4011.1.2
by John Arbash Meinel
Fix some small bugs, and prefer the ctypes form. |
103 |
if has_ctypes: |
4011.1.1
by John Arbash Meinel
Implement -Dmemory for win32 |
104 |
class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure): |
105 |
"""Used by GetProcessMemoryInfo"""
|
|
106 |
_fields_ = [('cb', ctypes.c_ulong), |
|
107 |
('PageFaultCount', ctypes.c_ulong), |
|
108 |
('PeakWorkingSetSize', ctypes.c_size_t), |
|
109 |
('WorkingSetSize', ctypes.c_size_t), |
|
110 |
('QuotaPeakPagedPoolUsage', ctypes.c_size_t), |
|
111 |
('QuotaPagedPoolUsage', ctypes.c_size_t), |
|
112 |
('QuotaPeakNonPagedPoolUsage', ctypes.c_size_t), |
|
113 |
('QuotaNonPagedPoolUsage', ctypes.c_size_t), |
|
114 |
('PagefileUsage', ctypes.c_size_t), |
|
115 |
('PeakPagefileUsage', ctypes.c_size_t), |
|
116 |
('PrivateUsage', ctypes.c_size_t), |
|
117 |
]
|
|
118 |
cur_process = ctypes.windll.kernel32.GetCurrentProcess() |
|
119 |
mem_struct = PROCESS_MEMORY_COUNTERS_EX() |
|
120 |
ret = ctypes.windll.psapi.GetProcessMemoryInfo(cur_process, |
|
121 |
ctypes.byref(mem_struct), |
|
122 |
ctypes.sizeof(mem_struct)) |
|
123 |
if not ret: |
|
124 |
trace.note('Failed to GetProcessMemoryInfo()') |
|
125 |
return
|
|
126 |
info = {'PageFaultCount': mem_struct.PageFaultCount, |
|
127 |
'PeakWorkingSetSize': mem_struct.PeakWorkingSetSize, |
|
128 |
'WorkingSetSize': mem_struct.WorkingSetSize, |
|
129 |
'QuotaPeakPagedPoolUsage': mem_struct.QuotaPeakPagedPoolUsage, |
|
130 |
'QuotaPagedPoolUsage': mem_struct.QuotaPagedPoolUsage, |
|
131 |
'QuotaPeakNonPagedPoolUsage': mem_struct.QuotaPeakNonPagedPoolUsage, |
|
132 |
'QuotaNonPagedPoolUsage': mem_struct.QuotaNonPagedPoolUsage, |
|
133 |
'PagefileUsage': mem_struct.PagefileUsage, |
|
134 |
'PeakPagefileUsage': mem_struct.PeakPagefileUsage, |
|
135 |
'PrivateUsage': mem_struct.PrivateUsage, |
|
136 |
}
|
|
4011.1.2
by John Arbash Meinel
Fix some small bugs, and prefer the ctypes form. |
137 |
elif has_win32api: |
138 |
import win32process |
|
139 |
# win32process does not return PrivateUsage, because it doesn't use
|
|
140 |
# PROCESS_MEMORY_COUNTERS_EX (it uses the one without _EX).
|
|
141 |
proc = win32process.GetCurrentProcess() |
|
142 |
info = win32process.GetProcessMemoryInfo(proc) |
|
4011.1.1
by John Arbash Meinel
Implement -Dmemory for win32 |
143 |
else: |
144 |
trace.note('Cannot debug memory on win32 without ctypes' |
|
145 |
' or win32process') |
|
146 |
return
|
|
4163.1.1
by John Arbash Meinel
Some small fixes for the win32 'trace.debug_mem()' code. |
147 |
if short: |
4163.1.2
by John Arbash Meinel
Merge bzr.dev, which changed kB => KB. |
148 |
trace.note('WorkingSize %7dKB' |
149 |
'\tPeakWorking %7dKB\t%s', |
|
4163.1.1
by John Arbash Meinel
Some small fixes for the win32 'trace.debug_mem()' code. |
150 |
info['WorkingSetSize'] / 1024, |
151 |
info['PeakWorkingSetSize'] / 1024, |
|
152 |
message) |
|
153 |
return
|
|
154 |
if message: |
|
155 |
trace.note('%s', message) |
|
4170.2.1
by Alexander Belchenko
Use KB not kB for 1024 bytes |
156 |
trace.note('WorkingSize %8d KB', info['WorkingSetSize'] / 1024) |
157 |
trace.note('PeakWorking %8d KB', info['PeakWorkingSetSize'] / 1024) |
|
158 |
trace.note('PagefileUsage %8d KB', info.get('PagefileUsage', 0) / 1024) |
|
159 |
trace.note('PeakPagefileUsage %8d KB', info.get('PeakPagefileUsage', 0) / 1024) |
|
160 |
trace.note('PrivateUsage %8d KB', info.get('PrivateUsage', 0) / 1024) |
|
4011.1.1
by John Arbash Meinel
Implement -Dmemory for win32 |
161 |
trace.note('PageFaultCount %8d', info.get('PageFaultCount', 0)) |
162 |
||
163 |
||
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
164 |
def get_console_size(defaultx=80, defaulty=25): |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
165 |
"""Return size of current console.
|
166 |
||
167 |
This function try to determine actual size of current working
|
|
168 |
console window and return tuple (sizex, sizey) if success,
|
|
169 |
or default size (defaultx, defaulty) otherwise.
|
|
170 |
"""
|
|
171 |
if not has_ctypes: |
|
172 |
# no ctypes is found
|
|
173 |
return (defaultx, defaulty) |
|
174 |
||
175 |
# To avoid problem with redirecting output via pipe
|
|
176 |
# need to use stderr instead of stdout
|
|
177 |
h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE) |
|
178 |
csbi = ctypes.create_string_buffer(22) |
|
179 |
res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) |
|
180 |
||
181 |
if res: |
|
182 |
(bufx, bufy, curx, cury, wattr, |
|
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
183 |
left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw) |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
184 |
sizex = right - left + 1 |
185 |
sizey = bottom - top + 1 |
|
186 |
return (sizex, sizey) |
|
187 |
else: |
|
188 |
return (defaultx, defaulty) |
|
189 |
||
190 |
||
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
191 |
def _get_sh_special_folder_path(csidl): |
192 |
"""Call SHGetSpecialFolderPathW if available, or return None.
|
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
193 |
|
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
194 |
Result is always unicode (or None).
|
195 |
"""
|
|
196 |
if has_ctypes: |
|
197 |
try: |
|
198 |
SHGetSpecialFolderPath = \ |
|
199 |
ctypes.windll.shell32.SHGetSpecialFolderPathW |
|
200 |
except AttributeError: |
|
201 |
pass
|
|
202 |
else: |
|
203 |
buf = ctypes.create_unicode_buffer(MAX_PATH) |
|
204 |
if SHGetSpecialFolderPath(None,buf,csidl,0): |
|
205 |
return buf.value |
|
206 |
||
207 |
global has_win32com_shell |
|
208 |
if has_win32com_shell is None: |
|
209 |
try: |
|
210 |
from win32com.shell import shell |
|
211 |
has_win32com_shell = True |
|
212 |
except ImportError: |
|
213 |
has_win32com_shell = False |
|
214 |
if has_win32com_shell: |
|
215 |
# still need to bind the name locally, but this is fast.
|
|
216 |
from win32com.shell import shell |
|
217 |
try: |
|
218 |
return shell.SHGetSpecialFolderPath(0, csidl, 0) |
|
219 |
except shell.error: |
|
220 |
# possibly E_NOTIMPL meaning we can't load the function pointer,
|
|
221 |
# or E_FAIL meaning the function failed - regardless, just ignore it
|
|
222 |
pass
|
|
223 |
return None |
|
224 |
||
225 |
||
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
226 |
def get_appdata_location(): |
227 |
"""Return Application Data location.
|
|
228 |
Return None if we cannot obtain location.
|
|
229 |
||
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
230 |
Windows defines two 'Application Data' folders per user - a 'roaming'
|
231 |
one that moves with the user as they logon to different machines, and
|
|
232 |
a 'local' one that stays local to the machine. This returns the 'roaming'
|
|
233 |
directory, and thus is suitable for storing user-preferences, etc.
|
|
234 |
||
235 |
Returned value can be unicode or plain string.
|
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
236 |
To convert plain string to unicode use
|
3224.5.4
by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding. |
237 |
s.decode(osutils.get_user_encoding())
|
3638.4.2
by Mark Hammond
Add a reference to bug 262874 noting 'mbcs' may be the correct encoding. |
238 |
(XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
239 |
"""
|
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
240 |
appdata = _get_sh_special_folder_path(CSIDL_APPDATA) |
241 |
if appdata: |
|
242 |
return appdata |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
243 |
# from env variable
|
244 |
appdata = os.environ.get('APPDATA') |
|
245 |
if appdata: |
|
246 |
return appdata |
|
247 |
# if we fall to this point we on win98
|
|
248 |
# at least try C:/WINDOWS/Application Data
|
|
249 |
windir = os.environ.get('windir') |
|
250 |
if windir: |
|
251 |
appdata = os.path.join(windir, 'Application Data') |
|
252 |
if os.path.isdir(appdata): |
|
253 |
return appdata |
|
254 |
# did not find anything
|
|
255 |
return None |
|
256 |
||
257 |
||
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
258 |
def get_local_appdata_location(): |
259 |
"""Return Local Application Data location.
|
|
260 |
Return the same as get_appdata_location() if we cannot obtain location.
|
|
261 |
||
262 |
Windows defines two 'Application Data' folders per user - a 'roaming'
|
|
263 |
one that moves with the user as they logon to different machines, and
|
|
264 |
a 'local' one that stays local to the machine. This returns the 'local'
|
|
265 |
directory, and thus is suitable for caches, temp files and other things
|
|
266 |
which don't need to move with the user.
|
|
267 |
||
268 |
Returned value can be unicode or plain string.
|
|
269 |
To convert plain string to unicode use
|
|
270 |
s.decode(bzrlib.user_encoding)
|
|
3638.4.2
by Mark Hammond
Add a reference to bug 262874 noting 'mbcs' may be the correct encoding. |
271 |
(XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
|
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
272 |
"""
|
273 |
local = _get_sh_special_folder_path(CSIDL_LOCAL_APPDATA) |
|
274 |
if local: |
|
275 |
return local |
|
276 |
# Vista supplies LOCALAPPDATA, but XP and earlier do not.
|
|
277 |
local = os.environ.get('LOCALAPPDATA') |
|
278 |
if local: |
|
279 |
return local |
|
280 |
return get_appdata_location() |
|
281 |
||
282 |
||
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
283 |
def get_home_location(): |
284 |
"""Return user's home location.
|
|
285 |
Assume on win32 it's the <My Documents> folder.
|
|
286 |
If location cannot be obtained return system drive root,
|
|
287 |
i.e. C:\
|
|
288 |
||
4031.3.1
by Frank Aspell
Fixing various typos |
289 |
Returned value can be unicode or plain string.
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
290 |
To convert plain string to unicode use
|
3224.5.4
by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding. |
291 |
s.decode(osutils.get_user_encoding())
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
292 |
"""
|
3638.4.1
by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can |
293 |
home = _get_sh_special_folder_path(CSIDL_PERSONAL) |
294 |
if home: |
|
295 |
return home |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
296 |
# try for HOME env variable
|
297 |
home = os.path.expanduser('~') |
|
298 |
if home != '~': |
|
299 |
return home |
|
300 |
# at least return windows root directory
|
|
301 |
windir = os.environ.get('windir') |
|
302 |
if windir: |
|
2610.1.1
by Martin Pool
Fix get_home_location on Win98 (gzlist,r=john,r=alexander) |
303 |
return os.path.splitdrive(windir)[0] + '/' |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
304 |
# otherwise C:\ is good enough for 98% users
|
305 |
return 'C:/' |
|
306 |
||
307 |
||
308 |
def get_user_name(): |
|
309 |
"""Return user name as login name.
|
|
310 |
If name cannot be obtained return None.
|
|
311 |
||
4031.3.1
by Frank Aspell
Fixing various typos |
312 |
Returned value can be unicode or plain string.
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
313 |
To convert plain string to unicode use
|
3224.5.4
by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding. |
314 |
s.decode(osutils.get_user_encoding())
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
315 |
"""
|
316 |
if has_ctypes: |
|
317 |
try: |
|
318 |
advapi32 = ctypes.windll.advapi32 |
|
319 |
GetUserName = getattr(advapi32, 'GetUserName'+suffix) |
|
320 |
except AttributeError: |
|
321 |
pass
|
|
322 |
else: |
|
323 |
buf = create_buffer(UNLEN+1) |
|
324 |
n = ctypes.c_int(UNLEN+1) |
|
325 |
if GetUserName(buf, ctypes.byref(n)): |
|
326 |
return buf.value |
|
327 |
# otherwise try env variables
|
|
328 |
return os.environ.get('USERNAME', None) |
|
329 |
||
330 |
||
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
331 |
# 1 == ComputerNameDnsHostname, which returns "The DNS host name of the local
|
332 |
# computer or the cluster associated with the local computer."
|
|
333 |
_WIN32_ComputerNameDnsHostname = 1 |
|
334 |
||
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
335 |
def get_host_name(): |
336 |
"""Return host machine name.
|
|
337 |
If name cannot be obtained return None.
|
|
338 |
||
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
339 |
:return: A unicode string representing the host name. On win98, this may be
|
340 |
a plain string as win32 api doesn't support unicode.
|
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
341 |
"""
|
3626.1.2
by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars |
342 |
if has_win32api: |
343 |
try: |
|
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
344 |
return win32api.GetComputerNameEx(_WIN32_ComputerNameDnsHostname) |
3626.1.2
by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars |
345 |
except (NotImplementedError, win32api.error): |
346 |
# NotImplemented will happen on win9x...
|
|
347 |
pass
|
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
348 |
if has_ctypes: |
349 |
try: |
|
350 |
kernel32 = ctypes.windll.kernel32 |
|
351 |
except AttributeError: |
|
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
352 |
pass # Missing the module we need |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
353 |
else: |
354 |
buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1) |
|
355 |
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1) |
|
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
356 |
|
357 |
# Try GetComputerNameEx which gives a proper Unicode hostname
|
|
358 |
GetComputerNameEx = getattr(kernel32, 'GetComputerNameEx'+suffix, |
|
359 |
None) |
|
360 |
if (GetComputerNameEx is not None |
|
361 |
and GetComputerNameEx(_WIN32_ComputerNameDnsHostname, |
|
362 |
buf, ctypes.byref(n))): |
|
363 |
return buf.value |
|
364 |
||
365 |
# Try GetComputerName in case GetComputerNameEx wasn't found
|
|
366 |
# It returns the NETBIOS name, which isn't as good, but still ok.
|
|
367 |
# The first GetComputerNameEx might have changed 'n', so reset it
|
|
368 |
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1) |
|
369 |
GetComputerName = getattr(kernel32, 'GetComputerName'+suffix, |
|
370 |
None) |
|
371 |
if (GetComputerName is not None |
|
372 |
and GetComputerName(buf, ctypes.byref(n))): |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
373 |
return buf.value |
3626.1.2
by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars |
374 |
# otherwise try env variables, which will be 'mbcs' encoded
|
375 |
# on Windows (Python doesn't expose the native win32 unicode environment)
|
|
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
376 |
# According to this:
|
377 |
# http://msdn.microsoft.com/en-us/library/aa246807.aspx
|
|
378 |
# environment variables should always be encoded in 'mbcs'.
|
|
3626.1.2
by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars |
379 |
try: |
380 |
return os.environ['COMPUTERNAME'].decode("mbcs") |
|
381 |
except KeyError: |
|
382 |
return None |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
383 |
|
384 |
||
385 |
def _ensure_unicode(s): |
|
3794.1.1
by Martin Pool
Update osutils imports to fix setup.py on Windows |
386 |
from bzrlib import osutils |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
387 |
if s and type(s) != unicode: |
3788.1.1
by John Arbash Meinel
Fix a missing import |
388 |
from bzrlib import osutils |
3224.5.4
by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding. |
389 |
s = s.decode(osutils.get_user_encoding()) |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
390 |
return s |
3626.1.3
by John Arbash Meinel
Use GetComputerNameEx from ctypes when available. |
391 |
|
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
392 |
|
393 |
def get_appdata_location_unicode(): |
|
394 |
return _ensure_unicode(get_appdata_location()) |
|
395 |
||
396 |
def get_home_location_unicode(): |
|
397 |
return _ensure_unicode(get_home_location()) |
|
398 |
||
399 |
def get_user_name_unicode(): |
|
400 |
return _ensure_unicode(get_user_name()) |
|
401 |
||
402 |
def get_host_name_unicode(): |
|
403 |
return _ensure_unicode(get_host_name()) |
|
2568.2.2
by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class |
404 |
|
405 |
||
2617.5.8
by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range |
406 |
def _ensure_with_dir(path): |
407 |
if not os.path.split(path)[0] or path.startswith(u'*') or path.startswith(u'?'): |
|
408 |
return u'./' + path, True |
|
409 |
else: |
|
410 |
return path, False |
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
411 |
|
2617.5.8
by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range |
412 |
def _undo_ensure_with_dir(path, corrected): |
413 |
if corrected: |
|
414 |
return path[2:] |
|
415 |
else: |
|
416 |
return path |
|
417 |
||
418 |
||
419 |
||
2598.3.1
by Kuno Meyer
fix method rename glob_expand_for_win32 -> win32utils.glob_expand |
420 |
def glob_expand(file_list): |
2568.2.2
by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class |
421 |
"""Replacement for glob expansion by the shell.
|
422 |
||
423 |
Win32's cmd.exe does not do glob expansion (eg ``*.py``), so we do our own
|
|
424 |
here.
|
|
425 |
||
426 |
:param file_list: A list of filenames which may include shell globs.
|
|
427 |
:return: An expanded list of filenames.
|
|
428 |
||
429 |
Introduced in bzrlib 0.18.
|
|
430 |
"""
|
|
431 |
if not file_list: |
|
432 |
return [] |
|
433 |
import glob |
|
434 |
expanded_file_list = [] |
|
435 |
for possible_glob in file_list: |
|
2617.5.8
by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range |
436 |
# work around bugs in glob.glob()
|
437 |
# - Python bug #1001604 ("glob doesn't return unicode with ...")
|
|
438 |
# - failing expansion for */* with non-iso-8859-* chars
|
|
439 |
possible_glob, corrected = _ensure_with_dir(possible_glob) |
|
2568.2.2
by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class |
440 |
glob_files = glob.glob(possible_glob) |
441 |
||
442 |
if glob_files == []: |
|
443 |
# special case to let the normal code path handle
|
|
444 |
# files that do not exists
|
|
2617.5.8
by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range |
445 |
expanded_file_list.append( |
446 |
_undo_ensure_with_dir(possible_glob, corrected)) |
|
2568.2.2
by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class |
447 |
else: |
2617.5.8
by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range |
448 |
glob_files = [_undo_ensure_with_dir(elem, corrected) for elem in glob_files] |
2568.2.2
by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class |
449 |
expanded_file_list += glob_files |
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
450 |
|
451 |
return [elem.replace(u'\\', u'/') for elem in expanded_file_list] |
|
2681.4.1
by Alexander Belchenko
win32: looking for full path of mail client executable in registry |
452 |
|
453 |
||
454 |
def get_app_path(appname): |
|
455 |
"""Look up in Windows registry for full path to application executable.
|
|
4031.3.1
by Frank Aspell
Fixing various typos |
456 |
Typically, applications create subkey with their basename
|
2681.4.1
by Alexander Belchenko
win32: looking for full path of mail client executable in registry |
457 |
in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
|
458 |
||
459 |
:param appname: name of application (if no filename extension
|
|
460 |
is specified, .exe used)
|
|
461 |
:return: full path to aplication executable from registry,
|
|
462 |
or appname itself if nothing found.
|
|
463 |
"""
|
|
2681.4.3
by Alexander Belchenko
move import _winreg into function get_app_path to avoid ImportError on non-win32 platforms |
464 |
import _winreg |
2681.4.1
by Alexander Belchenko
win32: looking for full path of mail client executable in registry |
465 |
try: |
466 |
hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, |
|
467 |
r'SOFTWARE\Microsoft\Windows' |
|
468 |
r'\CurrentVersion\App Paths') |
|
469 |
except EnvironmentError: |
|
470 |
return appname |
|
471 |
||
472 |
basename = appname |
|
473 |
if not os.path.splitext(basename)[1]: |
|
474 |
basename = appname + '.exe' |
|
475 |
try: |
|
476 |
try: |
|
477 |
fullpath = _winreg.QueryValue(hkey, basename) |
|
478 |
except WindowsError: |
|
479 |
fullpath = appname |
|
480 |
finally: |
|
481 |
_winreg.CloseKey(hkey) |
|
482 |
||
483 |
return fullpath |
|
3023.1.2
by Alexander Belchenko
Martin's review. |
484 |
|
485 |
||
486 |
def set_file_attr_hidden(path): |
|
487 |
"""Set file attributes to hidden if possible"""
|
|
488 |
if has_win32file: |
|
489 |
win32file.SetFileAttributes(path, win32file.FILE_ATTRIBUTE_HIDDEN) |
|
4355.2.1
by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments. |
490 |
|
491 |
||
492 |
if has_ctypes and winver != 'Windows 98': |
|
493 |
def get_unicode_argv(): |
|
494 |
LPCWSTR = ctypes.c_wchar_p |
|
495 |
INT = ctypes.c_int |
|
496 |
POINTER = ctypes.POINTER |
|
497 |
prototype = ctypes.WINFUNCTYPE(LPCWSTR) |
|
498 |
GetCommandLine = prototype(("GetCommandLineW", |
|
499 |
ctypes.windll.kernel32)) |
|
500 |
prototype = ctypes.WINFUNCTYPE(POINTER(LPCWSTR), LPCWSTR, POINTER(INT)) |
|
501 |
CommandLineToArgv = prototype(("CommandLineToArgvW", |
|
502 |
ctypes.windll.shell32)) |
|
503 |
c = INT(0) |
|
504 |
pargv = CommandLineToArgv(GetCommandLine(), ctypes.byref(c)) |
|
4355.2.4
by Alexander Belchenko
win32utils.py: get_unicode_argv: get bzr options as tail of argv list based on the number of items in sys.argv[1:] list. |
505 |
# Skip the first argument, since we only care about parameters
|
4355.2.1
by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments. |
506 |
argv = [pargv[i] for i in range(1, c.value)] |
507 |
if getattr(sys, 'frozen', None) is None: |
|
4355.2.4
by Alexander Belchenko
win32utils.py: get_unicode_argv: get bzr options as tail of argv list based on the number of items in sys.argv[1:] list. |
508 |
# Invoked via 'python.exe' which takes the form:
|
509 |
# python.exe [PYTHON_OPTIONS] C:\Path\bzr [BZR_OPTIONS]
|
|
510 |
# we need to get only BZR_OPTIONS part,
|
|
4355.2.5
by Alexander Belchenko
improve comment |
511 |
# so let's using sys.argv[1:] as reference to get the tail
|
512 |
# of unicode argv
|
|
4355.2.4
by Alexander Belchenko
win32utils.py: get_unicode_argv: get bzr options as tail of argv list based on the number of items in sys.argv[1:] list. |
513 |
tail_len = len(sys.argv[1:]) |
514 |
ix = len(argv) - tail_len |
|
515 |
argv = argv[ix:] |
|
4355.2.1
by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments. |
516 |
return argv |
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. |
517 |
else: |
518 |
get_unicode_argv = None |