19
19
Only one dependency: ctypes should be installed.
22
from __future__ import absolute_import
27
from bzrlib import cmdline
30
if sys.platform == 'win32':
31
_major,_minor,_build,_platform,_text = sys.getwindowsversion()
34
# The operating system platform.
35
# This member can be one of the following values.
36
# ========================== ======================================
38
# -------------------------- --------------------------------------
39
# VER_PLATFORM_WIN32_NT The operating system is Windows Vista,
40
# 2 Windows Server "Longhorn",
41
# Windows Server 2003, Windows XP,
42
# Windows 2000, or Windows NT.
44
# VER_PLATFORM_WIN32_WINDOWS The operating system is Windows Me,
45
# 1 Windows 98, or Windows 95.
46
# ========================== ======================================
50
# don't care about real Windows name, just to force safe operations
33
from breezy.i18n import gettext
56
35
# We can cope without it; use a separate variable to help pyflakes
60
39
except ImportError:
63
if winver == 'Windows 98':
64
create_buffer = ctypes.create_string_buffer
67
create_buffer = ctypes.create_unicode_buffer
42
create_buffer = ctypes.create_unicode_buffer
43
extract_buffer = operator.attrgetter("value")
49
has_pywintypes = has_win32file = has_win32api = False
81
62
# pulling in win32com.shell is a bit of overhead, and normally we don't need
82
63
# it as ctypes is preferred and common. lazy_imports and "optional"
83
64
# modules don't work well, so we do our own lazy thing...
84
has_win32com_shell = None # Set to True or False once we know for sure...
65
has_win32com_shell = None # Set to True or False once we know for sure...
86
67
# Special Win32 API constants
87
68
# Handles of std streams
121
103
('PagefileUsage', ctypes.c_size_t),
122
104
('PeakPagefileUsage', ctypes.c_size_t),
123
105
('PrivateUsage', ctypes.c_size_t),
125
107
cur_process = ctypes.windll.kernel32.GetCurrentProcess()
126
108
mem_struct = PROCESS_MEMORY_COUNTERS_EX()
127
109
ret = ctypes.windll.psapi.GetProcessMemoryInfo(cur_process,
128
ctypes.byref(mem_struct),
129
ctypes.sizeof(mem_struct))
112
ctypes.sizeof(mem_struct))
131
trace.note('Failed to GetProcessMemoryInfo()')
114
trace.note(gettext('Failed to GetProcessMemoryInfo()'))
133
116
info = {'PageFaultCount': mem_struct.PageFaultCount,
134
117
'PeakWorkingSetSize': mem_struct.PeakWorkingSetSize,
149
132
proc = win32process.GetCurrentProcess()
150
133
info = win32process.GetProcessMemoryInfo(proc)
152
trace.note('Cannot debug memory on win32 without ctypes'
135
trace.note(gettext('Cannot debug memory on win32 without ctypes'
156
139
# using base-2 units (see HACKING.txt).
157
trace.note('WorkingSize %7dKiB'
158
'\tPeakWorking %7dKiB\t%s',
140
trace.note(gettext('WorkingSize {0:>7}KiB'
141
'\tPeakWorking {1:>7}KiB\t{2}').format(
159
142
info['WorkingSetSize'] / 1024,
160
143
info['PeakWorkingSetSize'] / 1024,
164
147
trace.note('%s', message)
165
trace.note('WorkingSize %8d KiB', info['WorkingSetSize'] / 1024)
166
trace.note('PeakWorking %8d KiB', info['PeakWorkingSetSize'] / 1024)
167
trace.note('PagefileUsage %8d KiB', info.get('PagefileUsage', 0) / 1024)
168
trace.note('PeakPagefileUsage %8d KiB',
148
trace.note(gettext('WorkingSize %8d KiB'),
149
info['WorkingSetSize'] / 1024)
150
trace.note(gettext('PeakWorking %8d KiB'),
151
info['PeakWorkingSetSize'] / 1024)
152
trace.note(gettext('PagefileUsage %8d KiB'),
153
info.get('PagefileUsage', 0) / 1024)
154
trace.note(gettext('PeakPagefileUsage %8d KiB'),
169
155
info.get('PeakPagefileUsage', 0) / 1024)
170
trace.note('PrivateUsage %8d KiB', info.get('PrivateUsage', 0) / 1024)
171
trace.note('PageFaultCount %8d', info.get('PageFaultCount', 0))
156
trace.note(gettext('PrivateUsage %8d KiB'),
157
info.get('PrivateUsage', 0) / 1024)
158
trace.note(gettext('PageFaultCount %8d'), info.get('PageFaultCount', 0))
174
161
def get_console_size(defaultx=80, defaulty=25):
242
229
one that moves with the user as they logon to different machines, and
243
230
a 'local' one that stays local to the machine. This returns the 'roaming'
244
231
directory, and thus is suitable for storing user-preferences, etc.
246
Returned value can be unicode or plain string.
247
To convert plain string to unicode use
248
s.decode(osutils.get_user_encoding())
249
(XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
251
233
appdata = _get_sh_special_folder_path(CSIDL_APPDATA)
255
appdata = os.environ.get('APPDATA')
258
# if we fall to this point we on win98
259
# at least try C:/WINDOWS/Application Data
260
windir = os.environ.get('windir')
262
appdata = os.path.join(windir, 'Application Data')
263
if os.path.isdir(appdata):
265
# did not find anything
236
# Use APPDATA if defined, will return None if not
237
return get_environ_unicode('APPDATA')
269
240
def get_local_appdata_location():
275
246
a 'local' one that stays local to the machine. This returns the 'local'
276
247
directory, and thus is suitable for caches, temp files and other things
277
248
which don't need to move with the user.
279
Returned value can be unicode or plain string.
280
To convert plain string to unicode use
281
s.decode(osutils.get_user_encoding())
282
(XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
284
250
local = _get_sh_special_folder_path(CSIDL_LOCAL_APPDATA)
287
253
# Vista supplies LOCALAPPDATA, but XP and earlier do not.
288
local = os.environ.get('LOCALAPPDATA')
254
local = get_environ_unicode('LOCALAPPDATA')
291
257
return get_appdata_location()
296
262
Assume on win32 it's the <My Documents> folder.
297
263
If location cannot be obtained return system drive root,
300
Returned value can be unicode or plain string.
301
To convert plain string to unicode use
302
s.decode(osutils.get_user_encoding())
304
266
home = _get_sh_special_folder_path(CSIDL_PERSONAL)
307
# try for HOME env variable
308
home = os.path.expanduser('~')
269
home = get_environ_unicode('HOME')
272
homepath = get_environ_unicode('HOMEPATH')
273
if homepath is not None:
274
return os.path.join(get_environ_unicode('HOMEDIR', ''), home)
311
275
# at least return windows root directory
312
windir = os.environ.get('windir')
276
windir = get_environ_unicode('WINDIR')
314
278
return os.path.splitdrive(windir)[0] + '/'
315
279
# otherwise C:\ is good enough for 98% users
319
283
def get_user_name():
320
284
"""Return user name as login name.
321
285
If name cannot be obtained return None.
323
Returned value can be unicode or plain string.
324
To convert plain string to unicode use
325
s.decode(osutils.get_user_encoding())
329
289
advapi32 = ctypes.windll.advapi32
330
GetUserName = getattr(advapi32, 'GetUserName'+suffix)
290
GetUserName = getattr(advapi32, 'GetUserName' + suffix)
331
291
except AttributeError:
334
buf = create_buffer(UNLEN+1)
335
n = ctypes.c_int(UNLEN+1)
294
buf = create_buffer(UNLEN + 1)
295
n = ctypes.c_int(UNLEN + 1)
336
296
if GetUserName(buf, ctypes.byref(n)):
297
return extract_buffer(buf)
338
298
# otherwise try env variables
339
return os.environ.get('USERNAME', None)
299
return get_environ_unicode('USERNAME')
342
302
# 1 == ComputerNameDnsHostname, which returns "The DNS host name of the local
343
303
# computer or the cluster associated with the local computer."
344
304
_WIN32_ComputerNameDnsHostname = 1
346
307
def get_host_name():
347
308
"""Return host machine name.
348
309
If name cannot be obtained return None.
350
:return: A unicode string representing the host name. On win98, this may be
351
a plain string as win32 api doesn't support unicode.
311
:return: A unicode string representing the host name.
361
321
kernel32 = ctypes.windll.kernel32
362
322
except AttributeError:
363
pass # Missing the module we need
323
pass # Missing the module we need
365
buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1)
366
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
325
buf = create_buffer(MAX_COMPUTERNAME_LENGTH + 1)
326
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH + 1)
368
328
# Try GetComputerNameEx which gives a proper Unicode hostname
369
GetComputerNameEx = getattr(kernel32, 'GetComputerNameEx'+suffix,
329
GetComputerNameEx = getattr(kernel32, 'GetComputerNameEx' + suffix,
371
331
if (GetComputerNameEx is not None
372
332
and GetComputerNameEx(_WIN32_ComputerNameDnsHostname,
373
buf, ctypes.byref(n))):
333
buf, ctypes.byref(n))):
334
return extract_buffer(buf)
376
336
# Try GetComputerName in case GetComputerNameEx wasn't found
377
337
# It returns the NETBIOS name, which isn't as good, but still ok.
378
338
# The first GetComputerNameEx might have changed 'n', so reset it
379
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
380
GetComputerName = getattr(kernel32, 'GetComputerName'+suffix,
339
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH + 1)
340
GetComputerName = getattr(kernel32, 'GetComputerName' + suffix,
382
342
if (GetComputerName is not None
383
and GetComputerName(buf, ctypes.byref(n))):
385
# otherwise try env variables, which will be 'mbcs' encoded
386
# on Windows (Python doesn't expose the native win32 unicode environment)
388
# http://msdn.microsoft.com/en-us/library/aa246807.aspx
389
# environment variables should always be encoded in 'mbcs'.
391
return os.environ['COMPUTERNAME'].decode("mbcs")
396
def _ensure_unicode(s):
397
if s and type(s) != unicode:
398
from bzrlib import osutils
399
s = s.decode(osutils.get_user_encoding())
403
def get_appdata_location_unicode():
404
return _ensure_unicode(get_appdata_location())
406
def get_home_location_unicode():
407
return _ensure_unicode(get_home_location())
409
def get_user_name_unicode():
410
return _ensure_unicode(get_user_name())
412
def get_host_name_unicode():
413
return _ensure_unicode(get_host_name())
343
and GetComputerName(buf, ctypes.byref(n))):
344
return extract_buffer(buf)
345
return get_environ_unicode('COMPUTERNAME')
416
348
def _ensure_with_dir(path):
417
349
if (not os.path.split(path)[0] or path.startswith(u'*')
418
or path.startswith(u'?')):
350
or path.startswith(u'?')):
419
351
return u'./' + path, True
421
353
return path, False
423
356
def _undo_ensure_with_dir(path, corrected):
511
443
def set_file_attr_hidden(path):
512
444
"""Set file attributes to hidden if possible"""
513
445
if has_win32file:
514
if winver != 'Windows 98':
515
SetFileAttributes = win32file.SetFileAttributesW
517
SetFileAttributes = win32file.SetFileAttributes
446
SetFileAttributes = win32file.SetFileAttributesW
519
448
SetFileAttributes(path, win32file.FILE_ATTRIBUTE_HIDDEN)
520
except pywintypes.error, e:
521
from bzrlib import trace
449
except pywintypes.error as e:
522
451
trace.mutter('Unable to set hidden attribute on %r: %s', path, e)
525
def _command_line_to_argv(command_line, single_quotes_allowed=False):
454
def _command_line_to_argv(command_line, argv, single_quotes_allowed=False):
526
455
"""Convert a Unicode command line into a list of argv arguments.
528
457
It performs wildcard expansion to make wildcards act closer to how they
536
465
:return: A list of unicode strings.
538
s = cmdline.Splitter(command_line, single_quotes_allowed=single_quotes_allowed)
539
# Now that we've split the content, expand globs if necessary
467
# First, split the command line
468
s = cmdline.Splitter(
469
command_line, single_quotes_allowed=single_quotes_allowed)
471
# Bug #587868 Now make sure that the length of s agrees with sys.argv
472
# we do this by simply counting the number of arguments in each. The counts should
473
# agree no matter what encoding sys.argv is in (AFAIK)
474
# len(arguments) < len(sys.argv) should be an impossibility since python gets
475
# args from the very same PEB as does GetCommandLineW
478
# Now shorten the command line we get from GetCommandLineW to match sys.argv
479
if len(arguments) < len(argv):
480
raise AssertionError("Split command line can't be shorter than argv")
481
arguments = arguments[len(arguments) - len(argv):]
483
# Carry on to process globs (metachars) in the command line
484
# expand globs if necessary
540
485
# TODO: Use 'globbing' instead of 'glob.glob', this gives us stuff like
541
486
# '**/' style globs
543
for is_quoted, arg in s:
488
for is_quoted, arg in arguments:
544
489
if is_quoted or not glob.has_magic(arg):
557
502
if command_line is None:
558
503
raise ctypes.WinError()
559
504
# Skip the first argument, since we only care about parameters
560
argv = _command_line_to_argv(command_line)[1:]
561
if getattr(sys, 'frozen', None) is None:
562
# Invoked via 'python.exe' which takes the form:
563
# python.exe [PYTHON_OPTIONS] C:\Path\bzr [BZR_OPTIONS]
564
# we need to get only BZR_OPTIONS part,
565
# We already removed 'python.exe' so we remove everything up to and
566
# including the first non-option ('-') argument.
567
for idx in xrange(len(argv)):
568
if argv[idx][:1] != '-':
505
argv = _command_line_to_argv(command_line, sys.argv)[1:]
573
get_unicode_argv = None
508
def get_environ_unicode(key, default=None):
509
"""Get `key` from environment as unicode or `default` if unset
511
The environment is natively unicode on modern windows versions but
512
Python 2 only accesses it through the legacy bytestring api.
514
Environmental variable names are case insenstive on Windows.
516
A large enough buffer will be allocated to retrieve the value, though
517
it may take two calls to the underlying library function.
519
This needs ctypes because pywin32 does not expose the wide version.
521
cfunc = getattr(get_environ_unicode, "_c_function", None)
523
from ctypes.wintypes import DWORD, LPCWSTR, LPWSTR
524
cfunc = ctypes.WINFUNCTYPE(DWORD, LPCWSTR, LPWSTR, DWORD)(
525
("GetEnvironmentVariableW", ctypes.windll.kernel32))
526
get_environ_unicode._c_function = cfunc
527
buffer_size = 256 # heuristic, 256 characters often enough
529
buffer = ctypes.create_unicode_buffer(buffer_size)
530
length = cfunc(key, buffer, buffer_size)
532
code = ctypes.GetLastError()
533
if code == 203: # ERROR_ENVVAR_NOT_FOUND
535
raise ctypes.WinError(code)
536
if buffer_size > length:
537
return buffer[:length]
542
def _pywin32_is_local_pid_dead(pid):
543
"""True if pid doesn't correspond to live process on this machine"""
545
handle = win32api.OpenProcess(1, False, pid) # PROCESS_TERMINATE
546
except pywintypes.error as e:
547
if e[0] == 5: # ERROR_ACCESS_DENIED
548
# Probably something alive we're not allowed to kill
550
elif e[0] == 87: # ERROR_INVALID_PARAMETER
555
is_local_pid_dead = _pywin32_is_local_pid_dead
556
elif has_ctypes and sys.platform == 'win32':
557
from ctypes.wintypes import BOOL, DWORD, HANDLE
558
_kernel32 = ctypes.windll.kernel32
559
_CloseHandle = ctypes.WINFUNCTYPE(BOOL, HANDLE)(
560
("CloseHandle", _kernel32))
561
_OpenProcess = ctypes.WINFUNCTYPE(HANDLE, DWORD, BOOL, DWORD)(
562
("OpenProcess", _kernel32))
564
def _ctypes_is_local_pid_dead(pid):
565
"""True if pid doesn't correspond to live process on this machine"""
566
handle = _OpenProcess(1, False, pid) # PROCESS_TERMINATE
568
errorcode = ctypes.GetLastError()
569
if errorcode == 5: # ERROR_ACCESS_DENIED
570
# Probably something alive we're not allowed to kill
572
elif errorcode == 87: # ERROR_INVALID_PARAMETER
574
raise ctypes.WinError(errorcode)
577
is_local_pid_dead = _ctypes_is_local_pid_dead
580
def _is_pywintypes_error(evalue):
581
"""True if exception instance is an error from pywin32"""
582
if has_pywintypes and isinstance(evalue, pywintypes.error):